51C语言中断LED闪烁,单片机定时器中断实现LED灯闪烁程序

运用定时器0工作在方式1(16位计数器)实现LED灯的闪烁。先来看看定时器0工作在方式1的逻辑结构图。

c9d8fb17f9209173199402efc64e5218.png

从上图可以看到,GATE先经过非门,再和INT0引脚作为或门的输入。这里简单提一下数字电路中的与门、或门和非门。顾名思义,与门当且仅当所有输入都位高电平时输出才是高电平,或门只要有其中之一输入是高电平则输出就是高电平,非门的输出电平状态刚好和输入电平状态相反。因此从定时器0方式1的逻辑结构图中,当GATE=0,且TR0=1时,TL0低8位寄存器便在机器周期的作用下开始加1计数。当TL0计满之后向TH0进位,直到TH0也计满,此时再来一个计数,计数器便溢出TF0置1,发出定时器0中断申请。

在清楚定时器的工作方式之后,重点就是如何让定时器定时我们想要的时间呢?这就涉及到定时器的初值问题。定时器一旦启动,便在TL0和TH0原来的基础上开始每隔一个机器周期加1操作直到溢出。假设在程序开始执行时TL0和TH0的初值都是0,单片机的晶振是12MHz,那么该单片机的机器周期就是1us,计满TL0和TH0一共需要(2的16次方减1=65535)个数,再来一个加1就溢出。也就是说定时器最多可以定时的时间是65536us(65.536ms),可想而知如果我们需要定时器能够定时50ms的话,那么TL0和TH0必须有一定的初值。通俗的理解就是定时器的16位计数器是个水桶,这个水桶最多能够倒满65.536斤水,而我们只需要往水桶里到50斤水就把水桶倒满,这个时候水桶里必须要有15.536斤水,这就是初值。

好,这里我们就正式开始如何确定定时器的初值,我们要让定时器定时50ms就产生一次中断,这个时候TL0和TH0装入的总数就是65536-50000=15536,把15536对256取模:15536/256=60装入TH0中,把15536对256求余:15536%256=176装入TL0中。这样就得到我们想要的初值了。

那么为什么这样算呢?之前已经说过定时器0工作在方式1时是16位的计数器,其中TH0是高8位,TL0是低8位,单片机复位时TL0和TH0初值如下图所示,每一位的值都是二进制(要么是0要么是1),当TL0计满之后向TH0进位,TH0计满后再加1就申请定时器中断。

4fe1a6fac64edfbdd0929848b7072054.png

TL0计满一次时8位值都是1,也就是255(2的8次方减1),再来一个加1时TL0全部清零向TH0进位,也就是说此时TL0中的值是0000 0000,而TH0中的值是0000 0001,这个时候是计数256次;同样的等到TL0第二次计满时8位值都是1,再来一个加1时TL0全部清零向TH0进位,也就是说此时TL0中的值是0000 0000,而TH0中的值是0000 0010,这个时候是计数2*256次,依次类推,当计满256*256次时溢出。大家看出规律了吗?

好,我们继续讲任何一种情况,假设TL0中的初值是十进制L,TH0中的初值是十进制H,那么经过(256-L)次计数后TH0中的值加1变成H+1,TL0中的值变成0;再经过256次计数后TH0中的值变成H+2,TL0中的值变成0。依次类推,当TH0加了(256-H)次1时发生溢出,定时器请求中断。

因此一共经过了【(256-H-1)*256+256-L】=(65536-256H-L)次计数定时器请求中断。也就是说定时器中的16位寄存器的初值C=256H+L。

很明显TH0中的初值H=C/256,而TL0中的初值L=C%256,这就推导出来了。

搞定了定时器初值的问题,接下来我们就可以写定时器中断的代码了。

中断服务程序的写法

C51的中断函数格式如下:

void 函数名() interrupt 中断号 using 工作组

{

中断服务程序具体内容

}

中断函数没有返回值和参数,函数名只要符合C语言标准就可以,中断号是指单片机中的中断源序号,是编译器识别不同中断源的唯一凭证,using工作组是指这个中断服务程序使用单片机内存中4组工作寄存器的哪一组,由编译器自动分配,通常我们可以忽略不写。

讲了这么多,终于可以写程序了,是不是有点小激动呢?

#include //包含头文件

sbit led = P0^0;

unsigned char count = 0; //定时累计变量,我们需要1000ms定时,50 * 20 = 1000

//count是全局变量,通俗地说就是程序每次重新执行时值保持住最近一次的值

//后续会专门讲讲C语言的一些基础知识

void main()

{

TMOD = 0x01; //设置定时器0工作方式1,16位计数

TH0 = (65536 - 45872) / 256; //晶振11.0592MHz,定时50ms时TH0初值

TL0 = (65536 - 45872) % 256; //晶振11.0592MHz,定时50ms时TL0初值

EA = 1; //开启总中断

ET0 = 1; //开启定时器0中断

TR0 = 1; //启动定时器0

while(1); //程序停止,等待定时器0中断发生

}

void T0_INT() interrupt 1 //大家对照着上述格式看看

{

TH0 = (65536 - 45872) / 256; //晶振11.0592MHz,定时50ms时TH0初值

TL0 = (65536 - 45872) % 256; //晶振11.0592MHz,定时50ms时TL0初值

//重装初值,这个很好理解,我们需要每次定时的时间相同

count++; //每进入一次中断,也就是说50ms时间到了,count变量进行累计

if(20 == count) //1000ms定时时间到

{

count = 0; //清零,使得可以再次定时1000ms

led = ~led; //P0.0电平取反,也就实现LED灯的熄灭或者点亮

}

}

d5079897820482867c52c252791a654b.png

好了,到这里定时器中断实现LED灯间隔1s闪烁就实现了

  • 12
    点赞
  • 99
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,根据您的要求,我可以为您提供以下的设计方案: 1. 首先,您需要准备8个LED、1个555定时器芯片、1个4017计数器芯片、1个74HC238译码器芯片和一些电阻、电容等元器件。 2. 将8个LED按照交替闪烁的顺序连接起来,即将LED1和LED3、LED5和LED7、LED2和LED4、LED6和LED8两两相连,形成4组。 3. 将每组两个LED的正极分别连接到4017计数器芯片的Q0和Q1引脚、Q2和Q3引脚、Q4和Q5引脚、Q6和Q7引脚,将它们的负极连接到地线。 4. 将555定时器芯片的引脚1连接到正电源,引脚2连接到电容C1,再将电容C1的另一端连接到地线,引脚3连接到电阻R1,再将电阻R1的另一端连接到地线。此时,引脚2和引脚6之间的电压将随时间变化而周期性地上升和下降。 5. 将555定时器芯片的引脚6连接到4017计数器芯片的CLK引脚,引脚5连接到地线。 6. 将74HC238译码器芯片的A、B、C三个输入引脚连接到4017计数器芯片的QA、QB、QC三个输出引脚,作为译码器的选择信号。 7. 将74HC238译码器芯片的Y0-Y7八个输出引脚分别连接到8个LED的正极,将它们的负极连接到地线。 接下来,您需要按照以下步骤进行操作: 1. 调整电阻R1和电容C1的数值,以控制555定时器芯片的工作频率。一般情况下,可选择R1=10kΩ,C1=10μF,使得闪烁频率为1Hz。 2. 当555定时器芯片的输出电压上升时,它将触发4017计数器芯片,使得计数器按照顺序输出Q0、Q1、Q2、Q3、Q4、Q5、Q6、Q7八个引脚的高电平信号。 3. 74HC238译码器芯片根据4017计数器芯片的输出信号,选择相应的LED进行驱动,使其交替闪烁。 这样,您就可以实现八个LED的交替闪烁。需要注意的是,具体的接线步骤和元器件数值还需要根据您的具体电路设计需求进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值