目录
一、设计背景
二、实现功能
三、仿真演示
四、源程序
一、设计背景
近年来随着科技的飞速发展,单片机的应用正在不断的走向深入。本文阐述了基于单片机的数字电子秒表倒计时设计,倒计时精度达0.05s了,解决了传统的由于倒计时精度不够造成的误差和不公平性,是各种体育竞赛的必备设备之一。本设计的数字电子秒表倒计时系统采用51单片机为中心器件,利用其定时器/计数器定时和记数的原理,结合显示电路、LED数码管以及外部中断电路来设计倒计时器。将软、硬件有机地结合起来,使得系统能够实现六位LED显示,倒计时精度为0.05秒,能正确地进行倒计时,倒计时精度为0.05秒,能正确地进行倒计时,复位后倒计时重新回到初始状态。其中软件系统采用C语言编写程序,包括显示程序,定时中断服务,外部中断服务程序,延时程序等,并在KEIL5中调试运行,硬件系统利用PROTEUS8.11强大的功能来实现,简单切易于观察,在仿真中就可以观察到实际的工作状态。
二、实现功能
以51单片机为控制核心,设计一种可调倒计时秒表。整个系统包括MCU、晶振电路、时钟电路、功能按键以及数码管显示。该系统利用共阳数码管实时显示时、分、秒倒计时,通过独立按键键盘设计控制倒计时秒表的启停、定时时间的设计。可具体实现以下功能:
(1) 按下设置键后,在数字闪烁的过程中,采用启动外部中断,能对增、减按键产生响应,。
(2) 按下启动键后,启动定时器;按下暂停键后,停止定时器。
(3)·定时器定时50ms,20次定时可产生1秒钟计时。
(4) 倒计时结束后,停止定时器。
(5) 最大定时99时59分59秒。
三、仿真演示
初始化定时时间0时0分0秒。
按下时间设置按键可以设置倒计时时间,通过连续按下时间设置按键可在时、分、秒设置来回切换,利用闪烁效果提示当前设置单位。
设置好倒计时时间后,利用启动键和停止键实现倒计时秒表的启停。
文章来源:https://www.toymoban.com/news/detail-431867.html
四、源程序
#include <reg51.h>
#define false 0
#define true 1
#define uchar unsigned char //0——255
#define uint unsigned int //0——65535
#define ulong unsigned long //0——4294967295
sbit start_key = P3^0; //启动按钮
sbit pause_key = P3^1; //停止按钮
sbit set_key = P3^6; //停止按钮
uchar disCode[10] = {0x03,0x9f,0x25,0x0d,0x99,0x49,0x41,0x1f,0x01,0x09}; //数码管段码 0~9
uchar locCode[8] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //位码
void displayTime(void); //刷新时间显示
void disPlay(uchar num, uchar loc); //数码管、led显示函数
void Exint_Init(void);
void Timer_Init(void);
void Delay1ms(unsigned int n); //延时1ms
uchar state; //状态:0-停止,1-启动,2-暂停
ulong ms = 0; //存储毫秒值
uchar shi = 0; // 小时数
uchar fen = 0; //分钟数
uchar miao = 0; //秒数
uchar set_flag = 0;
uchar smg_c = 0; //数码管闪烁时间计数
bit smg_f = 0; //数码管闪烁标志
void Timer_Init(void)
{
TMOD=0x11; //0110 0001 //方式一
TH0= (65536-50000)/256;
TL0= (65536-50000)%256; // 50ms
TH1= (65536-50000)/256;
TL1= (65536-50000)%256; // 50ms
TR0=1; //开启T0
TR1=1; //开启T1
//ET0=1; //T0中断允许
//ET1=1; //T1中断允许
EA=1; //总中断开启
}
/*******************************************************************************
* 函 数 名 : T0_INT
* 函数功能 : T0定时器中断函数10ms
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void T0_INT0(void) interrupt 1
{
ms++;
if(ms == 20) //1s时间到
{
ms = 0;
if(miao > 0){miao--;}
if(miao == 0) //秒数计时为0
{
if(fen == 0) //没有分钟数
{
if(shi == 0){TR0 = 0;} //判断是否还有时数,若没有,倒计时结束,停止计时
else{ shi--;fen = 60;}
}
if(fen > 0) //有分钟数
{
fen--;
miao = 59;
}
}
}
}
/*******************************************************************************
* 函 数 名 : T0_INT1
* 函数功能 : T0定时器中断函数50ms
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void T0_INT1(void) interrupt 3
{
smg_c++;
if(smg_c == 10)
{
smg_c = 0;
smg_f = ~smg_f;
}
}
/*********外部中断0、1初始化***********/
void Exint_Init()
{
IT0 = 1;
IT1 = 1; //下降沿触发
EX0 = 1;
EX1 = 1;
PX0 = 1; // 中断优先级设置
PX1 = 0;
}
/*********外部中断0服务函数***********/
void Exint0_Service() interrupt 0
{
if(set_flag == 3)
{
miao++;
if(miao == 60){miao = 59;}
}
if(set_flag == 2)
{
fen++;if(fen == 60){fen = 59;} //按键加
}
if(set_flag == 1)
{
shi++;
if(shi == 100) {shi = 99;}
}
}
/*********外部中断1服务函数***********/
void Exint1_Service() interrupt 2
{
if(set_flag == 3)
{
if(miao > 0){miao--;}
}
if(set_flag == 2)
{
if(fen > 0){fen--;} //按键减
}
if(set_flag == 1)
{
if(shi > 0){shi--;}
}
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main(void)
{
Timer_Init();
Exint_Init();
while(1)
{
displayTime(); //刷新时间显示
//检测启动按钮
if(start_key == 0) //按下了启动、停止按钮
{
Delay1ms(10); //延时消抖
if(start_key == 0)
{
ET0 = 1; //T0中断允许打开,开始计时
set_flag = 0;
TR0 = 1;
while(start_key == 0) displayTime(); //防止按键重复检测
}
}
//检测停止按钮
if(pause_key == 0) //已启动计时,并且暂停按钮按下
{
Delay1ms(10); //延时消抖
if(pause_key == 0)
{
ET0 = 0;
while(pause_key == 0) displayTime(); //防止按键重复检测
}
}
if(set_key == 0) //已启动计时,并且暂停按钮按下
{
Delay1ms(10); //延时消抖
if(set_key == 0)
{
ET1=1;
set_flag++;
if(set_flag == 4)
{
set_flag = 1;
}
while(set_key == 0) displayTime(); //防止按键重复检测
}
}
}
}
void displayTime(void) //刷新时间显示
{
if(((smg_f == 0) && (set_flag == 1))|| (set_flag == 0) || (set_flag == 2) || (set_flag == 3))
{
disPlay(shi/10, 0); //显示分钟数的十位
disPlay(shi%10, 1); //显示分钟数的个位
}
if(((smg_f == 0) && (set_flag == 2))|| (set_flag == 0) || (set_flag == 1) || (set_flag == 3))
{
disPlay(fen/10, 2); //显示分钟数的十位
disPlay(fen%10, 3); //显示分钟数的个位
}
if(((smg_f == 0) && (set_flag == 3))|| (set_flag == 0) || (set_flag == 1) || (set_flag == 2))
{
disPlay(miao/10, 4); //显示秒数的十位
disPlay(miao%10, 5); //显示秒数的个位
}
}
void disPlay(uchar num, uchar loc) //数码管、led显示函数
{
P0 = 0xff; //消除重影
P2 = locCode[loc]; //位码输出
P0 = disCode[num]; //段码输出
Delay1ms(1); //增加显示时间,防止显示过暗
}
/*******************************************************************************
* 函 数 名 : Delay1ms (多个)
* 函数功能 : 延时函数,延时n*1ms
* 输 入 : n-延时次数
* 输 出 : 无
*******************************************************************************/
void Delay1ms(unsigned int n)
{
unsigned char i, j;
for (; n>0; n--)
for(i=0;i<10;i++)
for(j=0;j<33;j++);
}
链接:https://pan.baidu.com/s/1geHUYam9Q1vYHOVoBJWeyw
提取码:b4fy
文章来源地址https://www.toymoban.com/news/detail-431867.html
到了这里,关于基于51单片机的倒计时秒表proteus仿真设计的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!