51定时器控制4各led,使用回调函数机制

时间:2021-11-08 23:29:38

程序转载自51hei,经过自己的实际验证,多了一种编程的思路技能,回调函数的基本思想也是基于事件机制的,哪个事件来了, 就执行哪个事件。

程序中,最多四个子定时器,说明51的处理速度是不够的,在中断中添加过多的代码会定时不准确。自己实验了5个,第五个想要定时4秒,实际差不多有5秒了,因此中断里面是代码越少越好~~

 1 #include<reg52.h>        //头文件
 2 #define MY_TIMER_MAX    (4)        //最多四个定时器
 3 #define NULL (0)
 4 
 5 typedef void (*pFun)(void);        //callback 函数指针类型
 6 typedef struct myTimer  7 {  8     char on;                        //开关
 9     char is_period;                    //是否周期循环
 10     unsigned int time_out;    //定时时间,单位ms
 11     unsigned int count;        //定时计数用
 12 }  13 MY_TIMER;  14 
 15 pFun callback[MY_TIMER_MAX] = {NULL};            //定时器回调函数数组
 16 MY_TIMER myTimerList[MY_TIMER_MAX] = {0};        //定时器结构数组
 17 int gMyTimerMessage[MY_TIMER_MAX] = {0};        //定时器消息数组
 18 
 19 sbit LED1=P2^0;  20 sbit LED2=P2^1;  21 sbit LED3=P2^2;  22 sbit LED4=P2^3;  23 sbit LED5=P2^4;  24 
 25 #define ALL_ON {LED1=0;LED2=0;LED3=0;LED4=0;LED5=0;}    //灯全开
 26 
 27 //创建定时器,简化版本。
 28 int CreatTimer(int index,unsigned short int time_out,char is_period,pFun callbackFun)  29 {  30     if(index >= MY_TIMER_MAX) return -1;  31     myTimerList[index].on = 1;  32     myTimerList[index].is_period = is_period;  33     myTimerList[index].time_out = time_out;  34     myTimerList[index].count = 0;  35     callback[index] = callbackFun;  36     return index;  37 }  38 
 39 //四个LED控制函数,on初始是0,第一次调用on变为1,是关灯。
 40 void led_1_ctrl(void)  41 {  42     static char on = 0;  43     on = !on;  44     LED1 = on;  45 }  46 void led_2_ctrl(void)  47 {  48     static char on = 0;  49     on = !on;  50     LED2 = on;  51 }  52 void led_3_ctrl(void)  53 {  54     static char on = 0;  55     on = !on;  56     LED3 = on;  57 }  58 void led_4_ctrl(void)  59 {  60     static char on = 0;  61     on = !on;  62     LED4 = on;  63 }  64 
 65 void led_5_ctrl(void)  66 {  67     static char on = 0;  68     on = !on;  69     LED5 = on;  70 }  71 
 72 void Init_Timer0(void)    //初始化定时器0
 73 {  74     TMOD=0x01;                //定时器0,使用模式1,16位定时器
 75     TH0=(65536-1000)/256;    //给定初值
 76     TL0=(65536-1000)%256;  77     EA=1;        //打开总中断
 78     ET0=1;        //打开定时器中断
 79     TR0=1;        //开定时器
 80 }  81 
 82 void main(void)    //主函数
 83 {  84     unsigned int i;  85 
 86  ALL_ON;  87     
 88     CreatTimer(0,250,1,led_1_ctrl);  89     CreatTimer(1,500,1,led_2_ctrl);  90     CreatTimer(2,1000,1,led_3_ctrl);  91     CreatTimer(3,2000,1,led_4_ctrl);  92     //CreatTimer(4,4000,1,led_5_ctrl);
 93 
 94     Init_Timer0();    //初始化定时器0
 95     while(1)  96  {  97         for(i = 0; i<MY_TIMER_MAX; ++i)  98  {  99             if(gMyTimerMessage[i])            //定时器消息来到,启动。
100  { 101                 gMyTimerMessage[i] = 0;        //消息清除
102                 if(callback[i] != NULL) 103  { 104                     (*callback[i])();        //调用回调函数
105  } 106  } 107  } 108  } 109 } 110 
111 //定时器中断函数,1ms 定时。
112 void Timer0_isr(void) interrupt 1
113 { 114     unsigned int i = 0; 115 
116 
117     TH0=(65536-1000)/256;//重新赋值 1ms
118     TL0=(65536-1000)%256; 119 
120     EA = 0; 121     for(i = 0; i<MY_TIMER_MAX; ++i) 122  { 123         if(myTimerList[i].on)        //如果定时开启
124  { 125             ++(myTimerList[i].count);                                //计数++
126             if(myTimerList[i].count >= myTimerList[i].time_out)        //定时到
127  { 128                 gMyTimerMessage[i] = 1;                                //发消息,在main函数中会用到
129                 if(myTimerList[i].is_period)                        //是否周期循环
130  { 131                     myTimerList[i].count = 0;                        //计数重置
132  } 133                 else
134  { 135                     myTimerList[i].on = 0;                            //关掉定时器
136  } 137  } 138  } 139  } 140     EA = 1; 141 }