搜索
bottom↓
回复: 331

【原创】最高效率使用单片机,放弃程序中的延时函数

  [复制链接]

出0入0汤圆

发表于 2010-10-9 15:04:47 | 显示全部楼层 |阅读模式
我是PC机底层编程转过来的,以前从来没接触过单片机,五个月前学习AVR,在这里学到很多东西。但也意识到电子工程师们的硬件编程思想与PC机底层编程思想上的很多不同,引发了一些思考。我说一说,供大家参考,只为学习,无意争论。

我第一次看到教程里Delay()函数的代码时我吓了一跳,竟然让单片机空转以实现和外界同步,这怎么可能?
试想,如果PC机CPU空转一秒,那么音乐会断一秒、画面会停顿一秒、下载文件会断一秒,这怎么可行?

我看到很多单片机程序,它们的单片机99.9%的工作时间都在打空转,99.9%大家可能感到有些危言耸听,那就让我们算一算:

已内部8M频的AVR单片机来说,单指令周期仅为1/8 = 0.125us,那一毫秒可以执行多少个单周期指令? 1%0.125*1000 = 8000个

而我看到论坛里下到的绝大多数程序,两个延时函数之间代码的执行时间要远远小于8000个指令周期。
说实话,很多16K以上的程序,把所有延时函数去掉,总体能执行几毫秒就不错了。

换句话说,我说单片机的利用率小于0.01%还是口下留情了。

要说怎么解决问题,就要先找到问题,我问问大家,程序中,我们为什么延时?

原因很多,可能是外设速度太慢,也可能是为了躲过人眼视觉停留时间,等等。
总之就是与外界不同步,而我们想要同步。

所以说这些延时应该是很有道理的,我不否定这一点,但问题的关键这些延时空转,我们为什么不能把这些时间回收起来做一些别的事呢?
试想,如果把这99.9%的时间回收,那可以一笔相当巨大的资源。

有很多人有些特殊方法回收过这些空转时间,比如说在延时函数中做点事。

但这些往往都不通用,下面我说一些我的两种方法:




1、前后台模式下延时时间回收的方法:

前后台模式就是大家最常用的主程序大循环 + 中断的模式。

首先解决外设太慢问题,像串口、键盘、LCD、SD卡等IO,这些收发可以建立外部缓冲区。比如串口收发在中断中完成保存到缓冲区,而主程序操作缓冲区而不直接操纵串口,这已经看到很多人这样用了。但像矩阵键盘的缓冲区,我很少看到有人这么用,在中断中接收按键信息保存到缓冲区。
还有像LCD,我们一个个往显存中写数据是很浪费的,也应该建立缓冲,统一处理。

建立缓冲区这类方式中间有一些技术难点,比如像串口接收,无法判断对发是否全部发完,怎么办?可以设立定时,如果一个字节接收之后1ms之内没收到下一个,则认为接收完毕。这只是一个思想,具体应用大家掌握。

可能有人会说,除了外设太慢,还有像视觉停留的问题怎么解决,总不能让流水灯快到人眼都看不清吧。
这就我下面要说的问题,这些延时的时间怎么回收?就是全部放到定时中断中!

可能又有些人会说,书里、教程都说了,中断处理东西的时间要尽量短,你这样整个中断有太多判断、很长,时间很长,这不行。

这是一种教条的思想,把书读死了。可以在中断中这样处理,比如:

void (*Task)(void);
ISR
{
      (*Task)(void);
}

中断里用的内容通过函数指针来调用,这样可以在主程序根据需要时任意改变要执行的任务,还可以改任务的周期。所用的判断都是在主程序需中执行,然后改变指针的指向,来确定中断中下一步的任务。

这样,在前后台系统中主程序将任务分配完,还有很多余力处理很多事。

比如有很多个键盘、LED点阵、数码管等,它们都需要实时响应,很容造成编程困难、响应迟钝,其实只要把延时的时间回收,处理这些就非常从容了。

可能还有人会说,有些项目用不了这么苛刻的时间,你回收的时间用不了,要那么多干嘛?
其实这时,你就可以用死循环扫描事件,可以实时响应。你的系统跟原来空循环延时比,实时性要高了不知多少倍。




2、变异的协作式内核

先说说嵌入式操作系统的内核,简单的说,它就是个任务调度器,让多个任务在同一个CPU上同时执行,所谓同时也是相对的,无非就第一个任务执行几毫秒、第二个任务在执行几毫秒。。。外表看起来就是同时执行。

至于可剥夺式内核和协作式内核的区别,大家可以百度一下。

说道能在单片机上用的嵌入式操作系统,大家会说出一些如uCosII、FreeOS等操作系统。
还有很多人对这些操作系统十分抗拒、十分反对,他们的理由是什么?

1、这些操作系统占用大量RAM、ROM
2、这些实时操作系统所谓的实时是相对非实时操作系统的,跟裸机比实际上是慢了

这些理由不是没道理,因为这些商用操作系统都是可剥夺式内核,它们的原则是保证最高优先级任务在可确定的时间内响应。
它们的有优点是任务切换时间是确定的,不会随任务的多少而改变。
有了这些确定性,让它们在商用产品大放光彩。因为其时间稳定性。

但它们的缺点也很明显,中断级节拍浪费很多时间。任务间同时调用时引发同步问题而引入许多如信号量、邮箱等机制浪费大量RAM、ROM。

综上,可剥夺式内核稳定可定量,在越高级的单片机上越有优势,在8位机上可用,但需要大量裁剪,并不一定合适。



而协作式内核的核心思想是什么?它不像剥夺式内核保证最高级任务速度最快,而是保证所有任务的平均速度最快!

正如我前面的说法,我连续两个延时函数之间的代码很难超过1ms,甚至很难超过100us,我们可以将其忽略。这样10个任务,第一个执行完主动放弃单片机控制权,交给第二个任务,第二个任务执行完主动放弃控制权,交给第三个任务。10个任务之间无间隙,每一个任务需要延时时,就主动放弃控制权。

基于这种思想,我们的就达到了回收空转延时的目的,而且应为每个任务是执行完后主动放弃,所以不存在剥夺式内核的同步问题,基本不需要邮箱、信号量等机制,对RAM、ROM的要求就非常低了。

这样来看,协作式内核非常适合8位机。但可能有太多嵌入式系统的书中对剥夺式内核不分场合的认可,造成很多人误解。而且uCos等系统的权威,也让很多RTOS作者争相效仿,没用对8位机的场合做合理分析。

商用系统中没有协作式内核,而民用的,还少有优秀的协作式内核,都是基于传统节拍。

传统协作式内核需要定时中断为时钟基准,也会间歇性打断任务,造成不必要的损失,这并不是我们想要的。

我们其实可以仅仅是让定时器以大分频系数开着, 而不给其产生中断的机会。当任务将要放弃使用权时,读取定时器,作为时钟基准,然后清零。

做法一句两句说不清,而效果是什么?可以做到任务是以不受干扰,与裸机相同的工作状态,这是传统协作式内核做不到的,而仅当它需要延时了,才放弃使用权,将延时的时间给其它任务。这正符合我全文的目的 -- 回收空转延时时间

这样的内核体积会非常小,运行方式与裸机无异,仅仅是把空转延时时间干些其它事。对使用者还没什么要求,不想以往系统那么复杂。

可惜市面上并没有基于这种方式的内核,我已经写了一个,非常精简,运行稳定。但作为一个想应用实际的内核,还需要检验。我最后检查一下后,过几天拿出来大家一起分享。




PS:好了,我上面两种方式,均为原创。希望能对大家有帮助~ 第二种中介绍的变异协作式内核思想很简单,有兴趣可以自己写一个,我过几天会把我的发上来。

出0入0汤圆

发表于 2010-10-9 15:07:11 | 显示全部楼层
好,期待

出0入0汤圆

发表于 2010-10-9 15:14:50 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-9 15:17:42 | 显示全部楼层
先markkkkk

出0入0汤圆

发表于 2010-10-9 15:24:02 | 显示全部楼层
等等看。。MARK

出0入0汤圆

发表于 2010-10-9 16:20:38 | 显示全部楼层
看完了,不错。可以留个qq吗?想交流一下。我469356814

出0入0汤圆

发表于 2010-10-9 16:30:53 | 显示全部楼层
板凳

出0入0汤圆

 楼主| 发表于 2010-10-9 16:34:50 | 显示全部楼层
回复【6楼】d20062303732 lin
-----------------------------------------------------------------------

从不上Q啊~邮箱yrloy@live.cn,一起交流

出0入0汤圆

发表于 2010-10-9 16:44:30 | 显示全部楼层
等楼主的连载

出0入0汤圆

发表于 2010-10-9 16:53:59 | 显示全部楼层
有点意思,MARK,期待中...

出0入0汤圆

发表于 2010-10-9 17:03:26 | 显示全部楼层
厉害

出0入0汤圆

发表于 2010-10-9 17:07:41 | 显示全部楼层
恩,不错,mark
不过做的都是低要求的小项目,几个中断或者干脆查询方式就都解决了哎

出0入264汤圆

发表于 2010-10-9 17:16:30 | 显示全部楼层
对第二种方式感兴趣。

出0入0汤圆

 楼主| 发表于 2010-10-9 17:19:26 | 显示全部楼层
回复【12楼】cbeeee
恩,不错,mark
不过做的都是低要求的小项目,几个中断或者干脆查询方式就都解决了哎
-----------------------------------------------------------------------

嗯,但这些小项目中我们每一个都要用不同的方法来安排结构。如果找出通用的方法,下次在做其它项目,只要分清任务中的主次就可以变成简单的几个程序,不用设计结构,降低工作量~

正像uCos作者所说,用惯了多任务系统的人,绝不愿回到裸机状态。可惜uCos过于庞大,AVR系列只有SRAM 2K以上的单片机勉强可用。
而文中提到的内核在51上都可以流畅运行,与裸机无异。

出0入0汤圆

发表于 2010-10-9 17:19:58 | 显示全部楼层
对于第二种方式在实际应用中的可行性,仍需要多次验证才可知晓

出0入0汤圆

发表于 2010-10-9 17:22:21 | 显示全部楼层
呵呵,期待啊。中断用指针的方法,和ARM的中断有点像啊,这样处理数据也需要入栈的吧?

出0入0汤圆

发表于 2010-10-9 17:25:43 | 显示全部楼层
Contiki应该和LZ的东西有较强相关性。不妨参考一下。

出0入0汤圆

发表于 2010-10-9 17:26:15 | 显示全部楼层
观望中 .....

出0入0汤圆

发表于 2010-10-9 17:27:30 | 显示全部楼层
写的不错。

出0入8汤圆

发表于 2010-10-9 17:28:49 | 显示全部楼层
记号

出0入0汤圆

发表于 2010-10-9 17:29:07 | 显示全部楼层
回复【16楼】astankvai 陈超
呵呵,期待啊。中断用指针的方法,和arm的中断有点像啊,这样处理数据也需要入栈的吧?
-----------------------------------------------------------------------

这样做相当于写一个os了

出0入0汤圆

 楼主| 发表于 2010-10-9 17:29:43 | 显示全部楼层
回复【16楼】astankvai 陈超
呵呵,期待啊。中断用指针的方法,和arm的中断有点像啊,这样处理数据也需要入栈的吧?
-----------------------------------------------------------------------

这些我们不用理会,中断前后保护现场的工作是编译器的事,没问题的。


回复【15楼】zhousfe 敏—感—词工
对于第二种方式在实际应用中的可行性,仍需要多次验证才可知晓
-----------------------------------------------------------------------

第二种方案我刚刚写完,我用四个不同频率、不同图案的流水灯在Mega16上运行12小时,时间误差极小,继续运行,长期运行的检测基本没偶然错误。

我有用键盘、两个4位数码管实验,键盘响应非常及时,数码管亮度稳定均匀,暂没发现问题,继续运行

出0入0汤圆

 楼主| 发表于 2010-10-9 17:31:04 | 显示全部楼层
回复【21楼】biansf2001 花溅泪
回复【16楼】astankvai 陈超
呵呵,期待啊。中断用指针的方法,和arm的中断有点像啊,这样处理数据也需要入栈的吧?
-----------------------------------------------------------------------
这样做相当于写一个os了
-----------------------------------------------------------------------

呵呵,我可写不了OS,没有文件系统、GUI系统,这个最多是个新鲜的OS内核

出0入0汤圆

发表于 2010-10-9 17:33:56 | 显示全部楼层
MARK

出0入0汤圆

发表于 2010-10-9 17:34:10 | 显示全部楼层
感觉没什么太大必要放弃延时
毕竟单片机和PC针对的应用不一样
用AVR来播放MP3的时候,估计没人会加延时

出0入0汤圆

发表于 2010-10-9 17:41:07 | 显示全部楼层
mark
期待继续!

出0入0汤圆

 楼主| 发表于 2010-10-9 17:45:10 | 显示全部楼层
回复【25楼】ldqmoon
感觉没什么太大必要放弃延时
毕竟单片机和pc针对的应用不一样
用avr来播放mp3的时候,估计没人会加延时
-----------------------------------------------------------------------

我的意思是指放弃空转的延时,在延时的时候,能有效的做其它的事情,等延时完毕,在回到原位继续执行~

出0入0汤圆

发表于 2010-10-9 18:07:16 | 显示全部楼层
楼主提的问题其实我也曾想过,也想花时间攻读OS代码~可没有坚持下来,看来解决问题是必须的了。坚持啊坚持

出0入0汤圆

 楼主| 发表于 2010-10-9 19:52:26 | 显示全部楼层
回复【28楼】huwenhui
-----------------------------------------------------------------------

其实内核任务调度部分代码绝不超过100行,并不难。而其它部分可以这么来学,就是我如果是系统的作者,我需要让系统有什么功能。想到之后,找找就找到了,真有类似的功能。然后再读就简单了~

出0入0汤圆

发表于 2010-10-9 20:26:48 | 显示全部楼层
写的不错!

出0入0汤圆

发表于 2010-10-9 20:37:05 | 显示全部楼层
加油,等看后文。

这种说法是错误的,当然作者为了起个吸引人的标题,可以理解。

出0入0汤圆

发表于 2010-10-9 20:50:35 | 显示全部楼层
期待

出0入0汤圆

发表于 2010-10-9 20:51:22 | 显示全部楼层
所以说有了TimerTick这东西。在扫描键盘的时候非常有用。

出5入8汤圆

发表于 2010-10-9 20:57:23 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-9 20:59:52 | 显示全部楼层
MARK 期待

出0入0汤圆

发表于 2010-10-9 21:00:43 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-9 21:11:08 | 显示全部楼层
支持一下。。。

出0入0汤圆

发表于 2010-10-9 21:19:22 | 显示全部楼层
操作系统的思想。即便不等待。你能确定程序做的都是有意义的事情???

出0入0汤圆

发表于 2010-10-9 21:34:09 | 显示全部楼层
关注

出0入0汤圆

发表于 2010-10-9 21:39:06 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-9 21:40:52 | 显示全部楼层

出0入0汤圆

发表于 2010-10-9 21:50:42 | 显示全部楼层
好铁啊,等待你的下文
理解很透彻

出0入0汤圆

发表于 2010-10-9 21:54:52 | 显示全部楼层
不用大吃一惊吧。pc的cpu使用率有多少?回收时间?回收给系统还是储存起来?单片机多是实时处理由挂起到恢复要多久?很多时候数据已经过去了或者说丢失了回收那有何用?微软为win的强大牺牲了多少硬件性能。当然随着硬件的更新换代这种中断、切换、甚至睡眠挂起以代替空转是大势所趋。

出0入0汤圆

发表于 2010-10-9 21:55:40 | 显示全部楼层
因为即使99.99%的资源浪费了,也完成任务了, 等时间不够时自然会想办法的。 费那么多心思省出时间来,也没有。 单片机的速度对它执行的任务来说太快了。

出0入170汤圆

发表于 2010-10-9 21:57:40 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-9 22:00:50 | 显示全部楼层
有时候对每个片段执行的时钟的刻度要求较高或者只有单任务怎么办?
比如用100kbit的spi与10sps的adc通讯。
当然如果可以,在需要延时时插入其他事务也是很好的,但搞得如同操作系统了。

出0入0汤圆

发表于 2010-10-9 22:02:29 | 显示全部楼层
回复【楼主位】yrloy 断雪
-----------------------------------------------------------------------
Delay()函数用处还是很多地~在对时序要求严格的东西 还要关中断 一般在嵌入式os都有这样的考虑~

出0入0汤圆

发表于 2010-10-9 22:08:21 | 显示全部楼层
同意kk1271
另外,很多时候,做控制的微处理器并不需要要多大的运算量,所以空转带来的简化代码和高实时性是有利的。
楼主的想法已经到了做成os的程度,可以直接转入现有的嵌入式操作系统了。

出0入0汤圆

发表于 2010-10-9 22:12:21 | 显示全部楼层
windos大部分时间也是在空循环中等待,处于idle状态。

出0入0汤圆

发表于 2010-10-9 22:16:14 | 显示全部楼层
mark 2

出0入0汤圆

发表于 2010-10-9 22:23:43 | 显示全部楼层
等你看到高水平的电子工程师用单片机,你就会觉得天哪,单片机竟然可以这样使用,这怎么可能?
要是这样使用PC机,就连286都可以运行windows XP了,并且还非常流畅!

出0入0汤圆

发表于 2010-10-9 22:42:15 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-9 22:50:22 | 显示全部楼层
MARK

出0入0汤圆

发表于 2010-10-9 23:04:30 | 显示全部楼层
mark!!

出0入0汤圆

发表于 2010-10-9 23:14:44 | 显示全部楼层
受益!

出0入18汤圆

发表于 2010-10-9 23:18:39 | 显示全部楼层
呵呵  读完了  楼主的想法不错  我个人觉得 在一部分应用里  楼主的提议非常的好 也很有必要
这样的确可以提高性能

但是在一部分应用里  延时 很有必要  剩余的就是空转  你回收了 能干吗 应用不需要  你还是空转
所以有些应用空转延时也很有必要  比如高精度的通讯  像48楼说的一样  不能中断  中断了就错了
比如某个MCU只负责一个通讯和一些简单的任务 那么多余的时间你回收了页没用  因为用不着!

我觉得还是 2方面协调发展 按需分配!

出0入0汤圆

发表于 2010-10-9 23:32:15 | 显示全部楼层
又有地方可以~~~抄架了~~~~ 晚点看完 在找咂~~~~ 哈哈


终于~~大致看完     16K 以下程序跟本不用管这时间问题  也不在呼这点时间



利用~~空出来的这点时间作别的事  可行是可行  但是对于 20个任务以下的处理~~~~ 计算时间还不如由得他在哪等时间单位

还有 一个  定时器要设成多短 才能有足够的 准确的时间片给你选或比较 但这样系统也会发生频繁的中断。。。。

要不~~~~给N 个任务配N+N个定时器

出0入0汤圆

发表于 2010-10-9 23:53:46 | 显示全部楼层
楼主可以写个NOP循环,没事就让程序去玩NOP,有事中断喊它回来。干完后继续玩NOP

出0入0汤圆

发表于 2010-10-10 00:04:05 | 显示全部楼层
我觉得真正做产品考虑成本的单片机工程师,都应该考虑如果用最便宜的单片机实现最多的功能。
让单片机在做无用的等待的基本上还不能算合格的单片机工程师。一个主程序循环执行的时间越少,它的实时性就越高,回收时间就是提高稳定性。要想提高单片机水平必须要有提高软件效率的思想。
我一般把软件的工作按实时性划分,例如红外信号解码,按键查询,显示刷新均2ms执行一次,一些对实时性要求不高的程序就500ms处理一次,例如温度采集。 125us进入一次定时中断,这里面设置定时标志,这里面也可以处理更高实时性的任务(当然要简短,如果处理时间长的任务可以设置一个标志位,退出中断后,让程序处理完进入中断前的子程序,马上跳到标志位标识的子程序。)

出0入4汤圆

发表于 2010-10-10 00:12:26 | 显示全部楼层
是呀,看到坛子里很多人写的那个GPRS发短信的程序都是
SEND("XXXXXXX");
DELAY(XXX);
SEND("XXXXXXX");
DELAY(XXX);
SEND("XXXXXXX");
DELAY(XXX);
SEND("XXXXXXX");
DELAY(XXX);
SEND("XXXXXXX");
DELAY(XXX);
杯具,一旦哪一步收到的数据不正确呢,就不知道该怎么办喽

有经验的人写都是用状态机的,整个系统一直在循环

出0入0汤圆

发表于 2010-10-10 00:15:02 | 显示全部楼层
回复【58楼】jrcsh  邪恶的小会会
又有地方可以~~~抄架了~~~~ 晚点看完 在找咂~~~~ 哈哈
终于~~大致看完     16k 以下程序跟本不用管这时间问题  也不在呼这点时间

利用~~空出来的这点时间作别的事  可行是可行  但是对于 20个任务以下的处理~~~~ 计算时间还不如由得他在哪等时间单位
还有 一个  定时器要设成多短 才能有足够的 准确的时间片给你选或比较 但这样系统也会发生频繁的中断。。。。
要不~~~~给n 个任务配n+n个定时器
-----------------------------------------------------------------------

呵呵,其实有一个定时器就够了,设置125us进入一次定时中断,在里面设置多少个定时变量都行了。当然,这些计时变量的最小值是125us,至于定时时间,无限大。

出0入0汤圆

发表于 2010-10-10 00:25:23 | 显示全部楼层
哈哈,对,忽然想起来,这种思想应该叫做状态机。至于所谓操作系统,感觉很高深的样子。我编程,主程序一个循环一般不会超2ms,子程序有有些1个小时才会执行一次,有限10ms执行一次,根据实时性的需要。但是主程序2ms循环一周,就能保证任务在需要响应时能在2ms内被处理。当然,如果需要更快被响应也是可以的,我一般都放在定时中断里面去查询和响应,例如125us定时器溢出进入中断后,我就去查询期间是否有紧急任务要处理,对于要求更快响应的,一方面要缩短定时器溢出时间,当然就会增加发生中断的次数,进栈和出栈多了会影响效率。用外部中断那就是最高的响应速度的任务了。

出0入0汤圆

发表于 2010-10-10 00:34:03 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-10 00:41:17 | 显示全部楼层
点点点。。。

出0入0汤圆

发表于 2010-10-10 00:53:10 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-10 00:55:55 | 显示全部楼层
回复【61楼】electricit
是呀,看到坛子里很多人写的那个gprs发短信的程序都是
send("xxxxxxx");
delay(xxx);
send("xxxxxxx");
delay(xxx);
send("xxxxxxx");
delay(xxx);
send("xxxxxxx");
delay(xxx);
send("xxxxxxx");
delay(xxx);
杯具,一旦哪一步收到的数据不正确呢,就不知道该怎么办喽
有经验的人写都是用状态机的,整个系统一直在循环
-----------------------------------------------------------------------
这个应该根据程序大小来确定。 状态机对于程序的阅读来说有点难度特别是大程序。 不知道那里就赋值改变了状态。

不使用状态机,倒是可以看出程序的流程来。 直接用if判断。

出0入0汤圆

发表于 2010-10-10 01:04:32 | 显示全部楼层
马克

出0入0汤圆

发表于 2010-10-10 01:08:27 | 显示全部楼层
这几天正在看一本书,讲的是时间触发嵌入式系统设计,感觉楼主和书上说的差不多。书上的代码不错!

出0入0汤圆

发表于 2010-10-10 01:15:20 | 显示全部楼层
回复【69楼】chengluoran  
这几天正在看一本书,讲的是时间触发嵌入式系统设计,感觉楼主和书上说的差不多。书上的代码不错!
-----------------------------------------------------------------------

什么书名?有地方下载么,哈哈哈

出0入0汤圆

发表于 2010-10-10 05:52:38 | 显示全部楼层
回复【62楼】shzdxx 春
回复【58楼】jrcsh  邪恶的小会会
又有地方可以~~~抄架了~~~~ 晚点看完 在找咂~~~~ 哈哈
终于~~大致看完     16k 以下程序跟本不用管这时间问题  也不在呼这点时间
  
利用~~空出来的这点时间作别的事  可行是可行  但是对于 20个任务以下的处理~~~~ 计算时间还不如由得他在哪等时间单位
还有 一个  定时器要设成多短 才能有足够的 准确的时间片给你选或比较 但这样系统也会发生频繁的中断。。。。
要不~~~~给n 个任务配n+n个定时器
-----------------------------------------------------------------------
呵呵,其实有一个定时器就够了,设置125us进入一次定时中断,在里面设置多少个定时变量都行了。当然,这些计时变量的最小值是125us,至于定时时间,无限大。
-----------------------------------------------------------------------

频繁的~~~进入中断 ~~~~ 我怕怕  


一个 16K 以下的程序简单应用  只要主意点 1~3天 交差    如果大量的时间花在算 间隔时间上~~~ 不2个星期能交差来

出0入0汤圆

发表于 2010-10-10 08:34:08 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-10 09:13:02 | 显示全部楼层
收藏

出0入0汤圆

发表于 2010-10-10 09:13:43 | 显示全部楼层
LZ有想法是好的,但mars了。。。

状态机在嵌入式系统中的出现也远不止几年而已:)

出0入0汤圆

 楼主| 发表于 2010-10-10 09:19:26 | 显示全部楼层
回复【39楼】user1st
操作系统的思想。即便不等待。你能确定程序做的都是有意义的事情???

-----------------------------------------------------------------------

把时间全用上,CPU大多情况还有大量空闲资源,我文中说了怎样用这些时间。退一步想,哪怕是再没意义,也一定比空转要强的多,不是么?

出0入0汤圆

 楼主| 发表于 2010-10-10 09:27:48 | 显示全部楼层
回复【44楼】hemjidn
不用大吃一惊吧。pc的cpu使用率有多少?回收时间?回收给系统还是储存起来?单片机多是实时处理由挂起到恢复要多久?很多时候数据已经过去了或者说丢失了回收那有何用?微软为win的强大牺牲了多少硬件性能。当然随着硬件的更新换代这种中断、切换、甚至睡眠挂起以代替空转是大势所趋。
-----------------------------------------------------------------------

我无异争论,只为学习。
不过请阁下看完全文再说话,我文中提供了一种不占用任何额外CPU时间的方法,说的很清楚。
这本就是为低性能8位机给出的方案,因为高性能机的剥夺式系统很成熟。

出0入0汤圆

 楼主| 发表于 2010-10-10 09:31:17 | 显示全部楼层
回复【45楼】flkflk
因为即使99.99%的资源浪费了,也完成任务了, 等时间不够时自然会想办法的。 费那么多心思省出时间来,也没有。 单片机的速度对它执行的任务来说太快了。
-----------------------------------------------------------------------

嗯,是,不过等时间不够时想出来的办法总是特殊办法,每次都要费脑筋,并不通用。
高等数学中绝大多数问题不用微积分以特殊方法都能解决,但为什么牛顿还要发明微积分。
我就是想让自己省力才想出这些办法,就跟大家一起说说的。

出0入0汤圆

 楼主| 发表于 2010-10-10 09:36:26 | 显示全部楼层
回复【47楼】ssaweee
有时候对每个片段执行的时钟的刻度要求较高或者只有单任务怎么办?
比如用100kbit的spi与10sps的adc通讯。
当然如果可以,在需要延时时插入其他事务也是很好的,但搞得如同操作系统了。
-----------------------------------------------------------------------

请读完全文,怎么大家都这么问,我文中变异协作式内核中的变异就是指的这点,你可以看看,每个任务运行跟裸机是没有区别。

而且解决你举的例子的方法,我在文中也给了,就是放入中断保证时效严格,然后通过I/O缓冲区保证数据不丢,即高效又稳定。

出0入0汤圆

发表于 2010-10-10 09:38:41 | 显示全部楼层
回复【22楼】yrloy  断雪
回复【16楼】astankvai 陈超
呵呵,期待啊。中断用指针的方法,和arm的中断有点像啊,这样处理数据也需要入栈的吧?
-----------------------------------------------------------------------
这些我们不用理会,中断前后保护现场的工作是编译器的事,没问题的。
回复【15楼】zhousfe 敏—感—词工
对于第二种方式在实际应用中的可行性,仍需要多次验证才可知晓
-----------------------------------------------------------------------
第二种方案我刚刚写完,我用四个不同频率、不同图案的流水灯在mega16上运行12小时,时间误差极小,继续运行,长期运行的检测基本没偶然错误。
我有用键盘、两个4位数码管实验,键盘响应非常及时,数码管亮度稳定均匀,暂没......
-----------------------------------------------------------------------
出栈入栈虽然是编译器做的事,但是对小RAM的单片机来说,开销就大了哟。

出0入0汤圆

 楼主| 发表于 2010-10-10 09:39:56 | 显示全部楼层
回复【48楼】kk1271
回复【楼主位】yrloy 断雪
-----------------------------------------------------------------------
delay()函数用处还是很多地~在对时序要求严格的东西 还要关中断 一般在嵌入式os都有这样的考虑~

-----------------------------------------------------------------------


我的每一个任务与裸机无异,仅是以大分频系数的定时器做时基,并没有产生中断的机会,具体文章说了。
而且如果时序要求严苛,哪怕是裸机,也一定要关中断的,这点与OS无关。

出0入0汤圆

发表于 2010-10-10 09:42:19 | 显示全部楼层
延时的确是个头痛的问题,UCOS的延时用起来的确是很爽,但是只能是TICK的整数倍。TICK太小,系统开销就大了。我们公司现在软件审核都比较严,不允许有阻塞。延时都是用状态机做,还好是16位机,要是8位就累傻了。

出0入0汤圆

 楼主| 发表于 2010-10-10 09:43:15 | 显示全部楼层
回复【52楼】kaka STM8
等你看到高水平的电子工程师用单片机,你就会觉得天哪,单片机竟然可以这样使用,这怎么可能?
要是这样使用pc机,就连286都可以运行windows xp了,并且还非常流畅!
-----------------------------------------------------------------------

但是会是看网页就不能听歌、看电影就不能下载东西的流畅。。。
你如果让现在的windows以单任务运行,它也会流畅的。

出0入0汤圆

 楼主| 发表于 2010-10-10 09:45:40 | 显示全部楼层
回复【57楼】dengxiaofeng 天下的人
呵呵  读完了  楼主的想法不错  我个人觉得 在一部分应用里  楼主的提议非常的好 也很有必要  
这样的确可以提高性能
但是在一部分应用里  延时 很有必要  剩余的就是空转  你回收了 能干吗 应用不需要  你还是空转
所以有些应用空转延时也很有必要  比如高精度的通讯  像48楼说的一样  不能中断  中断了就错了
比如某个mcu只负责一个通讯和一些简单的任务 那么多余的时间你回收了页没用  因为用不着!
我觉得还是 2方面协调发展 按需分配!
-----------------------------------------------------------------------

嗯嗯,我也是这意思,就是说出来,大家分享一下。

出0入0汤圆

 楼主| 发表于 2010-10-10 09:48:51 | 显示全部楼层
回复【58楼】jrcsh 邪恶的小会会
又有地方可以~~~抄架了~~~~ 晚点看完 在找咂~~~~ 哈哈
终于~~大致看完     16k 以下程序跟本不用管这时间问题  也不在呼这点时间
  
利用~~空出来的这点时间作别的事  可行是可行  但是对于 20个任务以下的处理~~~~ 计算时间还不如由得他在哪等时间单位
还有 一个  定时器要设成多短 才能有足够的 准确的时间片给你选或比较 但这样系统也会发生频繁的中断。。。。
要不~~~~给n 个任务配n+n个定时器
-----------------------------------------------------------------------

晕,我不想争论的。。。

在看看我后后面说的方法。。。我只的变异就是说不用中断来浪费性能。。。
传统协作式内核是靠定时中断来当时钟节拍,总会打断任务浪费性能,我的仅仅是读读大分频定时器的数当时钟,并不让它产生中断,整体运行跟裸机是没区别的~

出0入0汤圆

 楼主| 发表于 2010-10-10 09:54:47 | 显示全部楼层
回复【69楼】chengluoran
这几天正在看一本书,讲的是时间触发嵌入式系统设计,感觉楼主和书上说的差不多。书上的代码不错!
-----------------------------------------------------------------------

呵呵,是啊,什么书啊,内核定时的思想应该差不多。

不过我后面所指的变异,是我没见过任何系统中有,因为高性能机不采用协作式内核,就更别说变异了。

而低性能机恰恰需要这种简介高效内核,但却没有能变异到跟裸机一样的~~

出0入0汤圆

 楼主| 发表于 2010-10-10 09:56:05 | 显示全部楼层
回复【74楼】snoopyzz
lz有想法是好的,但mars了。。。
状态机在嵌入式系统中的出现也远不止几年而已:)
-----------------------------------------------------------------------

。。。
这不是状态机!@#¥%……&*()——+

出0入0汤圆

 楼主| 发表于 2010-10-10 10:00:31 | 显示全部楼层
回复【79楼】astankvai 陈超
回复【22楼】yrloy  断雪
回复【16楼】astankvai 陈超
呵呵,期待啊。中断用指针的方法,和arm的中断有点像啊,这样处理数据也需要入栈的吧?
-----------------------------------------------------------------------
这些我们不用理会,中断前后保护现场的工作是编译器的事,没问题的。
回复【15楼】zhousfe 敏—感—词工
对于第二种方式在实际应用中的可行性,仍需要多次验证才可知晓
-----------------------------------------------------------------------
第二种方案我刚刚写完,我用四个不同频率、不同图案的流水灯在mega16上运行12小时,时间误差极小,继续运行,长期运行的检测基本没偶然错误。
我有用键盘、两个4位数......
-----------------------------------------------------------------------

嗯,不过这点开销一定比空转延时小的多。
不过还是推荐第二种方法,我在切换部分都是汇编实现的,过几天吧,发上来大家看看,性能如何。

出0入0汤圆

 楼主| 发表于 2010-10-10 10:03:46 | 显示全部楼层
回复【81楼】astankvai 陈超
延时的确是个头痛的问题,ucos的延时用起来的确是很爽,但是只能是tick的整数倍。tick太小,系统开销就大了。我们公司现在软件审核都比较严,不允许有阻塞。延时都是用状态机做,还好是16位机,要是8位就累傻了。
-----------------------------------------------------------------------

用UCOS,小数据、不定时、无规律的事件放到中断接收就好了,这样就不阻塞了。

出0入0汤圆

发表于 2010-10-10 10:54:15 | 显示全部楼层
回复【70楼】shzdxx  春
-----------------------------------------------------------------------
书名是《时间触发嵌入式系统设计模式 8051系列微控制器开发可靠应用》,坛里有人发过。

出0入0汤圆

发表于 2010-10-10 10:55:32 | 显示全部楼层
留观!

出0入0汤圆

发表于 2010-10-10 11:15:46 | 显示全部楼层
频繁的入栈出栈容易不安全的

出0入0汤圆

发表于 2010-10-10 11:28:50 | 显示全部楼层
回复【楼主位】yrloy 断雪
-----------------------------------------------------------------------

对于用IO控模拟的SPI通讯,外部器件对高低电平的时间有要求,这样在单片机IO电平跳转的时候必须有一段延时,这种情况下如何处理呢,先跳出来等时间到了再回去?那样传一个字节就要跳进跳出16次,无疑程序是复杂的

出0入0汤圆

 楼主| 发表于 2010-10-10 11:33:27 | 显示全部楼层
回复【92楼】ddcat
回复【楼主位】yrloy 断雪
-----------------------------------------------------------------------
对于用io控模拟的spi通讯,外部器件对高低电平的时间有要求,这样在单片机io电平跳转的时候必须有一段延时,这种情况下如何处理呢,先跳出来等时间到了再回去?那样传一个字节就要跳进跳出16次,无疑程序是复杂的
-----------------------------------------------------------------------

程序复杂的切换操作是留给内核做的,对于使用者仅仅就相当于两个任务,就是说第一个任务跟正常使用时模拟的代码一样,而当你延时的时候,内核自动跳到第二个任务,所以说这些复杂的操作使用者无需考虑,会用即可。

出0入0汤圆

发表于 2010-10-10 11:52:27 | 显示全部楼层
事实胜于雄辩。试试用延时产生单频率(声音)和(原创)产生单频率或多频率就知道他们之间的优劣了……

出0入0汤圆

发表于 2010-10-10 12:35:53 | 显示全部楼层
“仅仅是让定时器以大分频系数开着, 而不给其产生中断的机会。当任务将要放弃使用权时,读取定时器,作为时钟基准,然后清零。”

这里我没太懂具体作用是干啥??

出0入0汤圆

 楼主| 发表于 2010-10-10 13:04:39 | 显示全部楼层
回复【95楼】lbc___
“仅仅是让定时器以大分频系数开着, 而不给其产生中断的机会。当任务将要放弃使用权时,读取定时器,作为时钟基准,然后清零。”
这里我没太懂具体作用是干啥??
-----------------------------------------------------------------------

作为一个内核是需要时钟来确定用户的延时时间的,以往内核都是以一次中断作为一次节拍来计算时间,准确,但是每一次中断的入栈出栈都浪费很多资源。与其如此,不如采用读取定时器的方式作为时间基准,而不让它产生中断浪费资源,想让中断不产生还不至于溢出,所以采用大分频系数。

出0入0汤圆

发表于 2010-10-10 13:08:28 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-10 13:17:51 | 显示全部楼层
浆糊中

出0入0汤圆

发表于 2010-10-10 13:19:43 | 显示全部楼层
这样的内核体积会非常小,运行方式与裸机无异,仅仅是把空转延时时间干些其它事。对使用者还没什么要求,不想以往系统那么复杂。

可惜市面上并没有基于这种方式的内核,我已经写了一个,非常精简,运行稳定。但作为一个想应用实际的内核,还需要检验。我最后检查一下后,过几天拿出来大家一起分享。


这样的商业用OS早就有了,比如原来的treesoft, vector的 osCAN 都是这样的系统。

在汽车方面应用超过8年多了。

出0入0汤圆

 楼主| 发表于 2010-10-10 13:46:27 | 显示全部楼层
osCAN是剥夺式内核,受中断节拍干扰,怎么可能是这种?!

其实它对硬件的要求相当的高



PS:又百度了下,发现是混合型调度,但调度方式还是定时中断,不能裸机一致

出0入0汤圆

发表于 2010-10-10 14:12:52 | 显示全部楼层
如果是像操作18B20那一点器件的精确到几个微妙的延时,不用DELAY()怎么办?
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-20 03:09

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表