1.1 简单延时子程序
在做单片机控制时,经常要遇到到延时的问题。比如要让蜂鸣器响1s,然后停1s,然后再响1s,反复下去。这个例子,要求延时的时间已经很准确了(1s),一般情况下,如果要求延时的时间不需要很精确,那么可以写一个简单的延时程序,然后通过调试,最后达到延时的目的。
这种方法适合大概的延时,可以通过while或for循环实现。为方便后续研究,我用for循环方式。
程序可以这样写:
#include
#define uint unsigned int
#define uchar unsigned char //宏定义
void delay() //延时函数
{
uint x,y;
for(x=100;x>0;x--)
for(y=5000;y>0;y--);
}
void main()
{
delay();
}
通过调试循环次数x,y值,改变延时间,最后达到满意的数值为止。
1.2 带参数的延时子程序
#define uint unsigned int
#define uchar unsigned char
void delay(uint z) //延时函数
{
uint x,y;
for(x=100;x>0;x--)
for(y=z;y>0;y--);
}
void main()
{
delay(k) //k为常数
}
在主函数main中调整常数k,方可达到延时目的。
1.3 中断程序
中断:CPU在处理某一事件A时,发生了另一事件B请求CPU迅速去处理(中断发生);CPU暂时中断当前的工作,转去处理事件B(中断响应和中断服务);待CPU将事件B处理完毕后,再回到原来事件A被中断的地方继续处理事件A(中断返回),这一过程称为中断。
理解上述中断的定义,有两点需要注意:1,中断程序执行完,又返回中断前的地方(断点)接着执行程序;2,中断的函数不需要声明,且该函数放在main函数的外面(附中断程序)。
附:80C51的中断系统
80C51的中断系统有5个中断源(见图1)(8052有6个),2个优先级,可实现二级中断嵌套。
图2
说明:图1,外部中断上的横线表示低电平有效。
1 中断请求标志寄存器TCON:
说明:
IT0(TCON.0),外部中断0触发方式控制位。
当IT0=0时,为电平触发方式。
当IT0=1时,为边沿触发方式(下降沿有效)。
IE0(TCON.1),外部中断0中断请求标志位。
IT1(TCON.2),外部中断1触发方式控制位。
IE1(TCON.3),外部中断1中断请求标志位。
TF0(TCON.5),定时/计数器T0溢出中断请求标志位。(硬件控制)
TF1(TCON.7),定时/计数器T1溢出中断请求标志位。(硬件控制)
注意:低四位用于控制外部中断,高四位用于控制和申请定时/计数器中断;TF0、TF1由硬件自动控制;TR0(TR1)为1时,定时器0(1)启动,反之停止(软件控制)。可直接进行位操作。
2 中断标志寄存器IE:为1,中断允许。(可进行位操作)
3 中断优先级寄存器IP:
说明:
80C51单片机有两个中断优先级,即可实现二级中断服务嵌套。每个中断源的中断优先级都是由中断优先级寄存器IP中的相应位的状态来规定的。
§PX0(IP.0),外部中断0优先级设定位;
§PT0(IP.1),定时/计数器T0优先级设定位;
§PX1(IP.2),外部中断0优先级设定位;
§PT1(IP.3),定时/计数器T1优先级设定位;
§PS(IP.4),串行口优先级设定位;
§PT2(IP.5),定时/计数器T2优先级设定位。
§CPU同时接收到几个中断时,首先响应优先级别最高的中断请求。
§正在进行的中断过程不能被新的同级或低优先级的中断请求所中断。
§正在进行的低优先级中断服务,能被高优先级中断请求所中断。
总结:
中断响应条件
§ 中断源有中断请求;(TCON)
§ 此中断源的中断允许位为1;(IE)
§ CPU开中断(即EA=1)。(EA)
以上三条同时满足时,CPU才有可能响应中断。
中断子程序(定时器0(1)中断响应):
void main()
{
EA=1;//开CPU中断
ET0=1;//开定时器0(中断允许)
ET1=1;
TR0=1;//启动定时器0
TR1=1;
}
void time0() interrupt 1 //中断函数time0()不需要声明,数字1与优先级有关,如外部中断0,应设置为0(interrupt 0)。
{}
void time1() interrupt 3
{}
1.4 定时器和计数器
前面已经介绍了延时,但是那种方法延时的时间做不到很精确,今天介绍一种精确的方法,就是定时器/计数器。
1.41 与定时器/计数器有关的寄存器
l TCON:前面已经介绍过,它主要是控制启动和申请中断。
l TMOD:控制定时器的控制方式。可用下图描述:
说明:
l 高四位与T1操作有关,低四位与T0操作有关;
l M1MO为工作方式设置位。一般工作在方式1下,此时M1MO=01;
l 在GATE=0时,需用软件使TCON中的位TRO(TR1)置1,启动定时器。C/T0=0为定时模式,C/T0=1为计数模式;
1.42 定时器/计数器工作原理
定时/计数器的实质是加1计数器(16位),由高8位THO(1)和低8位TL(1)两个寄存器组成。加1计数器输入的计数脉冲有两个来源,一个是由系统的时钟振荡器输出脉冲经12分频后送来;一个是T0或T1引脚输入的外部脉冲源。每来一个脉冲计数器加1,当加到计数器为全1时,再输入一个脉冲就使计数器回零,且计数器的溢出使TCON中TF0或TF1置1,向CPU发出中断请求(定时/计数器中断允许时)。如果定时/计数器工作于定时模式,则表示定时时间已到;如果工作于计数模式,则表示计数值已满。
可见,由溢出时计数器的值(注:16位全填满1时,数值刚好是65535。而溢出时计数器的值应该是65535+1=65536,即216)减去计数初值才是加1计数器的计数值。
从上面可以得到两个结论:
l 计数位数是16位:高8位THO(1)和低8位TL(1);
l 计数参数(添入TH和TL)与计数初值的关系:X=216-N;//假设定时时间是50ms,即N=50000;则计数参数=65536-50000=15536。
附:计算THO(1)和低8位TL(1)初值// 假设延时时间为50ms
TH=(65536-50000)/256 //求模
TL=(65536-50000)%256 //求余
定时/计数器初始化程序应完成如下工作:
l 对TMOD赋值,以确定T0(1)的工作方式;
l 计算初值,并将其写入TH、TL;
l 中断方式时,则对IE赋值,开放中断;
l 使TR0或TR1置位启动定时/计数器定时或计数。
定时程序模块:
#include
void main()
{
TMOD=0x01; //定时器T0工作方式1
//送初值,定时为50ms。
TH0=(65536-50000)/256;
TL0=65536-50000)%256;
EA=1; //开总中断
ET0=1; //开定时器0中断
TRO=0; //启动定时器0
}
上一篇:第二部分 与外围设备的接口实例
下一篇:基于GSM网络的汽车防盗报警系统设计
推荐阅读最新更新时间:2024-03-16 15:11