程序转载自51hei,经过自己的实际验证,多了一种编程的思路技能,回调函数的基本思想也是基于事件机制的,哪个事件来了, 就执行哪个事件。
程序中,最多四个子定时器,说明51的处理速度是不够的,在中断中添加过多的代码会定时不准确。自己实验了5个,第五个想要定时4秒,实际差不多有5秒了,因此中断里面是代码越少越好~~
1 #include
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 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 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 }
上一篇:keil c51和keil mdk的共存方式
下一篇:8052频率计(计数器2和定时器0的结合)
推荐阅读最新更新时间:2024-11-11 16:59
设计资源 培训 开发板 精华推荐
- LT3091IT7 无镇流器负载共享的典型应用(使用 IMONP)
- LT1317CMS8 2V 至 3.3V 转换器的典型应用电路
- AM2LS-2405S-NZ 5V 2W DC-DC 转换器的典型应用
- 观赏鱼缸控制器
- 用于运动电机控制的差分放大器
- LTM4647IY 的典型应用电路 典型 6V 至 15V 输入 1.0V at 30A 输出设计
- LTM8052IV 36Vin、12Vout 降压型 CVCC 转换器的典型应用
- MC78M05CDTT5G 5V升压稳压器典型应用
- STEVAL-ILL002V2,基于 STP08CDC596 LED 驱动器的检测 LED 矩阵评估套件
- WIFI天气时钟