zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    动态库的链接和链接选项-L,-rpath-link,-rpath
    SSL/TLS 握手过程详解
    数字证书及CA介绍
    sendto函数的坑
    如何捕捉并分析SIGSEGV的现场
    gdb进程调试,多进程调试
    linux下的守护进程daemon
    winform的水印TextBox
    Winform中的TextBox的小技巧
    WebForms UnobtrusiveValidationMode 需要“jquery”ScriptResourceMapping。请添加一个名为 jquery (区分大小写)的 ScriptRes
  • 原文地址:https://www.cnblogs.com/CodeWorkerLiMing/p/10742313.html
Copyright © 2011-2022 走看看