从单片机基础到程序框架(全集 2019pdf版).pdf - 第606页

第一百一十五节: 按键控制数码管的秒表。 【115.1 按键控制数码管的秒表。 】 上图 11 5.1.1 数码管 上图 11 5.1.2 独立按键 本节通过一 个秒表的小项 目,让大家学 会以下 4 个知 识点: (1)上 层的 界面显 示框 架几 乎都 要用到 更新 变量 ,更 新变量 包括 整屏 更新和 局部 更新 ,本 节只 用到 整 屏更新。更 新变量是用全 局变量在函数 之间传 递信息。作用 是,当有某个 需要显示的数 据发…

100%1 / 836
vGu8ScanTimerFlag=1;
}
}
void T0_time() interrupt 1
{
DisplayScan();
if(1==vGu8ScanTimerFlag&&vGu16ScanTimerCnt>0)
{
vGu16ScanTimerCnt--;
}
TH0=0xfc;
TL0=0x66;
}
void SystemInitial(void)
{
P0=0x00;
P1_0=1;
P1_1=1;
P1_2=1;
P1_3=1;
TMOD=0x01;
TH0=0xfc;
TL0=0x66;
EA=1;
ET0=1;
TR0=1;
}
void Delay(unsigned long u32DelayTime)
{
for(;u32DelayTime>0;u32DelayTime--);
}
void PeripheralInitial(void)
{
}
第一百一十五节: 按键控制数码管的秒表。
【115.1 按键控制数码管的秒表。
上图 115.1.1 数码管
上图 115.1.2 独立按键
本节通过一个秒表的小项目,让大家学会以下 4 个知识点:
(1)上层的界面显示框架几乎都要用到更新变量,更新变量包括整屏更新和局部更新,本节只用到
屏更新。更新变量是用全局变量在函数之间传递信息。作用是,当有某个需要显示的数据发生改变的时候,
就要给更新变量置 1,让显示函数重新更新一次显示,确保最新的数据能及时显示出来,平时没有数据更
改变的时候不用频繁更新显示避免占用 CPU 过多的时间
(2)凡是需要显示数字的地方,都必须涉及如何把一个数据按“个十百千万...”的位逐个提取出来
算法。这个算法比较简单,主要“求余“求商”这两个运算语句就可以随心所欲的把数据位提取出来。
除此之外,还要学会如何用 if 语句判断数据的范围,来把高位尚未用到的某个数码管屏蔽,让该位数码
只显示一个“不显示”的数据(避免直接显示一 0)
(3)我常把单片机程序简化 4 个代表:按键(人机输入数码(人机界面)跑马灯(应用程序)
串口(通信)。本节的“应用程序”不是跑马灯,而是秒表。不管是跑马灯,还是秒表,都要用到一个总启
Gu8RunStart 一个运行步骤 Gu8RunStep。建议家,总启 Gu8RunStart 和总运行 Gu8RunStep
应该成双成对的出现(这样关断响应更及时,并且结构更紧凑,漏洞更少)比如,凡是总启动 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