当前位置:文档之家› 中断及定时计数器

中断及定时计数器

单片机的中断与定时器/计数器中断就是停止当前的任务,去做另一个需要马上处理的任务,做完后再回去做原来的任务!P1.0P1.1P1.2P1.3P1.4P1.5P1.6P1.7RST/V PD P3.0/RXD P3.1/TXD P3.2/INT0P3.3/INT1P3.4/T0P3.5/T1P3.6/WR P3.7/RD XTAL2XTAL1V SSV CC P0.0P0.1P0.2P0.3P0.4P0.5P0.6P0.7EA/V PP PSEN P2.7P2.6P2.5P2.4P2.3P2.2P2.1P2.0RST P3.0/RXD P3.1/TXDXTAL2XTAL1P3.2/INT0P3.3/INT1P3.4/T0P3.5/T1GNDV CC P1.7P1.6P1.5P1.4P1.3P1.2P1.1/AIN1P1.0/AIN0P3.7注:类似的还有Philips公司的 87LPC64,20引脚8XC748/750/(751),24引脚 8X749(752),28引脚 8XC754,28引脚 等等如上图 8051中有5个中断:P3.2和P3.3为外部中断INT0和INT1端口,P3.4和P3.5为定时器/计数器中断T0和T1端口, 以及一个串行口中断,(此内容暂时不讲)8052中有6个中断,比8051多一个特殊的定时器/计数器中断。

(暂时不讲)外部中断: INT0和INT1外部中断通过其对应的引脚来接受外部中断请求,触发方式有两种: 1.低电平触发,即得到地电位就触发中断。

2.负边沿触发,即由高电平降至低电平的瞬间触发。

区别在于低电平触发属于静态触发,只要是低电平就一定触发;而负边沿触发为动态触发,必须由高电平变为低电平的时候才会触发。

控制触发方式的开关为:IT 。

IT0和IT1分别对应控制INT0和INT1的触发方式。

0为低电平触发,1为负边沿触发。

例:外部中断INT0开启低电平触发: IT0=0;定时器/计数器中断: T0和T1它有两种工作模式:定时器与计数器。

1. 定时器模式下,单片机对内部时钟脉冲进行计数。

不使用外部端口。

2. 计数器模式下,单片机对外部脉冲进行计数,使用外部端口,外部脉冲由外部对应端口进入。

即P3.4和P3.5至于定时器/计数器是如何触发中断的将在后半部分内容中详细说明。

中断的启用与控制:中断平时是关闭的,只有通过打开相应的开关才能使用,打开后还需进行相应的设置。

1、EA ---- 中断允许总控制器=0,中断总禁止,关闭所有中断。

=1,中断总允许,各中断的允许或禁止由各中断的控制位进行设置。

2、EX0 EX1 ---- 外部中断0(1)允许控制位。

=0,禁止外中断。

=1,允许外中断。

3、ET0 ET1 ---- 定时中断0(1)允许控制位。

=0,禁止定时中断。

=1,允许定时中断。

定时器产生中断(触发方式后面讲),响应中断服务程序。

4、ES ---- 串行中断允许控制位。

=0,禁止串行中断。

=1,允许串行中断。

1、IE0 IE1 ---- 外部中断请求标志位。

(硬件自动清零)cpu检测到中断端口出现有效中断请求时,此位被置1,再中断响应完成转向中断服务子程序时,再由硬件自动清为0。

2、IT0 IT1 ---- 外部中断触发方式控制位。

(软件置位、清零)=0,时电平触发方式,低电平有效。

=1,是脉冲触发方式,下降沿触发有效;3、TR0 TR1 ---- 定时器0(1)运行控制位。

=0,禁止定时器运行;=1,允许定时器运行。

4、TF0 TF1 ---- 内部定时/计数器0(1)溢出标志。

相应的定时器溢出时,被自动置为1。

当转向中断服务子程序时,再由硬件自动清0。

中断的优先级:多个中断同时触发时候将会按照优先级顺序来执行:默认的自然优先顺序为:外中断 0→定时器0→外中断1→定时器1→串口中断(8052中的定时器2与串口中断的自然优先级相同,都在最底。

)8051单片机可人工对其优先级进行调整,但只有2个级别。

高级优先于低级执行,在同等级内部优先顺序依旧按照自然优先顺序排列。

1、PX0 PX1 ---- 外中断0(1)优先级设定位。

2、PT0 PT1 ---- 定时中断0(1)优先级设定位。

3、PS ---- 串行中断优先级设定位。

=0,低优先级;=1,高优先级。

举例:假定开放外中断1,采用负边沿触发方式,高优先等级需要作如下设定:EA=1EX1=1IT1=1PX1=1中断的嵌套使用:假如现在程序已经进入一个中断子程序进行执行。

此时又一中断触发,若此中断等级高于正在执行的中断,则停止当前任务处理中断请求;若此中断等级低于或等于当前处理中断,则等当前正在处理的中断执行完后在给与处理。

中断的使用:中断号中断源中断向量0 外部中断0 0003H1 定时器0 000BH2 外部中断1 0013H3 定时器1 001BH4 串行口0023H5 定时器2 0X2BH (外加器件)语法如下:void X(void) interrupt 中断号函数X()与中断源的联系是通过使用Keil的关键字interrupt 建立起来的。

例:void x(void) interrupt 1{ ET0=0; //禁止定时中断P1=0x0f;delay(1000);P1=0xf0;delay(1000);EX0=1; //允许外中断}中断实例:电路图:程序:#include<reg51.h> //定义8051寄存器的头文件#define LED P2 //定义LED接至P2void delay(int); //声明延迟函数void left(int); //声明单灯左移函数main() //主程序开始{EA=1; EX0=1; //允许INT0中断IT0=1; //INT0设为负边沿触发LED=0x00; //初值=0000 0000,灯全亮While(1) //无穷循环,程序一直运行{Delay(250); //延迟250*1ms=0.25sLED=~LED; //LED反向} //while循环结束} //主程序结束void my_int0(void) interrupt 0 //INT0中断子程序开始{unsigned saveLED=LED; //储存中断前LED状态left(3); //单灯左移三圈LED=saveLED; //写回中断前LED状态}void delay(int x) //延迟函数开始{int i,j: //声明整数变量i,jfor(i=0;i<x;i++) //计数x次,延时x*1msfor(j=1;j<120;j++); //计数120次} //延迟函数结束void left(int x) //单灯左移函数开始{int i.j; //声明整数变量i,jfor(i=0;i<x;i++) //i循环,执行x圈{LED=0xfe; //初始状态1111 1110,最右灯亮for(j=0;j<7;j++) //j循环,左移7次{delay(250); //延迟250*1ms=0.25sLED=(LED<<1)|0x01; //左移一位后,LED设为1}delay(250); //延迟250*1ms=0.25s} //i循环结束} //单灯左移函数结束定时器/计数器:定时器和计数器是单片机内的一个系统,并且与中断有联系,定时器以内部晶振脉冲为计时周期,计数器以外部对应端口的输入脉冲为计时周期。

在他们工作时每接收到一个脉冲,则给内部计数寄存器内数字加1,当计数存储器达到最高时候再加一位就会溢出,所有位清零,而对应的溢出标志位变为1,此时若对应中断是打开的,则触发中断。

TR0 TR1 ---- 定时器0(1)运行控制位。

=0,禁止定时器运行;=1,允许定时器运行。

TF0 TF1 ---- 内部定时/计数器0(1)溢出标志。

相应的定时器溢出时,被自动置为1。

当转向中断服务子程序时,再由硬件自动清0。

他们有4种工作模式:工作方式0:是13位的计数器,最大值为8192工作方式1:是16位的计数器,最大值为65536工作方式2:带有数据自动重装的功能,因此,定时更精确。

经常用于波特率发生器。

最大值为256工作方式3:是将它当做两个8位的定时器来用。

主要与另一个定时器工作于方式2时配套使用。

最大值为256计数寄存器:8051内部的计数寄存器为THx和TLx两个8位寄存器。

对于12mhz,定时器计一个数是1us.如果使用16位计数。

那么最多计65.535ms。

如果需要一个小于65.535ms的数字时候,则对计数寄存器的THx和TLx赋值即可:提示:如果是一个空的盆要1 万滴水滴进去才会满,我们在开始滴水之前就预先放入一勺水,还需要1 万滴嘛?单片机计数也是如此,如果我要计5000 个脉冲,就先放进60535 个,再来5000 个,不就到了65535 了吗?定时器同样如此,每个脉冲是1 微秒,则计满65536 个脉冲需时65.536 毫秒,但现在我只要10 毫秒就可以了,怎么办?10 个毫秒为10000 微秒,所以,只要在计数器里预先放进55536就可以了,这种计数方法我们把它称之为预置数计数法。

我们使用其中的一个作为例子(定时器0)进行介绍:以方式1说一下,定时器如何使用:在使用定时器之前,要先对定时器的工作方式做一下规定:TMOD寄存器就是专门用来管理这个参数的:我们仅仅使用定时器0,不使用定时器1.所以,TMOD为0x01;即工作方式1然后给定时器赋予初值:TH0和TL0赋完初值之后还要将cpu的中断允许打开:EA=1;ER0=1;分别是打开总中断和打开定时器0的中断。

这时,定时器是不是已经开始定时了呢?没有,这时,我们需要给它启动起来!TR0=1;就启动了定时器。

在cpu将定时器0计满的时候,硬件会自动的将TCON中的TF0置于1,引起cpu中断。

但是就会自动跳转到中断处理函数中,在中断函数中,我们需要重新给T0赋初值。

以确保定时的准确。

以下是一个程序://用定时/计数器T0从P2.0输出周期为1s的方波,让发光二极管以1HZ闪烁,设晶振频率为12MHz。

#include <reg52.h>#define uchar unsigned char#define uint unsigned intsbit D1=P2^0;uchar a;void init() //初始化{TMOD=0x01; //选择定数计数器0的工作方式为16位定时器TL0=(65535-50000)%256; //赋初值,定时50msTH0=(65535-50000)/256;EA=1; //中断控制允许ET0=1;a=0;TR0=1; //启动定时器0}void time0() interrupt 1 //定时器0中断函数{TL0=(65535-50000)%256; //赋初值,定时50msTH0=(65535-50000)/256;a++;TR0=1;}void main(){init();while(1){while(a==10)//半个周期(500ms)时,D1上的电平跳变一次。

相关主题