文章目录
一、倒计数的实现
1、原理分析
倒计数的段选信号需要由一个数组存放起来:
code uchar table[]={0x6F, 0x7F, 0x07, 0x7D, 0x6D, 0x66, 0x4F, 0x5B, 0x06, 0x3F};
然后需要用到定时器中断来实现数值的计算,所以要先初始化定时器,此处只用了一个定时器中断0;其实也可以由两个定时器中断来实现,只是需要两个中断服务函数来做,也就是一个典型的计数器。
初始化定时中断0:
void Init()
{
TMOD = 0x02;
ET0 = 1; //可用定时器0
TR0 = 1; //运行定时器0
TH0 = 156;
TL0 = 156;
EA = 1;
}
在定时器中断0服务函数中对数值进行计算,来统计时间:
void timer() interrupt 1
{
t++;
if(t==10000) //说明1秒时间到
{
t=0;
shu++;
if(shu==100) //进位到99,则重新置零
{
shu=0;
}
m= shu%10; //得到个位下标
n= shu/10; //得到十位下标
}
}
2、完整参考代码
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
void Init(); //时钟初始化
void dis(uint m, uint n); //显示函数
void delay(uint x);
sbit dula= P2^6;
sbit wela= P2^7;
// 9到0的段选信号
code uchar table[]={0x6F, 0x7F, 0x07, 0x7D, 0x6D, 0x66, 0x4F, 0x5B, 0x06, 0x3F};
uint m=0, n=0; //表示个位、十位的下标
uint t=0; //中间变量
uint shu=0; //表示具体的个位、十位数字
//初始化定时器
void Init()
{
TMOD = 0x02;
ET0 = 1; //可用定时器0
TR0 = 1; //运行定时器0
TH0 = 156;
TL0 = 156;
EA = 1;
}
void dis(uint i, uint j) //显示数码管函数
{
dula= 1;
P0= table[i]; //个位
dula= 0;
P0= 0xFF;
wela= 1;
P0= 0x7F;
wela= 0;
delay(1);
dula= 1;
P0= table[j]; //十位
dula= 0;
P0= 0xFF;
wela= 1;
P0= 0xBF;
wela= 0;
delay(1);
}
//定义延时函数
void delay(uint x)
{
uint i, j;
for(i=x; i>0; i--)
for(j=110; j>0; j--) ;
}
void main()
{
Init();
while(1)
{
dis(m, n);
}
}
// 定时器中断0服务函数 ,用来计时
void timer() interrupt 1
{
t++;
if(t==10000) //说明1秒时间到
{
t=0;
shu++;
if(shu==100) //进位到99,则重新置零
{
shu=0;
}
m= shu%10; //得到个位下标
n= shu/10; //得到十位下标
}
}
二、停表的实现
1、核心部分
//数值计算,同时也是下标的计算
sign[0]= ms%10; //毫秒个位
sign[1]= ms/10; //毫秒十位
sign[2]= s%10; //秒个位
sign[3]= s/10; //秒十位
sign[4]= m%10; //分钟个位
sign[5]= m/10; //分钟十位
此处为数值的下标计算,sign数组存放的就是现实分-秒-毫秒的数值下标,同时也是对应数码管需要显示数字的下标。
2、一个倒计时停表的实现
#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
void delay(uint x);
void dis();
void dis_gang();
sbit dula= P2^6;
sbit wela= P2^7;
code uchar table[]= {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
uchar sign[]={0, 0, 0, 0, 0, 0}; //控制6位数
uint ms=0, s=0, m=0; //分别表示毫秒,秒,分钟
uint num=0; //中间变量
void Init()
{
TMOD= 0x02; //设置定时器0的工作方式,即为设置为(0001 0010)
ET0= 1; //开定时器0中断
TR0= 1; //定时器0运行允许
TH0= 156; //重装初值高八位
TL0= 156; //重装初值第八位
EA= 1; //开启总中断
}
//定义显示数码管的函数u
void dis(uint i, uchar addr)
{
dula= 1;
P0= table[i];
dula= 0;
P0= 0xFF;
wela= 1;
P0= addr;
wela= 0;
delay(1);
}
//定义显示横杆的函数
void dis_gang() //在数字交界显示横杠
{
wela = 1;
P0 = 0xDB; //第3位和第6位
wela = 0;
dula = 1;
P0 = 0x40; //一个杠
dula = 0;
delay(1);
}
//定义延时函数
void delay(uint x)
{
uint i, j;
for(i=x; i>0; i--)
for(j=110; j>0; j--);
}
//定义主函数
void main()
{
Init();
while(1)
{
dis(sign[0], 0x7F); //毫秒个位
dis(sign[1], 0xBF);
dis(sign[2], 0xEF);
dis(sign[3], 0xF7);
dis(sign[4], 0xFD);
dis(sign[5], 0xFE);
dis_gang(); //显示横杆,延时极短,利用人眼的视觉残留效果实现同时显示
}
}
void timer() interrupt 1 //定时器0中断
{
num++; //每次触发定时器,就将n计数加1
if(num==167) //当计数到10000次,10000是1秒,则10000/60=167
{
num=0; //就将计数值清零,得到毫秒
ms++;
if(ms==60) //当毫秒达到60
{
ms=0; //将毫秒位清零,再将秒位加1操作
s++;
if(s==60) //当秒位达到60后
{
s=0; //将秒位清零,在将分钟位加1操作
m++;
if(m==60) //若分位达到60
{
m=0; //则将分钟为清零
}
}
}
//数值计算,同时也是下标的计算
sign[0]= ms%10; //毫秒个位
sign[1]= ms/10; //毫秒十位
sign[2]= s%10; //秒个位
sign[3]= s/10; //秒十位
sign[4]= m%10; //分钟个位
sign[5]= m/10; //分钟十位
}
}