从单片机基础到程序框架(全集 2019pdf版).pdf - 第365页
图 85.9.1 灌入式驱动 8 个 LED #include " REG52.H" #define CYCL E_SUM 5000 //主循环的次 数 #define INTE RRUPT_SUM 500 //中断 的次数 sbit P0_0= P0^0; //在主循环里 的 LED 灯 sbit P0_1= P0^1; //在定时中断 里的 LED 灯 unsigned c har Gu8Cy cleStep=0…

【85.5 定时器 0 的“自身原配开关”TR0。】
TR0:定时器的“自身原配开关”。宽度是 1 位的位变量。很多初学者会把 EA,ET0,TR0 三者搞不清。
定时器可以工作在“查询标志位”和“中断”这两种状态,也就是说在没有中断的情况下定时器也可以单独
使用的。TR0 是定时器 0 自身的发动引擎,要不要把这个发动引擎所产生的能量传输到中断的渠道,则取决
于中断开关 EA 和 ET0。TR0 是源头开关,EA 是中断总渠道开关,ET0 是中断分支渠道的定时器 0 开关。TR0
取 1 表示启动定时器 0,取 0 表示关闭定时器 0。
【85.6 定时器 0 的中断函数的书写格式。】
void 函数名() interrupt 1
{
...中断程序内容;
...此处省去若干代码
...中断程序内容;
...最后面的代码,要记得重装 TH0 与 TL0 的初值;
}
函数名可以随便取,只要不是编译器已经征用的关键字。这里的 1 是定时器 0 的中断号。不同的中断号
代表不同类型的中断,至于哪类中断对应哪个中断号,大家可以查找相关书籍和资料。本节用的定时器 0 处
于工作方式 1 的情况下,在即将退出中断之前,需要重装 TH0 与 TL0 的初始值。
【85.7 寄存器的名字来源。】
前面讲的寄存器都有固定的名字,而且这些名字都是唯一的,拼写的时候少一个字母或者多一个字母,
C 编译器都会报错不让你通过,因此问题来了,初学者刚接触一款单片机的时候,如何知道某个寄存器它特
定的唯一的名字?有两个来源。
第一个来源,可以打开 C 编译器的某个头文件(.h 格式)查看这些寄存器的名字。比如 51 单片机可以
查看 REG52.H 这个头文件。如何打开 REG52.H 这个文件?在 keil 源代码编辑器界面下,选中上面 REG52.H
这几个字符,在右键弹出的菜单下点击 Open ducument“REG52.H”即可。
第二个来源是直接参考一些现成的范例程序,这些范例程序网上很多,有的是原厂提供的,有的是热心
网友的分享,有的是技术书籍或者学习板开发板厂家提供的。
【85.8 如何快速配置寄存器。】
建议一边阅读芯片的数据手册,一边参考一些现成的范例程序,这些范例程序网上很多,有的是原厂提
供的,有的是热心网友的分享,有的是技术书籍或者学习板开发板厂家提供的。
【85.9 练习例程。】
现在编写一个定时中断程序,让两个 LED 灯闪烁,一个是在主函数里用累计主循环次数的方式实现(P0.0
控制),另一个是在定时中断函数里用累计定时中断次数的方式实现(P0.1 控制)。这两个闪烁的 LED 灯,一
个在 main 函数,一个是在中断函数,两路任务互不干涉独立运行,并行处理的“雏形”略显出来。

图 85.9.1 灌入式驱动 8 个 LED
#include "REG52.H"
#define CYCLE_SUM 5000 //主循环的次数
#define INTERRUPT_SUM 500 //中断的次数
sbit P0_0=P0^0; //在主循环里的 LED 灯
sbit P0_1=P0^1; //在定时中断里的 LED 灯
unsigned char Gu8CycleStep=0;
unsigned long Gu32CycleCnt=0; //累计主循环的计数器
unsigned char Gu8InterruptStep=0;
unsigned long Gu32InterruptCnt=0; //累计定时中断次数的计数器
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(Gu8CycleStep)

{
case 0:
Gu32CycleCnt++;
if(Gu32CycleCnt>=CYCLE_SUM)
{
Gu32CycleCnt=0;
P0_0=0; //主循环的 LED 灯亮。
Gu8CycleStep=1;
}
break;
case 1:
Gu32CycleCnt++;
if(Gu32CycleCnt>=CYCLE_SUM)
{
Gu32CycleCnt=0;
P0_0=1; //主循环的 LED 灯灭。
Gu8CycleStep=0;
}
break;
}
}
}
void T0_time() interrupt 1 //定时器 0 的中断函数,每 1ms 单片机自动执行一次此函数
{
switch(Gu8InterruptStep)
{
case 0:
Gu32InterruptCnt++; //累计中断次数的次数
if(Gu32InterruptCnt>=INTERRUPT_SUM) //次数达到设定值就跳到下一步骤
{
Gu32InterruptCnt=0; //及时清零计数器,为下一步骤的新一轮计数准备
P0_1=0; //定时中断的 LED 灯亮。
Gu8InterruptStep=1; //跳到下一步骤
}
break;
case 1:
Gu32InterruptCnt++; //累计中断次数的次数
if(Gu32InterruptCnt>=INTERRUPT_SUM) //次数达到设定值就返回上一步骤
{
Gu32InterruptCnt=0; //及时清零计数器,为返回上一步骤的新一轮计数准备