51单片机(四)定时器中断(+数码管

文章正文
发布时间:2025-05-24 03:50

一、中断 1、中断概念

单片机处理某一事件A时,事件B突然发生(中断发生),而且事件B的优先级大于事件A的优先级,则单片机暂停对事件A的执行,转向执行事件B(中断响应),执行完事件B后,再回到事件A,继续执行事件A。(中断返回)

2、中断嵌套

若事件的优先级A<B<C<D…单片机执行事件A时,发生了事件B,则暂停执行事件A而转向执行事件B,在执行事件B时,又发生了事件C,则停止执行事件B,进而转向执行事件C,执行事件C时,事件D发生,则单片机停止执行事件C,转向执行事件D…当事件D执行完毕,单片机返回事件C继续执行事件C,事件C执行完毕,单片机返回事件B继续执行事件B,事件B执行完毕,返回事件A继续执行事件A。这种在中断服务过程中又产生中断,并且发生中断响应的过程,就是中断嵌套。

注:事件D执行完毕后,返回事件C,并不是重新开始执行事件C,而是接续中断发生时的进度,继续执行。同事件B、C的中断返回

二、中断源(优先级顺序必记!) 中断源 默认中断级别
INT0外部中断0   最高  
T0定时器/计数器0中断   第2  
INT1外部中断1   第3  
T1定时器/计数器1中断   第4  
T1/TI串行口中断   第5  
T2定时器/计数器2中断   最低  

注1:上表中T2定时器/计数器是52单片机特有的。
注2:上表中的的优先级顺序一定要记住!!!接下来的一些寄存器每一位的信息也是按照这个顺序设定的。

三、中断允许寄存器IE和中断优先级寄存器IP 1、中断允许寄存器IE(Interrupt Enable ) 位序号 D7 D6 D5 D4 D3 D2 D1 D0
位符号   EA   _   ET2   ES   ET1   EX1   ET0   EX0  

这个寄存器的位符号和顺序一定要熟记,从低位到高位依次是:外部中断0、定时器/计数器0、外部中断1、定时器/计数器1、串行中断、D6位无效(52单片机用,T2)、EA全局中断允许位。

前五位的顺序就是之前我们强调的中断源优先顺序,记住顺序后,这里就很容易记住IE寄存器。

编写中断程序时,第一步需要打开全局中断允许,第二步需要选择中断源。其中寄存器某位软件置1表示打开,0表示关闭,单片机在上电是,IE寄存器每一位被清零,所以中断允许位及各中断源选择都处于关闭状态,需要程序进行操作。

打开头文件:

在这里插入图片描述

在这里插入图片描述


可以看到定义了8位的IE寄存器,编写程序时可直接对该寄存器操作。

比如选择外部中断0作为中断源,则IE寄存器D7位置1打开全局中断允许位,D0位软件置1打开外部中断0,此时IE寄存器的状态值为:10000001,即0x81;
程序为:(根据头文件,IE是有定义的,IE可以直接使用)

IE=0x81;

再查看头文件:

在这里插入图片描述

IE寄存器的每一位都重新命名。可以对每一位进行单独操作。所以上述程序还可以写成:

EA=1; EX0=1;

为了加深理解,再举个例子:比如现在需要使用定时器/计数器1作为中断源
方法一:
D7位置1,D3位置1,所以IE状态值:10001000,即0x88

所以程序:

IE=0x88;

方法二:

EA=1; ET1=1; 2、中断优先级寄存器IP(Interrupt Priority) D7 D6 D5 D4 D3 D2 D1 D0
-   -   -   PS   PT1   PX1   PT0   PX0  

上表中从低位到高位依次:外部中断0、定时器/计数器0、外部中断1、定时器/定时器1、串行口中断,依旧是我们之前记忆的中断源优先级顺序

中断优先级顾名思义,是用来设置优先级别的,类似STm32的NVIC 的优先级组,在实际应用中根据需要设置高优先级中断,形成中断嵌套。

该寄存器的某一位软件置1,表示将该位设置为高优先级,高优先级优先于低优先级发生中断响应,若俩中断源同为高优先级或同为低优先级,则按照默认顺序发生中断响应(我们一直强调记忆的那个顺序)。正因为有了IP寄存器,所以中断源的响应顺序并不是一直不变,它根据我们的设置来适应需求。

如果程序中没有对IP寄存器进行设置,则单片机上电后IP寄存器每一位都清零,相当于没有设置高优先级,中断响应顺序仍旧按照默认顺序发生。

打开头文件:

在这里插入图片描述


在这里插入图片描述

IP寄存器是在头文件里定义了的,并且寄存器的每一位都通过位操作重新命名,所以与IE寄存器相同,也有俩种操作方法。

举例说明:
若设置定时器/计数器T0和外部中断1为高优先级,则IP寄存器状态值:00000110,即0x06

程序:

IP=0x06;

或者:

PT0=1; PX1=1;

此时优先级顺序:
定时器/计数器0——>外部中断1(它俩按照默认顺序排,高优先级)——>外部中断0——>定时器/计数器1——>串行口中断(它仨按照默认顺序排,低优先级)

四、定时器中断

来到本博的重点——定时器中断,首先要知道,定时器/计数器的实质是加1计数器,由高八位和低八位俩个寄存器组成

打开头文件,可以看到定时器1和2的高8位和低8位的寄存器。

在这里插入图片描述

1、定时器工作原理

定时器实质是加1计数器,根据计数脉冲来+1计数,脉冲来源有俩种,一种是由系统的时钟振荡器输出脉冲经12分频后送来,另一种是T0或T1引脚输入的外部脉冲源,每来一个脉冲计数器就+1,当计数器16位都为1时(65535),再来一个脉冲后+1,计数器会归零,此时计数器的溢出使TCON寄存器中TF0或TF1置1,向CPU发送中断请求,也就是说定时器计满数就中断请求一次。

假如计数器初值为N0,每t0时间计数器+1,则每次中断间隔时间为:(65536-N0)*t0。

求t0:
设晶振频率为F,晶振产生的信号为正弦波(等效为矩形波,与阈值和占空比有关),则周期为1/F s,一个机器周期为12个振荡周期(所以系统的时钟振荡器输出脉冲经12分频后当作计数脉冲),所以一个机器周期为12/F s,一个机器周期计数器+1,所以计数器每+1一次的时间为:12/F s。
对于12MHZ的晶振,t0=12/(12* 10^6)s=10 ^-6s=1us。
对于11.0592MHZ的晶振,t0=12/(11.0592*10^6)s≈1.09us

求N0:
若初值为0,则12MHZ晶振发生一次中断需要时间:t=t0* 65536=65.536ms
这个t在程序中不好处理,所以加入初值,使t为一个整数,比如50ms,此时若想延时1s,只需中断20次即可。
当t=50ms时,计数器加的数为:50* 10^-3s/(1*10 ^-6s)=50000,所以初始值为:N0=65536-50000=15536

所以每次中断计数器溢出清零后,需重新给计数器设置初值15536,把它放入高8位和低8位寄存器。
高8位存放:
TH0(TH1)=(65536-50000)/256=15536/256=60(等式一)
低8位存放:
TL0(TL1)=(65536-50000)%256=15536%256=176(等式二)

至于为什么对256取余和取商,这里就不在解释(记住就好),学过算法的朋友应该知道,利用分治思想求大整数乘法,分而治之的“分”可能会用的这种方法。

从上面也看到,每50ms产生依次中断,所以等式一和等式二都减了50000(us),若20ms产生一次中断,则:
TH0(TH1)=(65536-20000)/256=45536/256=177
TL0(TL1)=(65536-20000)%256=45536%256=224

12MHZ晶振的装载初值程序如下:

//12MHZ重装载初值,定时器0 TH0=65536-50000/256; TL0=65536-50000%256;

若是11.0592MHZ晶振,之前说过,计数器+1的时间约为1.09us,若t0=50ms,则N=50* 10^3s/(1.09*10 ^-6s)≈45872

11.0592MHZ晶振的装载初值程序如下:

//11.0592MHZ重装载初值,定时器0,中断间隔50ms TH0=65536-45872/256; TL0=65536-45872%256; 2、定时器/计数器工作方式寄存器TMOD(Timer Mode) 位序号 D7 D6 D5 D4 D3 D2 D1 D0
位符号   GATE   C/T   M1   M0   GATE   C/T   M1   M0  

上表的寄存器 低四位为T0定时器,高四位为T1定时器。
GATE——顾名思义,门,为门控制位

GATE=0,定时器/计数器启动和停止受TCON寄存器(下一部分总结)中TR0(定时器0时)或TR1(定时器1时)控制,TR(0或1)=1时启动相应定时器,TR(0或1)=0时停止相应定时器。

GATE=1,定时器/计数器启动和停止受TCON寄存器中TR0(定时器0时)或TR1(定时器1时)和外部中断引脚INT0或INT1俩者共同控制

C/T——Counter/Timer,定时器和计数器选择位,该位为1时是计数器模式,为0时是定时器模式。

M1M0——工作方式选择。下表所示(记)

M1 M0 工作方式
0   0   方式0,为13位定时器/计数器  
0   1   方式1,为16位定时器/计数器  
1   0   方式2,8位初值自动重装的8位定时器/计数器  
1   1   方式3,仅适用于T0,分成俩个8位计数器,T1停止计数  

我们之前计算的装载值N0是方式1的,方式0和方式2的计算类似,我们目前只用方式1的16位寄存器,之后博客中再总结方式0、2、3。

编写程序时需要选择使用定时器/计数器0还是1,此时要对TMOD寄存器的D7和D3的GATE进行操作,需要选择使用定时器还是计数器,此时需要对TMOD寄存器的俩个C/T位进行操作,需要选择工作方式,此时需要对TMOD寄存器的M1M0位进行操作。

查看头文件:

在这里插入图片描述

没有对该寄存器的每一位再重新定义,所以不能对寄存器每位单独操作。现举例说明:

(1)使用定时器0工作方式1

使用定时器0,若只受TCON寄存器的TR0控制启动和停止,低4位的GATE位为0,采用定时器,所以C/T位为0,方式1,所以M1M0位为01,所以TMOD寄存器的状态值:00000001,即0x01

程序:

TMOD=0x01;

(2)使用计数器1工作方式1

采用计数器1,所以TMOD高4位GATE=0(只受TR0控制),C/T位为1,M1M0位为01,所以TMOD的状态值:01010000,即0x50

程序:

TMOD=0x50;

(3)使用定时器1工作方式1、计数器0工作方式1

采用定时器1和计数器0,所以高4位和低4位的C/T位分别时0和1,GETA位都为0(分别只受TR1和TR0控制),M1M0位都为01,所以TMOD寄存器的状态值:00010101,即0x15

程序:

TMOD=0x15; 3、定时器/计数器控制寄存器TCON(Timer Control) 位序号 D7 D6 D5 D4 D3 D2 D1 D0
位符号   TF1   TR1   TF0   TR0   IE1   IT1   IE0   IT0  

上表从低位到高位:D0、D1是外部中断0,D2、D3是外部中断1,D4、D5是定时器中断0、D6、D7是定时器中断1

D7——>TF1定时器1溢出标志位(Timer Flag)
当定时器1计满溢出时,由硬件使IF1置1,并且申请中断,当进入中断服务函数后该位自动清零。

D6——>TR1定时器1运行控制位(Timer Running)
上一部分TMOD寄存器总结过,当GATE=0时,定时器/计数器启动和停止仅受TCON寄存器的TR0或TR1控制,当GATE=1时定时器/计数器启动和停止受TCON寄存器的(TR0或TR1)和(INT0或INT1)引脚的电平状态一起控制。所以当TMOD寄存器的GATE=1时,且INT1引脚为高电平,TR1软件置1启动定时器1,当TMOD寄存器的GATE=0时,TR1软件置1启动定时器1,不论GATE=1或0,TR1位软件置0即可关闭计数器1。

D5——>TF0定时器0溢出标志位(Timer Flag)
当定时器0计满溢出时,由硬件使IF0置1,并且申请中断,当进入中断服务函数后该位自动清零。

D4——>TR0定时器0运行控制位(Timer Running)
当TMOD寄存器GATE=0时,定时器/计数器启动和停止仅受TCON寄存器的TR0或TR1控制,当GATE=1时定时器/计数器启动和停止受TCON寄存器的(TR0或TR1)和(INT0或INT1)引脚的电平状态一起控制。所以当TMOD寄存器的GATE=1时,且INT0引脚为高电平,TR0软件置1启动定时器0,当TMOD寄存器的GATE=0时,TR0软件置1启动定时器0,不论GATE=1或0,TR0位软件置0即可关闭计数器0。

D3、D2、D1、D0是关于外部中断的,定时器中断用不到这四位,我们之后博客涉及到再详述。

五、总结+面向程序

到此为止,我们总结了四个寄存器分别是:中断允许寄存器IE、中断优先级寄存器IP、定时器/计数器工作方式寄存器TMOD、定时器/计数器控制寄存器TCON。

中断允许寄存器IE
EA是全局中断允许位,如果要使单片机使用中断,该位必须打开,所以程序开头必须对该位软件置1,从D0——D5是按照默认优先级顺序排列的,这6位是中断源允许位,单片机使用什么中断源,就将对应位软件置1。并且EA寄存器各位在头文件中都进行了定义,所以可以对任意一位单独操作。

中断优先级寄存器IP
该寄存器是设置高优先的,对于一般性工程,优先级按照默认顺序即可,没有必要使用IP,所以编写程序时,一般不使用该寄存器。

定时器/计数器工作方式寄存器TMOD
该寄存器高4位控制定时器/计数器1,低4位控制定时器/计数器0,D7、D3位的GATE一般为低电平,所以 计数器/定时器的通断只受TCON寄存器的TR1或TR0控制。D6、D2位C/T是定时器、计数器选择位,该位必须选。此外D5、D4和D1、D0的M1M0是工作方式选择位,一般为方式1的16位定时器/计数器,所以M1M0位为01。

此外需要注意该寄存器没有对每一位进行定义,程序中只能TMOD=0x…来设置TMOD寄存器。

定时器/计数器控制寄存器TCON
定时器中断中只用到高4位,其中D6位的TR1和D4位的TR0是需要软件操作的,因为与TMOD寄存器的GATE有关系,所以需要TR0、TR1来启动定时器/计数器

程序流程:
①TMOD设置GATE、C/T、M1M0(TMOD寄存器)
②装载初值TH(0/1),TL(0/1)
③EA=1 打开全局中断允许位,允许使用中断(IE寄存器)
④ET0=1或ET1=1(定时器中断,用不到外部中断)(IE寄存器)
⑤TR0=1或TR1=1,启动定时器(第一步设置GATE=0时)(TCON寄存器)

例:利用定时器1工作方式1实现LED每0.5s闪烁一次

根据上面的程序流程:
①定时器1工作方式1,所以TMOD高四位GATE=0,C/T=0,M1M0=01,所以TMOD=0x10;
②11.0592HZ晶振,装载初值:TH1=(65536-45875)/256;TL1=(65536-45875)%256;
③EA=1;
④ET1=1;
⑤TR1=1;

代码:

TMOD=0x10; TH1=(65536-45872)/256; TL1=(65536-45872)%256; EA=1; ET1=1; TR1=1;

写中断服务函数,格式:
void 函数名()interrupt 中断号 using 工作组
{
函数体
}
①中断服务函数是无返回值的函数,所以用关键字void
②中断号,与默认的优先级顺序一致,定时器0的中断号为1,定时器1的中断号为3
③工作组为单片机RAM区从0-31总共32字节分成四组工作寄存器,每组为8位寄存器,可以指定使用哪一组工作寄存器,C51编译时会自动分配工作组,所以“using 工作组”可以省略不写。