昨天同学问我能不能帮他做道题,有关单片机定时器的,我大概写了一个小时把这道题完成了,写这篇博客记录练习和学习的历程。
使用的是普中科技的A2开发板。
题目
数码管秒表设计
任务1,能够操作数码管显示任意数字
任务2,在数码管的第1、2位显示秒数,第3位显示“-”,第4位显示1/10秒,第5位显示1/100秒。
任务3,按下独立按键K1后,秒表开始计时,再次按下独立按键K1后,秒表停止,按下独立按键K2后,秒表计数清零。
分析: 完成这个题目需要运用中断、独立键盘和数码管的相关知识。
我的代码
#include"reg52.h"
typedef unsigned int u16; //偷懒
typedef unsigned char u8;
u8 code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//数码管显示0-9的段选的数值
int sec; //定义秒变量
int msec; //定义毫秒变量
int count;//定义计时器溢出变量
sbit LSA=P2^2; //定义数码管位选的引脚
sbit LSB=P2^3;
sbit LSC=P2^4;
sbit k1=P3^1; //定义独立键盘的引脚
sbit k2=P3^0;
/*
名称:delay
作用:延时
*/
void delay(u16 z)
{
u16 x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
/*
名称:sec_display
作用:数码管上秒的十位和个位数的显示
*/
void sec_display(int second)
{
LSA=1;//数码管位选,下皆同
LSB=1;
LSC=1;
P0=smgduan[second/10];//显示秒的十位
delay(10);
//短暂延时,下同,在这里延时的时间越短,刷新的频率越高,看起来数码管闪烁的程度就越弱
P0=0x00;//消隐,下同
LSA=0;
LSB=1;
LSC=1;
P0=smgduan[second%10];
delay(10);
P0=0x00;
}
/*
名称:mirco_display
作用:数码管上1/10秒和1/100秒的显示
*/
void mirco_display(int x)
{
msec=x*50;//count加1,大约是50ms,这里x是后面输入的count
LSA=0;
LSB=0;
LSC=1;
P0=smgduan[msec/100];
delay(10);
P0=0x00;
LSA=1;
LSB=1;
LSC=0;
P0=smgduan[msec%100/10];
delay(10);
P0=0x00;
}
/*
名称:sta_display
作用:数码管上分隔符"-"的显示
*/
void sta_display()
{
LSA=1;
LSB=0;
LSC=1;
P0=0x40;
delay(10);
P0=0x00;
}
/*
名称:init
作用:定时器初始化,包括:确定定时器工作方式,打开总中断,装入初始值等,但是在这里定时器0一开始是关闭的,对应题目要求的按下键盘才开始计时
*/
void init()
{
TMOD=0x01; //确定定时器工作方式
EA=1; //打开总中断
ET0=1;
TR0=0; //关闭定时中断0
TH0=(65536-50000)/256; //装入初始值
TL0=(65536-50000)%256;
}
/*
名称:keyscan
作用:键盘检测,使用循环扫描的方式来检测是否有按键输入
*/
void keyscan()
{
if(k1==0) //检测到按键1按下
{
delay(50); //短暂延时,消除抖动
if(k1==0)
{
TR0=~TR0; //定时器状态取反,按下一次是打开,再按一次是关闭
while(!k1);//检测到松手
}
}
if(k2==0) //检测到按键2按下
{
delay(50); //短暂延时,消除抖动
if(k2==0)
{
count=0;//数值归零,以达到显示归零的效果
sec=0;
while(!k2);//检测到松手
}
}
}
/*
名称:主函数
作用:程序的主体
*/
void main()
{
init();//初始化
while(1)//进入死循环
{
keyscan();
sta_display();
sec_display(sec);
mirco_display(count);
}
}
/*
名称:timer0
作用:定时器中断
*/
void timer0() interrupt 1
{
TH0=(65536-50000)/256;//装入初始值
TL0=(65536-50000)%256;
count++; //约50ms,count加1
if(count==20) //count加20次,即1000ms=1s,秒加一
{
count=0; //count归零
sec++;
if(sec==60) //当s到达60,s归零
sec=0;
}
}