从单片机基础到程序框架(全集 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…

100%1 / 836
【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; //及时清零计数器,为返回上一步骤的新一轮计数准备