您的位置 首页 分销

最高功率运用单片机,抛弃程序中的延时函数

我是PC机底层编程转过来的,以前从来没接触过单片机,五个月前学习AVR,在这里学到很多东西。但也意识到电子工程师们的硬件编程思想与PC

我是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:好了,我上面两种方法,均为原创。期望能对咱们有协助~ 第二种中介绍的变异协作式内核思维很简略,有爱好能够自己写一个,我过几天会把我的发上来。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/bandaoti/fenxiao/255457.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部