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

发布者:祝福的4号最新更新时间:2024-04-15 来源: elecfans关键字:51定时器  led 手机看文章 扫描二维码
随时随地手机看文章

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


关键字:51定时器  led 引用地址:51定时器控制4个led,使用回调函数机制

上一篇:keil c51和keil mdk的共存方式
下一篇:8052频率计(计数器2和定时器0的结合)

推荐阅读最新更新时间:2024-11-11 16:59

51单片机C语言程序(五) 时钟程序(用定时器
#include reg52.h #define uchar unsigned char #define uint unsigned int sbit dula=P2^6; sbit wela=P2^7; sbit rs=P3^5; sbit lcden=P3^4; sbit s1=P3^0; sbit s2=P3^1; sbit s3=P3^2; sbit rd=P3^7; uchar count,s1num; char miao,shi,fen; uchar code table = 2009-7-13 MON ; uchar code table1 = 00:00:00 ; void delay(uint z) {
[单片机]
生迪Element LED灯泡采用Silicon Labs zigbee®技术实现IoT连接
Silicon Labs(亦名“芯科科技”,NASDAQ:SLAB)宣布为中囯生迪公司(Sengled)屡获殊荣的Element可连接灯泡提供最佳的zigbee®技术。Silicon Labs的无线SoC和zigbee协议栈使得Element灯泡能够轻松地连接到部署在智能家庭中的多节点网状网络。生迪开发和制造集成消费电子和节能LED灯泡的智能照明产品,通过iOS和Android应用程序或流行的智能家居生态系统,消费者可以单独或成组的控制Element灯泡、定制一系列智能照明功能、按照规划的时间自动地在夜晚开灯或白天关灯以节省能耗。   生迪的研发副总经理孙超群表示:“简单、可靠的无线连接是Element灯泡在市场上取得成功的关键所
[网络通信]
FPGA为设计平台的全彩led显示屏设计方案
介绍了一种以FPGA 可编程逻辑器件为设计平台的、采用大屏幕全彩led 显示屏进行全彩灰度图像显示的扫描控制器实现方案。经过对“19 场扫描”理论灰度实现原理的分析,针对采用该方法实现的全彩LED 显示屏刷新频率受串行移位时钟限制的缺点,提出了一种新式的实现高阶灰度显示的逐位点亮控制方法,在进行FPGA 电路设计中采用单独的计数器来控制屏幕的刷新频率,使全彩LED 显示屏的设计在L ED 的发光效率和刷新率之间的调整更加灵活。最后,根据大屏幕全彩LED 显示屏的设计要求,结合本文讨论的灰度控制方法,给出了FPGA 屏体扫描控制器的内部电路实现结构框架。   1 、引言   作为大型平板显示设备的一种,LED 显示屏以其
[电源管理]
FPGA为设计平台的全彩<font color='red'>led</font>显示屏设计方案
【蓝桥杯物联网】第四章 ​点亮一个LED
第一节硬件解读 任何一个实验都是从点亮一个LED开始的,本次将教大家如何用stm32cubeMX+MDK在蓝桥杯物联网开发板上面点亮一个LED。 先看蓝桥杯物联网的原理图:从图中可以看出PC15引脚连接到LD5的负极的一段,正级连接了一个510欧姆的电阻用来限流,保护电路,整个是一个简单的串联电路,并用3.3V的直流电供电。当PC15引脚输出低电平,LD5点亮;反之,LD5熄灭。 第二节配置环境 1,打开stm32cubeMX,选择“File-New Project ...”。 2,如图,在方框中搜索“L071KB”(可大写,可小写)。然后选择UFQFPN32的封装的芯片。 3,选中“A-Z”,查看蓝桥杯物联网芯
[单片机]
【蓝桥杯物联网】第四章 ​点亮一个<font color='red'>LED</font>
采用LED大灯将成为汽车设计新趋势
    从前,LED大灯只能在豪华车上见到,现在,这项配置也逐渐下放到其他级别车型中。     德国光源产品公司欧司朗(Osram)预计,今年,全球生产的新车中仅有2%配备LED大灯,而这项数字到2020年将变成20%。     LED尾灯和日间行车灯是汽车设计师们的最爱,他们利用LED灯的特点塑造出结构层次分明、具有水晶质感的车灯系统。     汽车制造商青睐LED灯的原因之一是其耐久性强、结构紧凑、高效节能,不过LED灯的成本相对较高。一个卤素大灯的成本大约20美元,一个疝气大灯大灯的成本在60-80美元之间。而LED大灯的成本虽然呈下滑趋势,但目前仍旧达到疝气大灯的两倍。     LED灯全称发光二
[汽车电子]
LED灯带安装及使用注意事项
LED 灯带是指把LED组装在带状的FPC(柔性线路板)或PCB硬板上,因其产品形状象一条带子一样而得名。因为使用寿命长(一般正常寿命在8~10万小时)、绿色环保而逐渐在各种装饰行业中崭露头角。如今,越来越多的人喜爱使用LED灯带,下面就由小编为您介绍LED灯带的简易安装方法。   LED灯带用于室内装饰时,由于不必经受风吹雨打,所以安装就非常简单。以必拓生产的LED灯带为例,每款LED灯带的背后都贴有自粘性3M双面胶,安装时可以直接撕去3M双面胶表面的贴纸,然后把灯条固定在需要安装的地方,用手抚平就好了。至于有的地方需要转角或者是长了怎么办?很简单,LED灯带是以3个LED为一组的串并联方式组成的电路结构,每3颗LED即可以剪
[电源管理]
Mini2440 裸机实验之LED程序、按键、中断
测试平台:Mini2440 Win7 64 ADS开发环境测试 此程序主要考虑按键、LED点亮、中断模式(IRQ)之间的联系 以下为main.c代码部分,其他请参考三星提供的2440用例代码 #define GLOBAL_CLK 1 #include stdlib.h #include string.h #include def.h #include option.h #include 2440addr.h #include 2440lib.h #include 2440slib.h #include mmu.h #include profile.h #include memtest.h /
[单片机]
Mini2440 裸机实验之<font color='red'>LED</font>程序、按键、中断
欧司朗从照明到光子学:整合数字业务,加大应用领域投资
2018年11月7日,欧司朗公布了2018财报的同时,CEO Olaf Berlien再次强调,公司将要更加侧重数字化与未来市场,已经通过调整事业部结构,从而迎接从照明到光子学(Photonics)时代的到来。 光子学(Photonics)研究始于1960年激光的发明,随后的其他发展则包括:20世纪70年代的激光二极管,用于传输信息的光纤和掺铒光纤放大器。这些发明构成了20世纪后期电信革命的基础,并为互联网提供了基础设施。 同样的,欧司朗的光子学战略也是瞄准了信息革命技术,为了推动光子学在各个领域的发展,欧司朗不光是生产光子学最基本的激光发射器、LED等产品,更是推出了众多集成化的应用,加速光子学商用时代的到来。 为此,欧司朗也推
[电源管理]
欧司朗从照明到光子学:整合数字业务,加大应用领域投资
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved