本文转载自https://my.oschina.net/czzhu/blog/261802;作者:小汉憨憨
摘要: 单片机非阻塞延时巧妙的软件设计。

下面为大家介绍一个曾见过的在裸机系统中,非阻塞延时的巧妙设计,当时它是被用在一导航影音娱乐系统的MCU驱动软件中,在此我对其作了一定的改动。

此章节涉及到STM32内容不多,以软件为主。

此延时软件的设计可以直接进行10、50、100ms及1s的查询定时,并且当若需其它时间要求的定时或延时可以很方便的自己编写软件很简单方便设定。

首先需要设置SysTick 定时中断为10MS进入一次。然后在定时中断函数中作如下处理

void SysTick_Handler(void)
{bTemp10Msec = TIMER_SET;++gTimer.Tick10Msec;if (0 == (gTimer.Tick10Msec % 5)){bTemp50Msec = TIMER_SET;}if (0 == (gTimer.Tick10Msec % 10)){bTemp100Msec = TIMER_SET;}if (100 == gTimer.Tick10Msec){gTimer.Tick10Msec = 0;bTemp1Sec = TIMER_SET;}
}

gTimer是定义的一全局结构体变量,Timer_Struct  gTimer;

此软件设计巧妙之处首先在结构体的设计上:

typedef struct
{u8 Tick10Msec;Char_Field Status;
} Timer_Struct;

其中Char_Field 为一联合体,设计如下:

typedef union
{unsigned char byte;Timer_Bit     field;
} Char_Field;

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

typedef struct
{unsigned char bit0: 1;unsigned char bit1: 1;unsigned char bit2: 1;unsigned char bit3: 1;unsigned char bit4: 1;unsigned char bit5: 1;unsigned char bit6: 1;unsigned char bit7: 1;
} Timer_Bit;

此联合体的这样设计的目的将在后面的代码中体现出来;

定时中断里的bTempXXX及后面定时或延时查询用的bSystemXXX 是宏定义,如下:

#define bSystem10Msec          gTimer.Status.field.bit0
#define bSystem50Msec          gTimer.Status.field.bit1
#define bSystem100Msec         gTimer.Status.field.bit2
#define bSystem1Sec            gTimer.Status.field.bit3
#define bTemp10Msec            gTimer.Status.field.bit4
#define bTemp50Msec            gTimer.Status.field.bit5
#define bTemp100Msec           gTimer.Status.field.bit6
#define bTemp1Sec              gTimer.Status.field.bit7

定时中断里的TIMER_SET 为真(1)可用宏定义,也可如下定义:

以上便是非阻塞延时软件的整体结构设计。

typedef enum
{TIMER_RESET = 0,TIMER_SET = 1,
} TimerStatus;

另外还需要在系统运行大的循环中调用设计的控制函数,

void SysTimer _Process(void)
{gTimer.Status.byte &= 0xF0;if (bTemp10Msec){bSystem10Msec = TIMER_SET;}if (bTemp50Msec){bSystem50Msec = TIMER_SET;}if (bTemp100Msec){bSystem100Msec = TIMER_SET;}if (bTemp1Sec){bSystem1Sec = TIMER_SET;}gTimer.Status.byte &= 0x0F;
}

此函数开头与结尾两句

gTimer.Status.byte &= 0xF0;
gTimer.Status.byte &= 0x0F;

就巧妙的实现了bSystemXXX  和 bTempXXX的消除工作,不用再定时到来后手动把计数值消除。此处便用到了联合体中的变量共用一个起始存储空间的特性。

下面一个简单的应用举例,比如我们想让一LED灯每100MS亮或灭一次,就可以这样设计:

int main(void)
{while(1){SysTimer _Process();if(TIMER_SET == bSystem100Msec){LED = !LED;}}
}

另 附此软件的整体代码 :

#define bSystem10Msec          gTimer.Status.field.bit0
#define bSystem50Msec          gTimer.Status.field.bit1
#define bSystem100Msec         gTimer.Status.field.bit2
#define bSystem1Sec            gTimer.Status.field.bit3
#define bTemp10Msec            gTimer.Status.field.bit4
#define bTemp50Msec            gTimer.Status.field.bit5
#define bTemp100Msec           gTimer.Status.field.bit6
#define bTemp1Sec              gTimer.Status.field.bit7typedef enum
{TIMER_RESET = 0,TIMER_SET = 1,
} TimerStatus;typedef struct
{unsigned char bit0: 1;unsigned char bit1: 1;unsigned char bit2: 1;unsigned char bit3: 1;unsigned char bit4: 1;unsigned char bit5: 1;unsigned char bit6: 1;unsigned char bit7: 1;
} Timer_Bit;typedef union
{unsigned char byte;Timer_Bit     field;
} Char_Field;typedef struct
{u8 Tick10Msec;Char_Field Status;
} Timer_Struct;//定义一全局变量
Timer_Struct gTimer;void SysTick_Handler(void)
{bTemp10Msec = TIMER_SET;++gTimer.Tick10Msec;if (0 == (gTimer.Tick10Msec % 5)){bTemp50Msec = TIMER_SET;}if (0 == (gTimer.Tick10Msec % 10)){bTemp100Msec = TIMER_SET;}if (100 == gTimer.Tick10Msec){gTimer.Tick10Msec = 0;bTemp1Sec = TIMER_SET;}
}void SysTimer _Process(void)
{gTimer.Status.byte &= 0xF0;if (bTemp10Msec){bSystem10Msec = TIMER_SET;}if (bTemp50Msec){bSystem50Msec = TIMER_SET;}if (bTemp100Msec){bSystem100Msec = TIMER_SET;}if (bTemp1Sec){bSystem1Sec = TIMER_SET;}gTimer.Status.byte &= 0x0F;
}

STM32系统滴答_及不可不知的延时技巧 - (下)相关推荐

  1. STM32系统滴答_及不可不知的延时技巧

    我想每个单片机爱好者及工程开发设计人员都有过点灯的经历.流水灯是个好东西,尤其是在调试资源有限的环境中,有时会帮上大忙. 然在最初入门时,如何让这些小灯们按照我们的想法欢快地跑起来呢,绝大多数小朋友的 ...

  2. STM32系统滴答_及不可不知的延时技巧 - (上)

    文章转载自https://my.oschina.net/czzhu/blog/228596:作者:小汉憨憨 摘要: 尤应强调注意的是SysTick 中断优先级. 我想每个单片机爱好者及工程开发设计人员 ...

  3. STM32——系统滴答定时器

    STM32--系统滴答定时器 宗旨:技术的学习是有限的,分享的精神是无限的. 一.SysTick[内核中] [风格:先描述一下库对寄存器的封装,再举例实现某些功能] SysTick定时器被捆绑在NVI ...

  4. stm32系统滴答定时器使用

     STM32菜鸟成长记录---系统滴答定时器(systick)应用 标签: delay任务测试reference编译器工作 2012-08-19 22:55 47395人阅读 评论(4) 收藏 举 ...

  5. STM32系统滴答定时器(systick)应用

    一:系统滴答定时器(systick) 1.systick介绍 Systick就是一个定时器而已,只是它放在了NVIC中,主要的目的是为了给操作系统提供一个硬件上的中断(号称滴答中断).滴答中断?这里来 ...

  6. stm32系统滴答定时器

    SysTick定时器(系统滴答定时器)是一个倒计时定时器,被捆绑在NVIC中,用于产生SYSTICK异常(异常号:15).在以前,大多操作系统需要一个硬件定时器来产生操作系统需要的滴答中断,作为整个系 ...

  7. stm32滴答计时器_STM32——系统滴答定时器

    STM32--系统滴答定时器 一.SysTick[内核中] [风格:先描述一下库对寄存器的封装,再举例实现某些功能] SysTick定时器被捆绑在NVIC中,用于产生SysTick异常(异常号: 15 ...

  8. stm32滴答计时器_stm32中的系统滴答定时器使用

    系统滴答定时器对于stm32的初学者来说还是非常重要的,因为随着你学习的深入编程过程中肯定会调用延时函数,比如我之前的一些gpio相关的实验中.那么延时函数的编写也是几种方法的,一般开始接触都是让系统 ...

  9. 【STM32】HAL库-系统滴答定时器SysTick

    SysTick定时器被捆绑在NVIC中,是一个简单的定时器,对于CM3.CM4内核芯片,都有Systick定时器.Systick定时器常用来做延时,或者实时系统的心跳时钟.这样可以节省MCU资源,不用 ...

最新文章

  1. 牛客练习赛81 B. 小 Q 与彼岸花(FWT nlogn做法)
  2. NSInvocation
  3. 物联网通信协议全解析
  4. python mysql latin1_python操作Mysql数据库
  5. OpenGL: 3D坐标到屏幕坐标的转换逻辑(gluProject的实现)(转)
  6. Boost:BOOST_ASSERT用法的测试程序
  7. 课程设计-毕业设计-JAVA画板课程设计---总之岁月漫长,然而值得等待。
  8. DRDS SQL 审计与分析——全面洞察 SQL 之利器
  9. 一段简单的打印代码(c#)
  10. Eigen官网教程(1) Matrix相关
  11. 成年人才是走失比例最高的!今日头条发布走失人口数据报告
  12. 【Elasticsearch】7.9 单字段支持的最大字符数
  13. CLR via C# 中关于装箱拆箱的摘录
  14. php mysql帮助类,基于PHP的MYSQL操作类
  15. keras中TimeDistributed的用法
  16. 2014年计算机应用文摘,2014年江西信息技术高考试卷Word版
  17. 浏览器 Cookie 的使用
  18. 计算机驱动器程序,打开计算机CD驱动器的位置
  19. 流量主头像组合微信小程序源码下载支持多种分类并支持姓氏头像制作生成
  20. putty连接设备时报错 Can’t agree a key change algorithm

热门文章

  1. KVM虚拟化产品-iVCS介绍
  2. windows和ubuntu双系统安装笔记
  3. dotnetfx35
  4. Google 天气预报 API
  5. 计划测试系列(一)--万事开头难
  6. Dao层,Mapper层,controller层,service层,model层都有什么作用
  7. (转)ABPA UI--Triggering PAI manually 通过设置新的OKCODE、触发PAI
  8. 修道士与野人问题——C++源代码,伪代码,详细分析
  9. acer蜂鸟swift1深度linux,宏碁蜂鸟Swift3和Swift1哪个值得买?宏碁蜂鸟Swift1和Swift3详细区别对比评测...
  10. 基于C的PCM音频数据的读取、处理与写入(一)