下面为你们介绍一个曾见过的在裸机系统中,非阻塞延时的巧妙设计,当时它是被用在一导航影音娱乐系统的MCU驱动软件中,在此我对其做了必定的改动。函数
此章节涉及到STM32内容很少,以软件为主。spa
此延时软件的设计能够直接进行10、50、100ms及1s的查询定时,而且当若需其它时间要求的定时或延时能够很方便的本身编写软件很简单方便设定。设计
首先须要设置SysTick 定时中断为10MS进入一次。而后在定时中断函数中做以下处理 code
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;it
此软件设计巧妙之处首先在结构体的设计上:io
typedef struct { u8 Tick10Msec; Char_Field Status; } Timer_Struct;
其中Char_Field 为一联合体,设计以下:class
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.bit7 typedef 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; }