您的位置 首页 数字

精妙的单片机非堵塞延时程序设计

对于每个单片机爱好者及工程开发设计人员,在刚接触单片机的那最初的青葱岁月里,都有过点亮跑马灯的经历。从看到那一排排小灯按着我们的想法在跳动时激动心情。到随着经验越多,越来又会感觉到这个小灯是个好东西,

关于每个单片机爱好者及工程开发规划人员,在刚触摸单片机的那开端的青翠年月里,都有过点亮跑马灯的阅历。从看到那一排排小灯按着咱们的主意在跳动时激动心境。到跟着经历越多,越来又会感觉到这个小灯是个好东西,尤其是在调试资源有限的环境中,有时会帮上大忙。

但关于绝大多数人,咱们在最开端让灯闪耀起来时大约都会用到堵塞延时完结,会像如下代码的姿态:

1.jpg

然后,在咱们触摸到守时器,咱们会发现,原来用守时中止来处理睬更好。比方咱们能够500ms中止一次,让灯亮或灭,其他的时刻体系还能够做十分之多的作业,功率一下提升了许多。

这时咱们就会渐渐意识到,第一种(堵塞延时)办法功率很低,让芯片在那儿空运转几百毫米,什么也不做,真是极大的糟蹋,尤其在芯片频率较高,使命又许多时,这样做就像在平整宽广的高速公路上挖了一大坑,呈现事端可想而知。

但一个单片机中的守时器究竟有限,假如我需求几十个或许更多不同时刻的守时中止,每一个时刻到都完结不同的处理动作,怎么去做呢。一般咱们会想到在一个守时中止函数中再界说static 变量持续守时,到了所需时刻,做不同的动作。而这样又会导致在一个中止里做了许多不同的作业,会抢占主轮询更多时刻,有时乃至喧宾夺主,并也不是很如的思想逻辑。

那么有没有更好的办法来完结呢,答案是必定的。下面介绍我在一个项目中偶遇,一个精妙规划的非堵塞守时延时软件的规划(此规划首要针关于无操作体系的裸机程序)。

在上篇文章中有对systick的介绍,比方我要设置其10ms中止一次,怎么完结呢?

也很简单,只需调用core_cm3.h文件中 SysTick_Config函数 ,当体系时钟为72MHZ,则设置成如下即可SysTick_Config(720000); (递减计数720000次后中止一次) 。此刻SysTick_Handler中止函数就会10ms进入一次;

使命守时用软件是怎么规划的呢 ?

且先看其数据结构,这也是精妙所在之处,在此作自顶向下的介绍:

其界说结构体类型如:

2.jpg

其间Char_Field 为一联合体,规划如下:

3.jpg

而它内部的Timer_Bit是一个可按位拜访的结构体:

4.jpg

此联合体的这样规划的意图将在后边的代码中体现出来。

如此结构体的规划就完结了。

然后咱们界说的一全局变量,Timer_Struct gTimer;

并在头文件中宏界说如下:

5.jpg

别的为了后边程序明晰,再界说一状况指示:

6.jpg

至此,预备作业就完结了。下面咱们就开端大显身手了!

首要,10ms守时中止处理函数如,能够看出,每抵达10ms 将把bTemp10Msec置1,每50ms 将把bTemp50Msec置1,每100ms 将把bTemp100Msec置1,每1s 将把bTemp1Sec置1,

7.jpg

而这又有什么用呢 ?

这时,咱们需在主轮询while(1)内最开端调用一个守时处理函数如下:

8.jpg

此函数最初与结束两句:

9.jpg

就别离奇妙的完结了bSystemXXX (低4位) 和 bTempXXX(高4位)的清零作业,不必再等守时抵达后还需手动把计数值清零。此处清零作业用到了联合体中的变量共用一个开始存储空间的特性。

但要确保while(1)轮询时刻要远小于10ms,否则将导致守时延时不精确。这样,在每轮询一次,就先把bSystemXXX ,再依据bTempXXX判别是否时刻抵达,并把对应的bSystemXXX 置1,而后边一切的使命就都能够经过bSystemXXX来进行守时延时,在最终函数退出时,又会把bTempXXX清零,为下一次时刻抵达后查询判别作好了预备。

说了这么多,举例说明一下怎么使用:

10.jpg

以上示例四个使命进程,

在主轮询里可进行如下处理:

11.jpg

这样,就能够轻松且明晰完结了多个使命,不同时刻内处理不同工作。(但留意,每个使命处理中不要有堵塞延时,也不要处理过多的作业,致使处理时刻较长。可规划成状况机来处理不同使命。)

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

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

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

微信扫一扫关注我们

返回顶部