关于单片机的计时器与中断系统
下面进入正题:
1、计时器
下面先看一个图:
其中可以清楚的看到,TH0和TL0是两个8位寄存器,这两个寄存器组合成T0加1计数器,所以计数器为16位计数器。同理,TL1和TH1组合成了T1加1计数器。
再看TMOD寄存器,它是一个8位寄存器,名字叫做工作方式寄存器,显然它是控制工作方式的,看电路图上看它有两条灰色的线条延伸到T0和T1,即它可控制T0和T1的工作方式,也可以清楚的看到,其低四位控制T0的工作方式,高4位控制T1的工作方式。
那么什么叫做工作方式呢?工作方式就是指开或者关,芯片是工作在定时模式还是计数模式,和寄存器的使用情况。总体如下:
GATE是门控位,GATE=0时,TCON中TR0/TR1=1时可启动。
GATE=1时,TCON中TR0/TR1=1,且外部中断引脚为高电平时可启动。
C/T=0:定时模式。
M1M0组合使用,其值如下:
00 | 13位定时/计数器 |
01 | 16位定时/计数器 |
10 | 8位自动重装定时/计数器 |
11 | T0分成两个定时/计数器,T1停止 |
再看TCON寄存器,它与TMOD一样,叫做控制寄存器,它是用于控制外部中断启动、申请的一系列工作的。定时器/计数器的工作要依赖于溢出中断,在中断处理中处理相关事件T0或者T1寄存器溢出时会申请中断,然后再处理。比如所以如果想要使用T0计数100,那么就用16位寄存器的溢出值减去初始值,既是计数值,那么就是65536-100=65436(65536-65436=100),所以T0要首先置初始值65436。这里先介绍TCON的高4位。
TF1:T1溢出中断请求标志位,T1溢出时TF1为1,相应中断后自动清0,也可使用软件控制。
TR1:T1运行控制位,TR1为1时,T1工作,TR1为0时,T1停止工作。
TF0:T0溢出中断请求标志位。同理TF1。
TR0:T0运行控制位,同理TR1。
M1M0控制的四种工作方式如下:
00 | 13位计数,使用了TL0的低5位和TH0的8位组成,TH0溢出置TF0中断。 |
01 | 16位计数,使用T0。同00。 |
10 | 自动重装初值的8位计数方式。 |
11 | T1停止,TH0和TL0分开计数。 |
计时器使用步骤:
·对TMOD赋值,确定T1、T0的工作方式。
·计算初值,并将其写入T0或者T1。
·对IE(IE后面再介绍)赋值,开放中断。
·使TR0或者TR1置位,启动计数。
二、中断
中断估计都知道是干啥的,这些就不啰嗦了,这里先上一幅图:
看这图估计都没心情,下面剖开来看:

其他的先不看,先看这点图,这是一个中断源,其中IT0是选择中断的方式,IT0=1时为选择下降沿有效,IT0=0时为低电平有效(有一个非门)。当中断触发时就将IE0置1,此时,向CPU申请中断。那么,IT0和IE0是在什么地方呢?
还记得上面讲的TCON吗?现在把低四位也加进去:
TF1 | TR1 | TF0 | TR0 | IE1 | IT1 | IE0 | IT0 |

参照1:INT0。
3、

TF0中断,上面已经介绍。
4、

TF1中断,上面已经介绍。
5、(RI或TI中断)

串行口中断请求标志,当串行口接收完一帧串行数据时,置位RI或当串行口发送完一帧串行数据时置位TI,向CPU申请中断。
TCON中断
其中,TCON中的中断标志有如下几个:TF1 | TR1 | TF0 | TR0 | IE1 | IT1 | IE0 | IT0 |
·IT0=0为下降沿有效
·IT0=1为负边沿触发
IE0:外部中断0中断请求标志位。
IT1:外部中断1触发方式控制位(同IT0)。
IE1:外部中断1中断请求标志位。
TF0:T0溢出中断。
TF1:T1溢出中断。
SCON中断
SCON中的中断如下:TI | RI |
TI:串行口发送中断标志位。当CPU将一个发送数据写入串行口发送缓冲器时,就启动了发送过程,每发送完一个串行帧,由硬件置位TI,CPU响应中断时,不能自动清除TI,TI必须由软件清除。
下面再看上图的下一部分:

这部分叫做中断允许控制,当一个中断发生时,必须由中断允许控制来检测是否允许,如果允许则转入中断处理,否则不处理。
先看右边的EA,这个是总的中断允许控制位,CPU想要处理中断,必须开此中断允许。
再看左边:
其中各个中断允许控制如下:
·EX0:外部中断0允许位
·ET0:T0中断允许位
·EX1:外部中断1允许位
·ET1:T1中断允许位
·ES:串行口中断允许位
其中,这几个位都是由中断允许寄存器IE控制的,IE寄存器具体如下:
EA | ES | ET1 | EX1 | ET0 | EX0 |
很明了,中断响应条件如下:
1、有中断请求
2、中断源中断允许位为1
3、CPU开中断(EA=1)
其中,8051有两个中断优先级,可以实现二级中断嵌套。每个中断源的中断优先级都是由中断优先级寄存器IP中的相应位的状态来规定的。
IP寄存器如下:

PT2 | PS | PT1 | PX1 | PT0 | PX0 |
可以按照上图以此类推。
(这里,PT2是80C52的中断,不介绍)
优先级高的中断可以打断优先级低的中断而先执行,实现中断嵌套。那么同一优先级之间不能打断,如果多个同优先级中断同时申请,则按照自然优先级顺序执行中断,自然优先级如下:
中断源 | 中断标志 | 中断服务程序入口 | 优先级顺序 |
外部中断0 | IE0 | 0003H | 高 |
T0 | TF0 | 000BH | ↓ |
外部中断1 | IE1 | 0013H | ↓ |
T1 | TF1 | 001BH | ↓ |
串行口中断 | RI或者TI | 0023H | 低 |
中断使用方法如下所示:
函数名
例如:void
那么,这里的x代表的是何种中断具体如下:
0:代表外部中断0
1:定时/计数器0
2:外部中断1
3:定时/计数器1
4:串行口中断
这里y代表寄存器组,可取0~7,也可以不写。
例如,外部中断0可以写:
interrupt
外部中断1可写
interrupt
下面看一个使用定时器和中断的数字时钟的例子:
#include
#define
uchar
uchar
uchar
void
int
while(a--){
for(i=0;i<148;i++);
}
}
//次函数表明使用的是定时器,定时为50ms
void
{
TMOD
//TMOD为
//且为16位定时器,GATE=0,配合下面TR0=1,则启动寄存器
TH0
//设定初值,即设定定时时间
TL0
//设定初值,即设定定时时间
IE
//0x82二进制为1000
//设定允许响应总中断和T0中断
TR0
//设置TCON中TR0=1,允许T0工作
}
void
{
TH0
//重新设定初值
TL0
count++;
if(count==20){
count=0;
second++;
//时间秒数加1
}
}
uchar
uchar
uchar
int
for(i=0;i<4;i++){
P1=hang[i];
temp=0x10;
for(j=0;j<4;j++){
if(!(temp&P1)){
return
}
temp<<=1;
}
}
return
}
uchar
uchar
uchar
P2=0;
P0=tab[y/10]-0x80;
Delay(1);
P2=1;
P0=tab[y];
return
}
uchar
uchar
uchar
P2=3;
P0=tab[y/10]-0x80;
Delay(1);
P2=4;
P0=tab[y];
return
}
uchar
uchar
uchar
P2=6;
P0=tab[y/10]-0x80;
Delay(1);
P2=7;
P0=tab[y];
return
}
void
{
uchar
uchar
uchar
Time0_Init();
while(1){
Delay(1);
if(mk==0){
s=show_second(second);
second%=60;
mk++;
}
else
minute+=s;
m=show_minute(minute);
minute%=60;
mk++;
}else{
hour+=m;
h=show_hour(hour);
hour%=24;
mk++;
mk=mk%3;
}
k=
if(12==k||13==k||14==k){
Delay(50);
k=
if(12==k||13==k||14==k){
if(12==k)hour++;
else
else
}
}
}
}
评论