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

vGu8Countd ownTimerF lag=0; //禁止 倒计时开始 (而 Gu8RunSt art 是启动开关 ,不矛 盾) vGu32Count downTimer Cnt=10000; //倒计时的软 件定时 器恢复初始值 10.000 秒 Gu8WdUpdat e=1; //整屏更 新一次显示 vGu8KeySec =0; break; case 2 : //启动的按键 if(0==Gu8R unStatus) / /在…

100%1 / 836
unsigned char Gu8RunStatus=0; //当前倒计时的状态。0 代表停止,1 代表正在工作中
unsigned char Gu8WdUpdate=1; //开机默认整屏更新一次显示。此变量在显示框架中是非常重要的变
volatile unsigned char vGu8Display_Righ_4=1; //显示“1”,跟 vGu32CountdownTimerCnt 高位一致
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 成双成对出
vGu8CountdownTimerFlag=0; //禁止倒计时开始(而 Gu8RunStart 是启动开关,不矛盾)
vGu32CountdownTimerCnt=10000; //倒计时的软件定时器恢复初始值 10.000
Gu8WdUpdate=1; //整屏更新一次显示
vGu8KeySec=0;
break;
case 2: //启动的按键
if(0==Gu8RunStatus) //在停止状态下
{
vGu8CountdownTimerFlag=0;
vGu32CountdownTimerCnt=10000; //初始值是 10.000
vGu8CountdownTimerFlag=1; //允许倒计时的软件定时器的启动
Gu8RunStatus=1; //倒计时处于工作状态(并且,这一瞬间才正式启动倒计时)
Gu8RunStart=1; //倒计时的运行步骤的总开关开启
Gu8RunStep=0; //总运行步骤归零。建议跟 vGu8RunStart 成双成对出现
Gu8WdUpdate=1; //整屏更新一次显示,确保在启动的时候能显示到最新的数据
}
vGu8KeySec=0;
break;
}
}
void DisplayTask(void) //数码管显示的上层任务函
{
//需要借用的中间变量,用来拆分数据位。
static unsigned char Su8Temp_4,Su8Temp_3,Su8Temp_2,Su8Temp_1; //需要借用的中间变
if(1==Gu8WdUpdate) //如果需要整屏更新
{
Gu8WdUpdate=0; //及时清零,只更新一次显示即可,避免一直进来更新显示
//先分解数据,注意,这里分解的时候,“先整除后求余”必须用一行代码一气呵成,不能拆
//分成两行代码,否则会有隐患会 bug。除非,把四个临时变都改成 unsigned long 类型。
//Su8Temp_4 提取“十秒”位。
Su8Temp_4=vGu32CountdownTimerCnt/10000%10; //实际精度是 0.001 秒,但显示精度是 0.01
//Su8Temp_3 提取“个秒”位。
Su8Temp_3=vGu32CountdownTimerCnt/1000%10; //实际精度是 0.001 秒,但显示精度是 0.01
//Su8Temp_2 提取“百毫秒”位。
Su8Temp_2=vGu32CountdownTimerCnt/100%10; //实际精度是 0.001 秒,但显示精度 0.01
//Su8Temp_1 提取“十毫秒”位。
Su8Temp_1=vGu32CountdownTimerCnt/10%10; //实际精度是 0.001 秒,但显示精度是 0.01
//判断数据范围,来决定最高位数码管是否需要显示。
if(vGu32CountdownTimerCnt<10000) //10.000 秒。实际 4 位数码管最大只能显示 99.99
{
Su8Temp_4=10; //在数码管转换表里,10 代表一个“不显示”的数据
}
//上面先分解数据之后,再过渡需要显示的数据到底层驱动变量里,让过渡的时间越短越好
vGu8Display_Righ_4=Su8Temp_4; //过渡需要显示的数据到底层驱动变量
vGu8Display_Righ_3=Su8Temp_3;
vGu8Display_Righ_2=Su8Temp_2;
vGu8Display_Righ_1=Su8Temp_1;
vGu8Display_Righ_Dot_4=0;
vGu8Display_Righ_Dot_3=1; //保留显示 2 位小数点
vGu8Display_Righ_Dot_2=0;
vGu8Display_Righ_Dot_1=0;
}
}
void RunTask(void) //倒计时的应用程序
{
if(0==Gu8RunStart)
{
return; // 如果总开关处于停止状态,则直接退出当前函数,不执行该函数以下的其它代码
}
switch(Gu8RunStep)
{
case 0: //在这个步骤里,主要用来初始化一些参
vGu8UpdateTimerFlag=0;