用定时器0的方式1实现第一个发光管以200ms间隔闪烁,用定时器1的方式1实现数码管前两位59s循环计时(来自郭天祥老师的51单片机练习)
初始化函数
//初始化函数
void Init()
{
TMOD = 0x11;//两个定时器的工作模式
TH0 = (65536 - 45872) / 256;//T0计时50ms
TL0 = (65536 - 45872) % 256;
TH1 = (65536 - 45872) / 256;//T1计时50ms
TL1 = (65536 - 45872) % 256;
EA = 1;//使能总中断
ET0 = 1;//使能T0中断
ET1 = 1;//使能T1中断
TR0 = 1;//启动T0
TR1 = 1;//启动T1
time = 0;//1s加1计时
}
数码管显示函数
//数码管显示函数
void display()
{
uint ge,shi;
//计算每秒个位与十位的变化
if(t1 == 20)
{
t1 = 0;
time++;
if(time == 60)
{
time = 0;
}
shi = time / 10;//十位
ge = time % 10;//个位
}
//显示十位
WLE = 1;
P0 = 0xfe;
WLE = 0;
P0 = 0xff;//消影
DLE = 1;
P0 = Table[shi];
DLE = 0;
delay_1ms(5);//延时短,达到动态扫描的效果
//显示个位
WLE = 1;
P0 = 0xfd;
WLE = 0;
P0 = 0xff;//消影
DLE = 1;
P0 = Table[ge];
DLE = 0;
delay_1ms(5);//延时短,达到动态扫描的效果
}
延时1ms函数
//延时1ms函数
void delay_1ms(uint z)
{
uint x,y;
for(x = z;x > 0;x--)
{
for(y =110;y > 0;y--){}
}
}
定时器0中断函数
void Timer0() interrupt 1
{
TH0 = (65536 - 45872) / 256;//T0计时50ms
TL0 = (65536 - 45872) % 256;
t0++;
if(t0 == 4)
{
t0 = 0;
led1 = ~led1;
}
}
定时器1中断函数
void Timer1() interrupt 3
{
TH1 = (65536 - 45872) / 256;//T1计时50ms
TL1 = (65536 - 45872) % 256;
t1++;
}
整个项目代码
#include
//【例3.5.2】在 TX-1C 实验板上完成如下功能:用定时器0的方式1实现第一个发光管以200ms间隔闪烁,用定时器1的方式1实现数码管前两位59s循环计时。
//实验板晶振 11.0529MHz
#define uint unsigned int
#define uchar unsigned char
sbit led1 = P1^0;//第一个发光管
sbit WLE = P2^7;//位选
sbit DLE = P2^6;//段选
//数码管的编码表
uchar code Table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
uint t0,t1,time;
void Init();
void LED();
void display();
void delay_1ms(uint z);
void main()
{
Init();
while(1)
{
display();
}
}
//初始化函数
void Init()
{
TMOD = 0x11;//两个定时器的工作模式
TH0 = (65536 - 45872) / 256;//T0计时50ms
TL0 = (65536 - 45872) % 256;
TH1 = (65536 - 45872) / 256;//T1计时50ms
TL1 = (65536 - 45872) % 256;
EA = 1;//使能总中断
ET0 = 1;//使能T0中断
ET1 = 1;//使能T1中断
TR0 = 1;//启动T0
TR1 = 1;//启动T1
time = 0;//1s加1计时
}
//数码管显示函数
void display()
{
uint ge,shi;
//计算每秒个位与十位的变化
if(t1 == 20)
{
t1 = 0;
time++;
if(time == 60)
{
time = 0;
}
shi = time / 10;//十位
ge = time % 10;//个位
}
//显示十位
WLE = 1;
P0 = 0xfe;
WLE = 0;
P0 = 0xff;//消影
DLE = 1;
P0 = Table[shi];
DLE = 0;
delay_1ms(5);//延时短,达到动态扫描的效果
//显示个位
WLE = 1;
P0 = 0xfd;
WLE = 0;
P0 = 0xff;//消影
DLE = 1;
P0 = Table[ge];
DLE = 0;
delay_1ms(5);//延时短,达到动态扫描的效果
}
//延时1ms函数
void delay_1ms(uint z)
{
uint x,y;
for(x = z;x > 0;x--)
{
for(y =110;y > 0;y--){}
}
}
void Timer0() interrupt 1
{
TH0 = (65536 - 45872) / 256;//T0计时50ms
TL0 = (65536 - 45872) % 256;
t0++;
if(t0 == 4)
{
t0 = 0;
led1 = ~led1;
}
}
void Timer1() interrupt 3
{
TH1 = (65536 - 45872) / 256;//T1计时50ms
TL1 = (65536 - 45872) % 256;
t1++;
}
1.不能将led灯的程序写在主函数中。因为,如果led灯的程序写在主函数中,并且led灯亮灭的间隔时间减短(如20ms),数码管每次显示的时间加长(如50ms),在这种情况下,有可能程序进入到数码管的display函数中执行并延时,但此时led灯的程序也到时间该执行,实际上却无法执行,那么t0变量就会一直加下去,之后led灯也就不会改变状态了。(郭天祥老师经验)
2.在数码管的display函数中,段选与位选的显示语句不能写在if语句中,否则数码管的十位会一直闪,不能正常显示。因为当段选与位选的显示语句写在if语句中时,只有t1=20时,才会显示数码管,对于十位数来说,就是短暂的几毫秒,之后就马上会因为个位数的显示而关闭,因而看到的实验现象是十位数隐隐闪现。当段选与位选的显示语句写在if语句外时,主函数的while语句会一直执行display函数,当t1没到20的时候,数码管就一直显示上一秒的值(数码管动态显示),当他t1=20的时候,说明1秒到达,就改变个位ge和十位shi变量的值,数码管显示数值就会更新,加1秒。
写此文章,仅记录自己学习51单片机过程中的一些思考和心得感悟,方便自己之后查阅,也供学习51单片机的小伙伴学习参考~