本帖最后由 lw1997 于 2019-11-2 23:33 编辑
软件定时器是用程序模拟出来的定时器,可以由一个硬件定时器模拟出成千上万个软件定时器,这样程序在需要使用较多定时器的时候就不会受限于硬件资源的不足,这是软件定时器的一个优点,即数量不受限制。但由于软件定时器是通过程序实现的,其运行和维护都需要耗费一定的CPU资源,同时精度也相对硬件定时器要差一些。在RTOS等操作系统中,都带有软件定时器,原理大同小异。典型的实现方法是:通过一个硬件定时器产生固定的时钟节拍,每次硬件定时器中断到,就对一个全局的时间标记加一,每个软件定时器都保存着到期时间,程序需要定期扫描所有运行中的软件定时器,将各个到期时间与全局时钟标记做比较,以判断对应软件定时器是否到期,到期则执行相应的回调函数,并关闭该定时器
程序如下,通过一个硬件定时器产生固定的时钟节拍,用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 //定时器个数
- //定义定时器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 函数指针类型
- 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; //状态
- unsigned char mode; //模式
- unsigned int period; //定时周期
- unsigned int count; //定时计数用
- pFun callback; //定时器回调函数
- } softTimer;
- //定时器结构数组
- 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;
- }
- //清除定时器状态(用于执行事件后手动清除定时器状态)
- 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;
- }
- }
- //获取定时器状态
- unsigned char softTimer_GetState(unsigned int id)
- {
- return softTimerList[id].state;
- }
- void softTimer_Update(void) //更新定时器状态,在硬件定时器中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() //主函数
- {
- 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中执行
- if(softTimer_8s_flag == 1)
- {
- LED4=~LED4;
- Delayms(200);//模拟耗时事件
- softTimer_8s_flag = 0;
- }
- }
- }
复制代码
程序及仿真:
51单片机软件定时器测试.7z
(48.06 KB, 下载次数: 109)
|