从单片机基础到程序框架(全集 2019pdf版).pdf - 第608页
0x06, //1 序号 1 0x5b, //2 序号 2 0x4f, //3 序号 3 0x66, //4 序号 4 0x6d, //5 序号 5 0x7d, //6 序号 6 0x07, //7 序号 7 0x7f, //8 序号 8 0x6f, //9 序号 9 0x00, //不显 示 序号 10 }; //数码管底层 驱动扫描的软 件定时器 volatile u nsigned c har vGu8Scan TimerFlag…

应该成双成对的出现(这样关断响应更及时,并且结构更紧凑,漏洞更少),比如,凡是总启动 Gu8RunStart
发生改变的时候,总运行步骤 Gu8RunStep 都复位归零一下。
(4)一个硬件的定时器中断,可以衍生出 N 个软件定时器,之前跟大家介绍的是“递减式”的软件定
时器,而且实际应用中,“递减式”的软件定时器也是用得最多。本节因为项目的需要,需要用到的是“累
加式”的软件定时器。不管是哪种软件定时器,大家都要注意定时器变量在定义时所用到的数据类型,这个
数据类型决定了定时时间的长度,比如在 51 单片机中,unsigned int 的范围是 0 到 65535,最大一次性定
时 65.535 秒。而 unsigned long 的范围是 0 到 4294967295,最大一次性定时 4294967.295 秒。本节秒表的
时间超过 65.535 秒,因此需要用到 unsigned long 类型的定时器变量。
本节秒表程序的功能:K1 按键是复位按键,每按一次,秒表都停止并且重新归零。K2 按键是启动和暂
停按键,当秒表处于复位后停止的状态时按一次则开始启动,当秒表处于正在工作的状态时按一次则处于暂
停状态,当秒表处于暂停的状态时按一次则继续处于工作的状态。本节 4 位数码管,显示的时间是带 2 位小
数点的,能显示的时间范围是:0.00 秒到 99.99 秒。代码如下:
#include "REG52.H"
#define KEY_FILTER_TIME 25
#define SCAN_TIME 1
void T0_time();
void SystemInitial(void) ;
void Delay(unsigned long u32DelayTime) ;
void PeripheralInitial(void) ;
void KeyScan(void);
void KeyTask(void);
void DisplayScan(void); //底层显示的驱动函数
void DisplayTask(void); //上层显示的任务函数
void RunTask(void); //秒表的应用程序
sbit KEY_INPUT1=P2^2;
sbit KEY_INPUT2=P2^1;
sbit P1_0=P1^0;
sbit P1_1=P1^1;
sbit P1_2=P1^2;
sbit P1_3=P1^3;
//数码管转换表
code unsigned char Cu8DigTable[]=
{
0x3f, //0 序号 0

0x06, //1 序号 1
0x5b, //2 序号 2
0x4f, //3 序号 3
0x66, //4 序号 4
0x6d, //5 序号 5
0x7d, //6 序号 6
0x07, //7 序号 7
0x7f, //8 序号 8
0x6f, //9 序号 9
0x00, //不显示 序号 10
};
//数码管底层驱动扫描的软件定时器
volatile unsigned char vGu8ScanTimerFlag=0;
volatile unsigned int vGu16ScanTimerCnt=0;
//秒表的软件定时器,注意,这里是 unsigned long 类型,范围是 0 到 4294967295 毫秒
volatile unsigned char vGu8StopWatchTimerFlag=0;
volatile unsigned long vGu32StopWatchTimerCnt=0;
//数码管上层每 10ms 就定时刷新一次显示的软件定时器。用于及时更新显示秒表当前的实时数值
volatile unsigned char vGu8UpdateTimerFlag=0;
volatile unsigned int vGu16UpdateTimerCnt=0;
unsigned char Gu8RunStart=0; //应用程序的总启动
unsigned char Gu8RunStep=0; //应用程序的总运行步骤。建议跟 vGu8RunStart 成双成对出现
unsigned char Gu8RunStatus=0; //当前秒表的状态。0 代表停止,1 代表正在工作中,2 代表暂停
unsigned char Gu8WdUpdate=1; //开机默认整屏更新一次显示。此变量在显示框架中是非常重要的变量
volatile unsigned char vGu8Display_Righ_4=10; //开机默认最高位数码管显示一个“不显示”数据
volatile unsigned char vGu8Display_Righ_3=0;
volatile unsigned char vGu8Display_Righ_2=0;
volatile unsigned char vGu8Display_Righ_1=0;
volatile unsigned char vGu8Display_Righ_Dot_4=0;
volatile unsigned char vGu8Display_Righ_Dot_3=1; //开机默认保留显示 2 个小数点
volatile unsigned char vGu8Display_Righ_Dot_2=0;
volatile unsigned char vGu8Display_Righ_Dot_1=0;
volatile unsigned char vGu8KeySec=0;
void main()

{
SystemInitial();
Delay(10000);
PeripheralInitial();
while(1)
{
KeyTask(); //按键的任务函数
DisplayTask(); //数码管显示的上层任务函数
RunTask(); //秒表的应用程序
}
}
void KeyTask(void) //按键的任务函数
{
if(0==vGu8KeySec)
{
return;
}
switch(vGu8KeySec)
{
case 1: //复位按键
Gu8RunStatus=0; //秒表返回停止的状态
Gu8RunStart=0; //秒表停止
Gu8RunStep=0; //总运行步骤归零。建议跟 vGu8RunStart 成双成对出现
vGu8StopWatchTimerFlag=0;
vGu32StopWatchTimerCnt=0; //秒表的软件定时器清零
Gu8WdUpdate=1; //整屏更新一次显示
vGu8KeySec=0;
break;
case 2: //启动与暂停的按键
if(0==Gu8RunStatus) //在停止状态下
{
Gu8RunStatus=1; //秒表处于工作状态
vGu8StopWatchTimerFlag=0;
vGu32StopWatchTimerCnt=0;
vGu8StopWatchTimerFlag=1; //启动秒表的软件定时器