从单片机基础到程序框架(全集 2019pdf版).pdf - 第371页
Gu8Step= 0; //切换到 case 0 这 个步骤, 依次循环 } break; } } } void T0_ti me() inte rrupt 1 / /定时器 0 的中断函数 ,每 1ms 单片 机自动执行一 次此函数 { if(1==vG u8TimeFlag& &vGu16Time Cnt>0) // 判断 vGu8Time Flag 是否等于 1, 就是互斥 量的判断 { vGu16Tim e…

#include "REG52.H"
#define BLINK_TIME 500 //时间是 500ms
sbit P0_0=P0^0;
volatile unsigned char vGu8TimeFlag=0; //互斥量变量标志
volatile unsigned int vGu16TimeCnt=0; //计时器变量
unsigned char Gu8Step=0; //switch 的切换步骤
void main()
{
TMOD=0x01; //设置定时器 0 为工作方式 1
TH0=0xfc; //产生 1ms 中断的 TH0 初始值
TL0=0x66; //产生 1ms 中断的 TL0 初始值
EA=1; //开总中断
ET0=1; //允许定时 0 的中断
TR0=1; //启动定时 0 的中断
while(1) //主循环
{
switch(Gu8Step)
{
case 0:
if(0==vGu16TimeCnt) //时间到
{
P0_0=0; //LED 灯亮
vGu8TimeFlag=0; //互斥量“加锁”
vGu16TimeCnt=BLINK_TIME; //计时器的写操作。设定计时的长度
vGu8TimeFlag=1; //互斥量“解锁”,同时蕴含了计时器“启动”的动作
Gu8Step=1; //切换到 case 1 这个步骤
}
break;
case 1:
if(0==vGu16TimeCnt) //时间到
{
P0_0=1; //LED 灯灭。
vGu8TimeFlag=0; //互斥量“加锁”
vGu16TimeCnt=BLINK_TIME; //计时器的写操作。设定计时的长度
vGu8TimeFlag=1; //互斥量“解锁”,同时蕴含了计时器“启动”的动作

Gu8Step=0; //切换到 case 0 这个步骤,依次循环
}
break;
}
}
}
void T0_time() interrupt 1 //定时器 0 的中断函数,每 1ms 单片机自动执行一次此函数
{
if(1==vGu8TimeFlag&&vGu16TimeCnt>0) //判断 vGu8TimeFlag 是否等于 1,就是互斥量的判断
{
vGu16TimeCnt--; //“自减一”的操作
}
TH0=0xfc; //重装初值,不能忘
TL0=0x66; //重装初值,不能忘
}
【86.4 解决闪烁出现不规则“非对称感”现象的方法。】
上述例子,实验现象应该是 LED 闪烁很有规则的每 1s 闪烁一次,但是也有一部分初学者可能会遇到闪
烁出现不规则“非对称感”的现象,这个问题的解决办法如下:在 keil2 的 project 下拉菜单下,选择 Options
for Target 选项,弹出的窗口中,切换到 Target 选项,在 Memory Model 选项中选择 small:variables in Data。
图 86.4.1 设置窗口

第八十七节: 一个定时中断产生 N 个软件定时器。
【87.1 信手拈来的软件定时器。】
初学者会疑惑,51 单片机只有 2 个定时器 T0 和 T1,是不是太少了一点?2 个定时器怎能满足实际项目
的需要,很多项目涉及到的定时器往往十几个,怎么办?这个问题的奥秘就在本节的内容。
51 单片机内置的 2 个定时器 T0 和 T1,是属于硬件定时器,硬件定时器是一个母体,它可以孕育出 N 个
软件定时器,实际项目中,我们需要多少个定时器只需要从同一个硬件定时器中断里构造出对应数量的软件
定时器即可。构造 N 个软件定时器的框架如下:
//“软件定时器 1”的相关变量
volatile unsigned char vGu8TimeFlag_1=0;
volatile unsigned int vGu16TimeCnt_1=0;
//“软件定时器 2”的相关变量
volatile unsigned char vGu8TimeFlag_2=0;
volatile unsigned int vGu16TimeCnt_2=0;
//“软件定时器 3”的相关变量
volatile unsigned char vGu8TimeFlag_3=0;
volatile unsigned int vGu16TimeCnt_3=0;
void main()
{
vGu8TimeFlag_1=0;
vGu16TimeCnt_1=1000; //“软件定时器 1”的定时时间是 1000ms
vGu8TimeFlag_1=1;
vGu8TimeFlag_2=0;
vGu16TimeCnt_2=500; //“软件定时器 2”的定时时间是 500ms
vGu8TimeFlag_2=1;
vGu8TimeFlag_3=0;
vGu16TimeCnt_3=250; //“软件定时器 3”的定时时间是 250ms
vGu8TimeFlag_3=1;
while(1) //主循环
{
if(0==vGu16TimeCnt_1) //“软件定时器 1”的时间到了
{
...在这里执行具体的功能代码
}
if(0==vGu16TimeCnt_2) //“软件定时器 2”的时间到了