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

程序转载自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 }

 

posted @ 2019-04-20 19:28  wdliming  阅读(969)  评论(0编辑  收藏  举报