51C语⾔中断LED闪烁,单⽚机定时器中断实现LED灯闪烁程序运⽤定时器0⼯作在⽅式1(16位计数器)实现LED灯的闪烁。先来看看定时器0⼯作在⽅式1的逻辑结构图。
从上图可以看到,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就申请定时器中断。
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灯的熄灭或者点亮}
}
好了,到这⾥定时器中断实现LED灯间隔1s闪烁就实现了
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论