1.基础知识
1.1、中断源
中断源符号 | 名称 | 中断引起原因 | 中断号 |
---|---|---|---|
/INT0 | 外部中断0 | P3.2引脚低电平或下降沿信号 | 0 |
T0 | 定时器0中断 | 定时,计数器0计数回0溢出 | 1 |
/INT01 | 外部中断1 | P3.3引脚低电平或下降沿信号 | 2 |
T1 | 定时器1中断 | 定时/计数器1计数回0溢出 | 3 |
TI/RI | 串行口中断 | 串行通信完成一帧数据发送或接收引起中断 | 4 |
1.2、定时器中断
设置模式:这里用的是定时器0中断,中断模式为1。
void zhongduan()
{
TMOD=0x01;
TH0=(65536-45872)/256;
TL0= (65536-45872)%256;
EA=1;
ET0=1;
TR0=1;
}
(1)TMOD=0x01 表示设置计时器 0 为工作方式 1,这种方式使用计数器模式,并且计数器的值被装入 TH0 和 TL0 寄存器中。
(2)TH0=(65536-45872)/256 和 TL0=(65536-45872)%256 是设置定时器计数初值的代码。65536是2的16次方,定时器是加1计数器16位。晶振为11.0592,故所记次数应为45872,计时器每隔50000(50ms)微秒发起一次中断。45872的来历,为(50000/(12*(1/11.0592M))
(3)EA=1,ET0=1,TR0=1 是开启中断的代码。EA 表示总中断使能开关,设置为 1 时表示打开所有中断。ET0 表示定时器 0 的中断使能开关,设置为 1 时表示打开定时器 0 中断。TR0 表示定时器 0 的运行控制开关,设置为 1 时表示启动定时器 0 的计数器开始计时。
void Time0() interrupt 1
{
TH0=(65536-45872)/256 ;
TL0=(65536-45872)%256 ;
count++;
}
在程序的结束,要重新设置定时器0的重载值,以便定时器可以继续计时并产生下一个中断。由于定时器的工作方式是在计数器减到0时产生中断,因此每次产生中断后都需要重新设置定时器的重载值,从而控制中断的时间间隔。这里的值根据定时器的时钟频率和所需的中断时间间隔计算而得。
2、代码
2.1、宏定义、头文件与延时
大多数程序都会用到,前面的博客有说,这里就不说了
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit duan=P2^6;
sbit wei =P2^7;
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
0x07,0x7f,0x6f};
uchar shijian ,deng = 2;
uchar count;
//延时
void delay(uint k)
{
uint i,j;
for(i=0;i<k;i++)
{
for(j=0;j<113;j++)
{
;
}
}
}
解释一下这里的全局变量count,是计数用的,是整个程序定时的关键。
变量deng就是指灯的意思,将deng初始化为2是因为最开始需要亮绿灯,因此将deng设置为2,表示初始状态为绿灯。如果将deng初始值设置为其他数字,例如0或1或3,则初始状态为红灯、黄灯或黄灯(绿灯和黄灯之间的转换),这都不符合交通信号灯的正常工作流程,因此将deng初始值设置为2最合适。(不懂得话。可以看一下后面的红绿灯程序的switch,case)
2.2、数码管显示
void display(uchar a,b)
{
P0=0xfb;
wei=1;
wei=0;
P0=table[a];
duan=1;
duan=0;
delay(5);
P0=0xf7;
wei=1;
wei=0;
P0=table[b];
duan=1;
duan=0;
delay(5);
}
这段代码实现了数码管的显示功能。在这里,a和b分别是需要显示的十位数和个位数。具体的显示流程是:
选择第一个数码管(P0=0xfb),并将要显示的十位数写入P0口。
打开第一个数码管的使能(wei=1),并在一段时间后关闭(wei=0)。
选择第二个数码管(P0=0xf7),并将要显示的个位数写入P0口。
打开第二个数码管的使能(wei=1),并在一段时间后关闭(wei=0)。
在每个数码管的使能开启后,相应的数字通过将数码管段选(duan)开启来实现。而在开启使能和关闭使能之间需要适当的延时,以确保数字能够正确显示。
段选根据端口连线
2.3、中断部分在本文第一部分讲过了,这里不在赘述
void zhongduan()
{
TMOD=0x01;
TH0=(65536-45872)/256;
TL0= (65536-45872)%256;
EA=1;
ET0=1;
TR0=1;
}
2.4、红绿灯显示
void redgreenyellow()
{
uchar shi,ge;
if(shijian==0)
{
switch(deng)
{
case 0:shijian=10;deng=1;break;//红灯
case 1:shijian=5;deng=2;break; //黄灯
case 2:shijian=10;deng=3;break;//绿灯
case 3:shijian=5;deng=0;break; //黄灯
}
switch(deng)
{
case 1:P1=0xfc;break;//红灯
case 2:P1=0xcf;break; //黄灯
case 3:P1=0xf3;break;//绿灯
case 0:P1=0xcf;break; //黄灯
}
}
shi = shijian/10;
ge = shijian%10;
display(shi,ge);
if(count==20)
{
count=0;
shijian--;
}
}
这段代码实现了红绿灯的控制和倒计时显示的功能。具体来说,代码中定义了两个变量 shi 和 ge 分别表示时间的十位数和个位数。在 if (shijian==0) 语句块中,程序首先根据当前的红绿灯状态 deng 设置下一个状态,并更新相应的倒计时时间 shijian。然后根据新的红绿灯状态 deng 在数码管上显示相应的时间。最后,程序检测到 count 的值为 20 时,说明经过了 20 次中断周期,即 1 秒钟,此时将 shijian 减一,更新时间,并将 count 重置为 0,以便下一次计时。
需要注意的是,代码中对 deng 变量的值进行了多次判断和修改。这是因为程序需要根据当前的红绿灯状态来决定下一个状态,所以需要不断地对 deng 变量进行判断和修改。
同时,注意一个小细节case空格0!!
2.5、主程序
这里比较简单,是对其他程序的综合调用
//主函数
void main()
{
zhongduan();
while(1)
{
redgreenyellow();
}
}
2.6、小尾巴
最后一点,是中断程序服务程序非常重要,没有它,前面的不能实现定时功能
void Time0() interrupt 1
{
TH0=(65536-45872)/256 ;
TL0=(65536-45872)%256 ;
count++;
}
在这个程序中,中断服务程序是通过定时器中断触发的,每当定时器溢出时,中断服务程序会被执行一次。在这个中断服务程序中,count变量的作用是用来计时的。每次中断服务程序被执行时,count的值会加1,这样可以通过累加count的值来计算时间。在这个程序中,count的单位是50毫秒,所以count累加20次就代表1秒过去了。
3.完整代码文章来源:https://www.toymoban.com/news/detail-476790.html
//红绿灯,需要用到的模块有数码管显示秒数,定时中断,以及相应的灯。
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit duan=P2^6;
sbit wei =P2^7;
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
0x07,0x7f,0x6f};
uchar shijian ,deng = 2;
uchar count;
//延时
void delay(uint k)
{
uint i,j;
for(i=0;i<k;i++)
{
for(j=0;j<113;j++)
{
;
}
}
}
//数码管显示部分
void display(uchar a,b)
{
P0=0xfb;
wei=1;
wei=0;
P0=table[a];
duan=1;
duan=0;
delay(5);
P0=0xf7;
wei=1;
wei=0;
P0=table[b];
duan=1;
duan=0;
delay(5);
}
//中断部分,采用定时器中断0
void zhongduan()
{
TMOD=0x01;
TH0=(65536-45872)/256;
TL0= (65536-45872)%256;
EA=1;
ET0=1;
TR0=1;
}
//红绿灯显示模块
void redgreenyellow()
{
uchar shi,ge;
if(shijian==0)
{
switch(deng)
{
case 0:shijian=10;deng=1;break;//红灯
case 1:shijian=5;deng=2;break; //黄灯
case 2:shijian=10;deng=3;break;//绿灯
case 3:shijian=5;deng=0;break; //黄灯
}
switch(deng)
{
case 1:P1=0xfc;break;//红灯
case 2:P1=0xcf;break; //黄灯
case 3:P1=0xf3;break;//绿灯
case 0:P1=0xcf;break; //黄灯
}
}
shi = shijian/10;
ge = shijian%10;
display(shi,ge);
if(count==20)
{
count=0;
shijian--;
}
}
//主函数
void main()
{
zhongduan();
while(1)
{
redgreenyellow();
}
}
void Time0() interrupt 1
{
TH0=(65536-45872)/256 ;
TL0=(65536-45872)%256 ;
count++;
}
4.运行结果
动态的,截几个图演示一下。
文章来源地址https://www.toymoban.com/news/detail-476790.html
到了这里,关于单片机——交通灯(定时器中断)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!