要求
在单片机综合训练平台上,利用定时器T0、数码管模块、2个独立按键,设计一个秒表,具有清零、暂停、启动的功能。
1.显示格式为:分-秒-0.05秒(即50毫秒)
2.按键S4为:暂停/启动
3.按键S5为:清零
电路图
代码
实现秒表功能
使用定时器实现秒表功能,要点是在毫秒位用累加的方式,函数在中断服务函数里面编写。
一般定时器中断服务函数都要说明一个变量,用于累加。
/*定义变量来保存分、秒、毫秒*/
unsigned char t_m = 0; /*分*/
unsigned char t_s = 0; /*秒*/
unsigned char t_005s = 0; /*50毫秒*/
void ServiceTimer0() interrupt 1
{
TH0 = (65535 - 50000) / 256;
TL0 = (65535 - 50000) % 256;
t_005s++;
if(t_005s == 20)
{
t_s++;
t_005s = 0;
if(t_s == 60)
{
t_m++;
t_s = 0;
}
if(t_m == 99)
{
t_m = 0;
}
}
}
秒表在数码管上显示
数码管显示的代码其实很简单,就是从第7位开始:一位显示函数+延时
其中,数码管显示函数必背!
/*======数码管显示函数======必背!*/
void DisplaySMG_Bit(unsigned char value, unsigned char pos)
{
SelectHC573(6);
P0 = 0x01 << pos;
SelectHC573(7);
P0 = value;
}
/*=======设置数码管显示内容========*/
void DelaySMG(unsigned int t)
{
while(t--);
}
void DisplayTime()
{
DisplaySMG_Bit(SMG_NoDot[t_005s%10],7);
DelaySMG(500);
DisplaySMG_Bit(SMG_NoDot[t_005s/10],6);
DelaySMG(500);
DisplaySMG_Bit(SMG_NoDot[16],5);
DelaySMG(500);
DisplaySMG_Bit(SMG_NoDot[t_s%10],4);
DelaySMG(500);
DisplaySMG_Bit(SMG_NoDot[t_s/10],3);
DelaySMG(500);
DisplaySMG_Bit(SMG_NoDot[16],2);
DelaySMG(500);
DisplaySMG_Bit(SMG_NoDot[t_m%10],1);
DelaySMG(500);
DisplaySMG_Bit(SMG_NoDot[t_m/10],0);
DelaySMG(500);
}
按键扫描
注意:1.实现启动/暂停:TR0 = ~TR0;
2.实现清零:t_005s = 0; t_s = 0;t_m = 0;
3.最后要有松开的代码编写,实现动态扫描
/*=======按键扫描函数=======*/
/*按键延时函数*/
void DelayK(unsigned char t)
{
while(t--);
}
void ScanKeys()
{
if(S4 == 0) //秒表启动与暂停
{
DelayK(100);
if(S4 == 0)
{
TR0 = ~TR0; //重要!实现启动/暂停
/*实现动态扫描,避免误操作122-125*/
while(S4 == 0)
{
DisplayTime();
}
}
}
if(S5 == 0) //秒表清零
{
DelayK(100);
if(S5 == 0)
{
t_005s = 0;
t_s = 0;
t_m = 0;
/*实现动态扫描,避免误操作138-141*/
while(S5 == 0)
{
DisplayTime();
}
}
}
}
完整代码
#include"reg52.h"
sbit S4 = P3^3;
sbit S5 = P3^2;
/*定义变量来保存分、秒、毫秒*/
unsigned char t_m = 0; /*分*/
unsigned char t_s = 0; /*秒*/
unsigned char t_005s = 0; /*50毫秒*/
unsigned char code SMG_NoDot[18] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};
void SelectHC573(unsigned char channel)
{
switch(channel)
{
case 4:
P2 = (P2 & 0x1f) | 0x80;
break;
case 5:
P2 = (P2 & 0x1f) | 0xa0;
break;
case 6:
P2 = (P2 & 0x1f) | 0xc0;
break;
case 7:
P2 = (P2 & 0x1f) | 0xe0;
break;
}
}
/*======数码管显示函数======必背!*/
void DisplaySMG_Bit(unsigned char value, unsigned char pos)
{
SelectHC573(6);
P0 = 0x01 << pos;
SelectHC573(7);
P0 = value;
}
/*=============定时器函数===========*/
/*=======定时器初始化=====*/
void InitTimer0()
{
TMOD = 0x01;
TH0 = (65535 - 50000) / 256;
TL0 = (65535 - 50000) % 256;
ET0 = 1;
EA = 1;
TR0 = 1;
}
/*=======中断服务函数:定时器实现秒表的功能=======*/
void ServiceTimer0() interrupt 1
{
TH0 = (65535 - 50000) / 256;
TL0 = (65535 - 50000) % 256;
t_005s++;
if(t_005s == 20)
{
t_s++;
t_005s = 0;
if(t_s == 60)
{
t_m++;
t_s = 0;
}
if(t_m == 99)
{
t_m = 0;
}
}
}
/*=======设置数码管显示内容========*/
void DelaySMG(unsigned int t)
{
while(t--);
}
void DisplayTime()
{
DisplaySMG_Bit(SMG_NoDot[t_005s%10],7);
DelaySMG(500);
DisplaySMG_Bit(SMG_NoDot[t_005s/10],6);
DelaySMG(500);
DisplaySMG_Bit(SMG_NoDot[16],5);
DelaySMG(500);
DisplaySMG_Bit(SMG_NoDot[t_s%10],4);
DelaySMG(500);
DisplaySMG_Bit(SMG_NoDot[t_s/10],3);
DelaySMG(500);
DisplaySMG_Bit(SMG_NoDot[16],2);
DelaySMG(500);
DisplaySMG_Bit(SMG_NoDot[t_m%10],1);
DelaySMG(500);
DisplaySMG_Bit(SMG_NoDot[t_m/10],0);
DelaySMG(500);
}
/*=======按键扫描函数=======*/
/*按键延时函数*/
void DelayK(unsigned char t)
{
while(t--);
}
void ScanKeys()
{
if(S4 == 0) //秒表启动与暂停
{
DelayK(100);
if(S4 == 0)
{
TR0 = ~TR0; //重要!实现启动/暂停
/*实现动态扫描,避免误操作122-125*/
while(S4 == 0)
{
DisplayTime();
}
}
}
if(S5 == 0) //秒表清零
{
DelayK(100);
if(S5 == 0)
{
t_005s = 0;
t_s = 0;
t_m = 0;
/*实现动态扫描,避免误操作138-141*/
while(S5 == 0)
{
DisplayTime();
}
}
}
}
void main()
{
InitTimer0();
while(1)
{
DisplayTime();
ScanKeys();
}
}
总结
1.秒表功能的实现,注意是在定时器中断服务函数厘米,通过累加实现
2.按键的暂停/启动:TR0 = ~TR0;
3.实现清零:t_005s = 0; t_s = 0;t_m = 0;
4.最后要有松开的代码编写,实现动态扫描
5.注意主函数的编写!