针对网络上大部分例程序只有倒计时秒 , 无法一眼看出还剩多少时间,因此做考试计时器不具备实用性。
因此,编写一个 分钟,秒钟分离的版本,方便考生的时间控制。
/*==================================================================
编写时间: 2022.04.21
设计目标:
四位共阴极数码管, 前两位为分钟后两位为秒钟。
设定时间为90分钟,开机后开始倒计时。
硬件电路设计:
数码管使用4个NPN三极管驱动,基极通过1K电阻连接STC89C51的
P1.0-P1.4 口。发射极共地,集电极接数码管阴极。
数码管数据位分别通过电阻限流后同STC89C51的P0口连接。
单片机晶振11.0592Mhz。
软件逻辑设计:
1.利用T0中断函数,计数到200次,发送1秒标志Flage,
2.数码管驱动函数(LedDriver)在接收到 Flage后,进行倒计时计算,并将数据传递给显示函数(LedShow)。
3.显示函数(LedShow)在收到时间数据后,进行数据分离,并写入数码管缓存。
4.数码管刷新函数(LedScan)利用数码管缓存的数据进行刷新动态显示。
Others You Need To Know:
为保证准确性, 取能被机器周期除尽的最小数值5ms
得出TMOD 16位寄存器初始值:60928 设定值:0xEE00;
================================================================*/
#include<reg52.h> //对寄存器配置的头文件。
sbit LEDS1 = P1 ^ 0;
sbit LEDS2 = P1 ^ 1;
sbit LEDS3 = P1 ^ 2;
sbit LEDS4 = P1 ^ 3;
unsigned int Tcount = 5400; //时间计数 设定90分钟 5400秒
bit Flage = 0;
unsigned char code LedChar[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71};
unsigned char LedBuf[] = {0x00, 0x00, 0x00, 0x00};
void LedCharDriver();
void LedScan();
void LedShow(unsigned int i);
void main()
{
/*======================
初始数码管
=======================*/
LEDS1 = 0;
LEDS2 = 0;
LEDS3 = 0;
LEDS4 = 0;
/*=======================
配置定时器
========================*/
EA = 1;
TMOD = 0x01;
TH0 = 0xEE;
TL0 = 0x00;
ET0 = 1;
TR0 = 1;
while(1)
{
LedCharDriver();
}
}
/*==================================
数码管驱动函数,进行倒计时并传递数据
===================================*/
void LedCharDriver()
{
if(Flage == 1)
{
Flage = 0;
Tcount--;
if(Tcount <= 0) //设定时间90分钟, 5400秒。
{
Tcount = 5400;
}
LedShow(Tcount); //传递剩余时间到显示函数
}
}
/*============================================
数码管显示函数,递数据分离,并写入缓存LedBuf中
=============================================*/
void LedShow(unsigned int i)
{
unsigned char j, k;
unsigned char min = 0;
unsigned char sec = 0;
min = i / 60;
sec = i % 60;
for(j = 0; j < 2; j++)
{
LedBuf[j] = LedChar[sec % 10];
sec = sec / 10;
}
for(k = 2; k < 4; k++)
{
LedBuf[k] = LedChar[min % 10];
min = min / 10;
}
}
/*==================================
数码管动态刷新,带消隐
==================================*/
void LedScan()
{
static unsigned char i = 0;
P0 = 0x00;
switch (i)
{
case 0:
LEDS4 = 0;
LEDS1 = 1;
i++;
P0 = LedBuf[0];
break;
case 1:
LEDS1 = 0;
LEDS2 = 1;
i++;
P0 = LedBuf[1];
break;
case 2:
LEDS2 = 0;
LEDS3 = 1;
i++;
P0 = LedBuf[2];
break;
case 3:
LEDS3 = 0;
LEDS4 = 1;
i=0;
P0 = LedBuf[3];
break;
default :
break;
}
}
/*=================================
中断函数,用于计时,同时刷新数码管
===================================*/
void InterruputTimer0() interrupt 1
{
static unsigned char cnt = 0;
TH0 = 0xEE;
TL0 = 0x00;
cnt++ ;
if(cnt >= 200)
{
cnt = 0;
Flage = 1;
}
LedScan();
}