要求
-
- 利用keil4软件搭建好实验环境;
- 实现0~99秒的计时,在数码管上显示秒计时数(到达99秒后重新从0开始);按下S2键,暂停计时,按下S3键,继续计时,达到类似秒表的效果;
2.实现秒小数点后第一位和第二位计时数值的显示。
//按下键盘中的S2键,暂停计时;按下S3键,继续计时
//晶振为11.0592MHz
#include<reg52.h>
#define uchar unsigned char
sbit du=P2^6;
sbit we=P2^7;
sbit S2=P3^0;
sbit S3=P3^1;
//halt表示是否暂停,pp是50毫秒计时,m是1秒计时
unsigned char halt,j,k,pp,m,n;
//数码管段选表
uchar code leddata[]= {
0x3F, //"0"
0x06, //"1"
0x5B, //"2"
0x4F, //"3"
0x66, //"4"
0x6D, //"5"
0x7D, //"6"
0x07, //"7"
0x7F, //"8"
0x6F, //"9"
0x77, //"A"
0x7C, //"B"
0x39, //"C"
0x5E, //"D"
0x79, //"E"
0x71, //"F"
0x76, //"H"
0x38, //"L"
0x37, //"n"
0x3E, //"u"
0x73, //"P"
0x5C, //"o"
0x40, //"-"
0x00, //熄灭
0x80 //"."
};
void Delay_Ms(unsigned char i)
{
for(j=i;j>0;j--)
for(k=125;k>0;k--);
}
void display_m(uchar Value_m) //十分位,百分位显示函数
{
du = 1;
P0 = leddata[Value_m/10]; //显示十分位
du = 0;
P0 = 0xff; //清除段码
we = 1;
P0 = 0xbf; //第三位数码管
we = 0;
Delay_Ms(5);
du = 1;
P0 = leddata[Value_m%10]; //显示百分位
du = 0;
P0 = 0xff; //清除段码
we = 1;
P0 = 0x7f; //第四位数码管 如果将P0=0xf6即从左至右让第四个数码管亮,则会引起第一个数码管一起闪亮,影响显示
we = 0; //这里显示为第五位数码管
Delay_Ms(5);
}
void display_n(uchar Value_n) //十位,个位显示函数
{
du = 1;
P0 = leddata[Value_n/10]; //显示十位
du = 0;
P0 = 0xff; //清除段码
we = 1;
P0 = 0xef; //第一位数码管
we = 0;
Delay_Ms(5);
du = 1;
P0 = leddata[Value_n%10]|0x80; //显示个位和小数点
du = 0;
P0 = 0xff; //清除段码
we = 1;
P0 = 0xdf; //第二位数码管
we = 0;
Delay_Ms(5);
}
void keyscan()
{
if(S2==0)
Delay_Ms(10);
if(S2==0) //暂停键按下
{
halt=1;
}
if(S3==0)
halt=0;
}
void main()
{
TMOD=0x01; // 方式1,为16位定时器/计数器
TH0=(65536-12902)/256; //定时器T0初值计算
TL0=(65536-12902)%256;
ET0=1; //允许T0溢出中断
TR0=1; //启动计数器计数的必要条件
EA=1; //所有的中断请求被开放
pp = 0;
m = 0;
while(1)
{
keyscan(); //执行按键扫描函数,是否有按键按下
if(halt==0) //如果没有暂停
{
TR0=1; //启动计数器进入中断
if(pp==1) //10ms时间到 1*14ms=10ms,中断程序中pp++
{ pp=0; //pp清0,等待下一次循环计数
m++; //m是秒计时
if(m>99) //计数10000后,m清0
{
m=0;
n++;
if(n>99)
{
n=0;
}
}
}
display_m(m); display_n(n); //输出m,n的值,然后再做十位个位数字的运算
}
else //如果暂停了
TR0=0; //则停止计数器计数,即停止计数器工作
display_m(m);display_n(n); //仍然输出m,n的值,但数码管显示数字不变化
}
}
void time0() interrupt 1 //进入中断服务程序进行约14ms计时
{ //定时精度<14ms时,数码管无法正常显示,为显示结果,本程序取14ms近似于10ms
TH0=(65536-12902)/256;
TL0=(65536-12902)%256;
pp++;
}
1.当定时精度<14ms时,数码管会出现显示卡顿的问题。
2.此程序所选用的是低四位控制的数码管,而不是高四位,原因在于使用高四位时,第一和第四数码管时会一起闪亮,无法正常显示数字,即使把第四位数码管转移到低四位控制的第一位(八个数码管的第五位),第一个数码管仍无法正常显示。
本设计中可能出现的问题
//按下键盘中的S2键,暂停计时;按下S3键,继续计时
//晶振为11.0592MHz
#include<reg52.h>
#define uchar unsigned char
sbit du=P2^6;
sbit we=P2^7;
sbit S2=P3^0;
sbit S3=P3^1;
//halt表示是否暂停,pp是50毫秒计时,m是1秒计时
uchar halt,j,k,pp, m;
//数码管段选表
uchar code leddata[]= {
0x3F, //"0"
0x06, //"1"
0x5B, //"2"
0x4F, //"3"
0x66, //"4"
0x6D, //"5"
0x7D, //"6"
0x07, //"7"
0x7F, //"8"
0x6F, //"9"
0x77, //"A"
0x7C, //"B"
0x39, //"C"
0x5E, //"D"
0x79, //"E"
0x71, //"F"
0x76, //"H"
0x38, //"L"
0x37, //"n"
0x3E, //"u"
0x73, //"P"
0x5C, //"o"
0x40, //"-"
0x00, //熄灭
0x80 //"."
};
void Delay_Ms(unsigned char i)
{
for(j=i;j>0;j--)
for(k=125;k>0;k--);
}
void display(uchar Value)
{
du = 1;
P0 = leddata[Value/1000]; //显示十位
du = 0;
P0 = 0xff; //清除段码
we = 1;
P0 = 0xfe; //第一位数码管
we = 0;
Delay_Ms(5);
du = 1;
P0 = leddata[Value%1000/100]|0x80; //显示个位和小数点
du = 0;
P0 = 0xff; //清除段码
we = 1;
P0 = 0xfd; //第二位数码管
we = 0;
Delay_Ms(5);
du = 1;
P0 = leddata[Value%1000%100/10]; //显示十分位
du = 0;
P0 = 0xff; //清除段码
we = 1;
P0 = 0xfb; //第三位数码管
we = 0;
Delay_Ms(5);
du = 1;
P0 = leddata[Value%1000%100%10]; //显示百分位
du = 0;
P0 = 0xff; //清除段码
we = 1;
P0 = 0xf6; //第四位数码管
we = 0;
Delay_Ms(5);
}
void keyscan()
{
if(S2==0)
Delay_Ms(10);
if(S2==0) //暂停键按下
{
halt=1;
}
if(S3==0)
halt=0;
}
void main()
{
TMOD=0x01;
TH0=(65536-46080)/256;
TL0=(65536-46080)%256;
ET0=1;
TR0=1;
EA=1;
pp = 0;
m = 0;
while(1)
{
keyscan();
if(halt==0) //如果没有暂停
{
TR0=1;
if(pp==1) //1s时间到
{ pp=0;
m++; //m是秒计时
// if(m>9999)
// {
// m=0;
// }
}
display(m);
}
else //如果暂停了
TR0=0;
display(m);
}
}
void time0() interrupt 1 //50ms计时
{
TH0=(65536-46080)/256;
TL0=(65536-46080)%256;
pp++;
}
这段程序的问题在于用一个量表示四位数,然而C51所使数码管能显示最大数为255,到256(2^6)就自动归零了。
|