下面爲你們介紹一個曾見過的在裸機系統中,非阻塞延時的巧妙設計,當時它是被用在一導航影音娛樂系統的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; }