moonf99

定时器与中断系统

2023/07/21

关于定时器与中断系统的一点理解与想法。

定时器

在一个单片机上,我们可能会挂载多个设备,为了能够使其高效运行,我们通常会使用到定时器与中断系统。

定时器的工作原理:

51单片机内部有一个12MHZ的晶振(有些开发板上可能是11.0592MHZ),我们给其配置定时初值,每经过一个指令周期都会+1,当其溢出后,若CPU响应该中断,则会进入中断函数。

定时器(Timer)的配置

这是图片

定时器/计数器控制寄存器TCON

TCON为定时器/计数器T0,T1的控制寄存器,同时也锁存T0,T1溢出中断源和外部请求中断源等。
这是图片

TF1:定时器/计数器T1溢出标志。
TR1:定时器T1的运行控制位。
TF0:定时器/计数器T0溢出标志。发生中断时,TF0由硬件自动置1,当CPU响应中断后,才由硬件清零。
TR0:定时器T0的运行控制位。该位由软件置位和清零。当GATE(TMOD.3)=0,TR0=1时就允许T0开始计数,TR0=0时禁止T0计数。当GATE(TMOD.3)=1,TR1=0且INT0输入高电平时(既外部中断关闭和定时器1关闭时),才允许T0计数。
IE1:外部中断1请求源(INT1/P3.3)标志。
IT1:外部中断1触发方式控制位。
IE0:外部中断0请求源(INT0/P3.2)标志。外部中断0请求源(INT0/P3.2)标志。IE0=1外部中断0向CPU请求中断,当CPU响应外部中断时,由硬件清零IE0(边缘触发方式)。
IT0:外部中断0触发方式控制位。

注意:由于TCON寄存器可位寻址,所以可以对其每个位进行单独配置!

1
2
TF0=0;//清除TF0标志
TR0=1;//定时器0开始计时

定时器/计数器工作模式寄存器TMOD

定时和计数功能由特殊功能寄存器TMOD的控制位C/T进行选择。
这是图片
可以看出TMOD寄存器的高8位控制定时器1,低8位控制定时器0,需要注意的是,TMOD寄存器不可位寻址!

TMOD.7:TMOD.7控制定时器1,置1时只有在INT1脚为高及TR1控制位置1时才可打开定时器/计数器1。
TMOD.3:TMOD.3控制定时器0,置1时只有在INT0脚为高及TR0控制位置1时才可打开定时器/计数器0。
TMOD.6:TMOD.6控制定时器1用作定时器或计数器,清零则用作定时器(从内部系统时钟进入),置1用作计数器(从T1/P3.5脚输入)
TMOD.2:TMOD.2控制定时器0用作定时器或计数器,清零则用作定时器(从内部系统时钟进入),置1用作计数器(从T0/P3.4脚输入)
TMOD.5/TMOD.4:定时器/计数器1模式选择(0 0),(0 1),(1 0),(1 1)
TMOD.1/TMOD.0:定时器/计数器0模式选择(0 0),(0 1),(1 0),(1 1)

工作模式1(常用)框图
这是图片

1
2
3
4
//	TMOD=0x01;//0000 0001 这里将定时器0设定为16位定时器模式
TMOD=TMOD&0xF0;//把TMOD的低4位清0 高4位保持不变 设定定时器模式
TMOD=TMOD|0x01;//把TMOD的最低位置1 高4位保持不变 设定定时器模式
//高4位保持不变是为了防止需要配置到两个定时器时发生相互干扰的情况发生!

TH0与TL0

TH0(Timer High 0)与TL0(Timer Low 0)分别用来设定定时器0初值的高8位与低8位。

如何设定定时器初值?
已知定时器每1us计数加1,加到65535us(65ms)则发生溢出, 这样的话可以将初值设定为64535,与65535的差值刚好是1000us(1ms),即1ms后发生溢出。

TH1与TL1

用来设定定时器1,方法同上。


中断系统(Timer0/1)

能够使CPU处理多种突发任务,我们需要用到中断系统。当定时器的高位发生溢出时,则会进入某个中断服务函数,处理完后退出到主函数,直到下次溢出。进入中断服务函数,由于MCU的处理速度很快,我们总误认为MCU是多线程的,事实上,MCU在一个时刻只会处理一个事件,处理完后才会进入下个事件,所以MCU其实是在单线程地处理事件。

51系列单片机中断请求源

这是图片
及中断查询次序号
这是图片

中断结构

这是图片

以定时器0为例:先设置中断请求标志位(TF0),再设置溢出中断允许位(ET0),打开总中断(EA),接着进入中断优先级控制位(PT0)。

中断允许寄存器IE(Timer0/1)

用于是否允许中断

ET0:T0的溢出中断允许位。ET0=1,允许T0中断,ET0=0禁止T0中断。
ET1:作用同上。

注意:寄存器IE可位寻址!

中断优先级控制寄存器IPH/IP(Timer0/1)

这是图片
这是图片
PT0H,PT0:定时器中断优先级控制位。

当PT0H=0且PT0=0时,定时器0中断位最低优先级中断(优先级0)
当PT0H=0且PT0=1时,定时器0中断位较低优先级中断(优先级1)
当PT0H=1且PT0=0时,定时器0中断位较高优先级中断(优先级2)
当PT0H=1且PT0=1时,定时器0中断位最高优先级中断(优先级3)

PT1H,PT1:定时器1中断优先级控制位。

作用同上。

注意:IPH不可位寻址,IP可位寻址!

定时器/计数器0/1控制寄存器TCON

TCON位定时器/计数器T0,T1的控制寄存器,同时也锁存T0,T1溢出中断源和外部请求中断源等。
这是图片

TR0:定时器0的运行控制位。
TF0:T0溢出中断标志。由硬件置1或清0,在CPU响应后才清0。
TR1,TF1同上。

注意:TCON可位寻址!

1
2
TF0=0;//清除TF0标志
TR0=1;//定时器0开始计时

食用例

按键控制LED流水灯模式
按下键码1控制流水灯顺序
Timer0.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
oid Timer0Init()
{
// TMOD=0x01;//0000 0001
TMOD=TMOD&0xF0;//把TMOD的低4位清0 高4位保持不变 设定定时器模式
TMOD=TMOD|0x01;//把TMOD的最低位置1 高4位保持不变 设定定时器模式
TL0=0x18;//64535%256
TH0=0xFC;//64535/256
TF0=0;//清除TF0标志
TR0=1;//定时器0开始计时
ET0=1;//T0的溢出中断允许位
EA=1;
PT0=0;
}

/*定时器中断函数模板
void Timer0_Routine() interrupt 1
{
static unsigned int T0Count;
TL0=0x18;
TH0=0xFC;
T0Count++;
if(T0Count>=1000)
{
T0Count=0;
}
}
*/

main.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
unsigned char KeyNum,LEDMode;

void main()
{
P2=0xFE;
Timer0Init();
while(1)
{
KeyNum=Key();
if(KeyNum)
{
if(KeyNum==1)
{
LEDMode++;
if(LEDMode>=2)LEDMode=0;
}
}
}
}


void Timer0_Routine() interrupt 1
{
static unsigned int T0Count;
TL0=0x18;
TH0=0xFC;
T0Count++;
if(T0Count>=500)
{
T0Count=0;
if(LEDMode==0)
{
P2=_crol_(P2,1);
}
if(LEDMode==1)
{
P2=_cror_(P2,1);
}
}
}
CATALOG
  1. 1. 定时器
    1. 1.1. 定时器的工作原理:
    2. 1.2. 定时器(Timer)的配置
      1. 1.2.1. 定时器/计数器控制寄存器TCON
      2. 1.2.2. 定时器/计数器工作模式寄存器TMOD
      3. 1.2.3. TH0与TL0
      4. 1.2.4. TH1与TL1
  2. 2. 中断系统(Timer0/1)
    1. 2.1. 51系列单片机中断请求源
    2. 2.2. 中断结构
      1. 2.2.1. 中断允许寄存器IE(Timer0/1)
      2. 2.2.2. 中断优先级控制寄存器IPH/IP(Timer0/1)
      3. 2.2.3. 定时器/计数器0/1控制寄存器TCON
  3. 3. 食用例