本帖最后由 lw1997 于 2019-11-2 23:33 編輯
軟件定時器是用程序模擬出來的定時器,可以由一個硬件定時器模擬出成千上萬個軟件定時器,這樣程序在需要使用較多定時器的時候就不會受限于硬件資源的不足,這是軟件定時器的一個優(yōu)點,即數(shù)量不受限制。但由于軟件定時器是通過程序實現(xiàn)的,其運行和維護都需要耗費一定的CPU資源,同時精度也相對硬件定時器要差一些。在RTOS等操作系統(tǒng)中,都帶有軟件定時器,原理大同小異。典型的實現(xiàn)方法是:通過一個硬件定時器產生固定的時鐘節(jié)拍,每次硬件定時器中斷到,就對一個全局的時間標記加一,每個軟件定時器都保存著到期時間,程序需要定期掃描所有運行中的軟件定時器,將各個到期時間與全局時鐘標記做比較,以判斷對應軟件定時器是否到期,到期則執(zhí)行相應的回調函數(shù),并關閉該定時器
程序如下,通過一個硬件定時器產生固定的時鐘節(jié)拍,用4個LED演示效果:
- #include "reg51.h"
- //#include "STC89C5xRC.h"
- sbit LED1=P1^0;
- sbit LED2=P1^1;
- sbit LED3=P1^2;
- sbit LED4=P1^3;
- unsigned char softTimer_8s_flag = 0; //8s定時器flag
- #define NULL 0
- #define SOFT_TIMER_MAX 4 //定時器個數(shù)
- //定義定時器ID
- #define ID_1S_LED_TASK 0
- #define ID_2S_LED_TASK 1
- #define ID_4S_LED_TASK 2
- #define ID_8S_LED_TASK 3
- typedef void (*pFun)(void); //callback 函數(shù)指針類型
- typedef enum tmrMode {
- MODE_ONE_SHOT = 0, //單次模式
- MODE_PERIODIC, //周期模式
- } tmrMode;
- typedef enum tmrState {
- SOFT_TIMER_STOPPED = 0, //停止
- SOFT_TIMER_RUNNING, //運行
- SOFT_TIMER_TIMEOUT, //超時
- SOFT_TIMER_WAITING //等待
- } tmrState;
- typedef struct softTimer {
- unsigned char state; //狀態(tài)
- unsigned char mode; //模式
- unsigned int period; //定時周期
- unsigned int count; //定時計數(shù)用
- pFun callback; //定時器回調函數(shù)
- } softTimer;
- //定時器結構數(shù)組
- softTimer softTimerList[SOFT_TIMER_MAX] = {0};
- //設定定時器
- void softTimer_Creat(unsigned char id,tmrMode mode,unsigned int interval,pFun cb)
- {
- softTimerList[id].mode = mode;
- softTimerList[id].period = interval;
- softTimerList[id].count = 0;
- softTimerList[id].callback = cb;
- softTimerList[id].state = SOFT_TIMER_STOPPED;
- }
- //打開定時器
- void softTimer_Start(unsigned int id)
- {
- softTimerList[id].state = SOFT_TIMER_RUNNING;
- }
- //停止定時器
- void softTimer_Stop(unsigned int id)
- {
- softTimerList[id].state = SOFT_TIMER_STOPPED;
- }
- //清除定時器狀態(tài)(用于執(zhí)行事件后手動清除定時器狀態(tài))
- void softTimer_Clr(unsigned int id)
- {
- if(softTimerList[id].mode == MODE_ONE_SHOT){
- softTimerList[id].state = SOFT_TIMER_STOPPED;
- }else{
- softTimerList[id].state = SOFT_TIMER_RUNNING;
- }
- }
- //獲取定時器狀態(tài)
- unsigned char softTimer_GetState(unsigned int id)
- {
- return softTimerList[id].state;
- }
- void softTimer_Update(void) //更新定時器狀態(tài),在硬件定時器中1ms調用一次
- {
- unsigned char id;
- for(id = 0 ;id <= SOFT_TIMER_MAX ; id++ ){
- switch (softTimerList[id].state){
- case SOFT_TIMER_STOPPED:
- break;
- case SOFT_TIMER_RUNNING:
- if(softTimerList[id].count < softTimerList[id].period){
- softTimerList[id].count ++;
- }else{
- softTimerList[id].count = 0;
- softTimerList[id].state = SOFT_TIMER_TIMEOUT;
- softTimerList[id].callback();
- }
- break;
- case SOFT_TIMER_TIMEOUT:
- if(softTimerList[id].mode == MODE_ONE_SHOT) {
- softTimerList[id].state = SOFT_TIMER_STOPPED;
- } else {
- softTimerList[id].count ++;
- softTimerList[id].state = SOFT_TIMER_RUNNING;
- }
- break;
- default: //state error
- break;
- }
- }
- }
- void Timer0Init(void) //1毫秒@12.000MHz
- {
- TMOD = 0x00; //設置定時器模式
- TL0 = 0xC0; //設置定時初值
- TH0 = 0xE0; //設置定時初值
- EA = 1;
- ET0 = 1;
- TR0 = 1;
- }
- void Interrupt() interrupt 1
- {
- TL0 = 0xC0; //重載定時初值
- TH0 = 0xE0; //重載定時初值
-
- softTimer_Update(); //1ms更新一次softTimer
- }
- void Delayms(unsigned int ms) //@12.000MHz
- {
- unsigned char i, j;
- while(--ms) {
- i = 2;
- j = 239;
- do {
- while (--j);
- } while (--i);
- }
- }
- void softTimer_1s_cb(void)
- {
- LED1 = ~LED1;
- }
- void softTimer_2s_cb(void)
- {
- LED2 = ~LED2;
- }
- void softTimer_4s_cb(void)
- {
- LED3 = ~LED3;
- }
- void softTimer_8s_cb(void)
- {
- softTimer_8s_flag = 1;
- }
- void main() //主函數(shù)
- {
- LED1=0;LED2=0;LED3=0;LED4=0;
-
- //配置相應定時器
- softTimer_Creat(ID_1S_LED_TASK,MODE_PERIODIC,1000,softTimer_1s_cb);
- softTimer_Creat(ID_2S_LED_TASK,MODE_PERIODIC,2000,softTimer_2s_cb);
- softTimer_Creat(ID_4S_LED_TASK,MODE_ONE_SHOT,4000,softTimer_4s_cb);
- softTimer_Creat(ID_8S_LED_TASK,MODE_PERIODIC,8000,softTimer_8s_cb);
-
- //打開相應定時器
- softTimer_Start(ID_1S_LED_TASK);
- softTimer_Start(ID_2S_LED_TASK);
- softTimer_Start(ID_4S_LED_TASK);
- softTimer_Start(ID_8S_LED_TASK);
-
- Timer0Init();//初始化定時器0
- while(1) {
-
- //盡量少用延時,如果事件處理耗時較長,應在main中執(zhí)行
- if(softTimer_8s_flag == 1)
- {
- LED4=~LED4;
- Delayms(200);//模擬耗時事件
- softTimer_8s_flag = 0;
- }
- }
- }
復制代碼
51hei截圖20191102225852.png (56.18 KB, 下載次數(shù): 79)
下載附件
2019-11-2 23:32 上傳
程序及仿真:
51單片機軟件定時器測試.7z
(48.06 KB, 下載次數(shù): 109)
2019-11-2 23:23 上傳
點擊文件名下載附件
程序及 下載積分: 黑幣 -5
|