51单片机定时器中断的详细理解

1. 首先附上代码例子

#include <AT89X52.H> 
#define uint unsigned int  
#define uchar unsigned char  
uint i,j;  
main(){
i=0;
j=0;
EA=1; //中断总开关开  
ET0=1;//定时器T0中断允许   
ET1=1;//定时器T1中断允许  
TR0=1;// 启动定时器T0
TR1=1;// 启动定时器T1
TMOD=0x11;//使用定时器T0的模式1  定时器T1的模式1



TH0=(65536-50000)/256; //定时器T0的高8位赋初值
TL0=(65536-50000)%256; //定时器T0的高8位赋初值



TH1=(65536-50000)/256; //定时器T1的高8位赋初值
TL1=(65536-50000)%256; //定时器T1的高8位赋初值




P0=0x00;   //打开所有P0口的LED灯
P1=0xff;   //关闭所有P1口的LED灯
while(1); //无限循环,


}
   


/**************************************************************
函数功能:定时器T0中断服务程序
**************************************************************/
void int1(void) interrupt 1 //“interrupt”声明函数为中断服务函数
{
i=i+1;
if(i==40){
 
       P0=~P0;   //P0口的LED灯取反
   i=0;
}                 
  TH0=(65536-50000)/256; //定时器T0的高8位重新赋初值
TL0=(65536-50000)%256; //定时器T0的高8位重新赋初值
 }


 /**************************************************************
函数功能:定时器T1中断服务程序
**************************************************************/
void int2(void) interrupt 3 //“interrupt”声明函数为中断服务函数
{
   
j=j+1;
if(j==40){
 
       P1=~P1;    //P1口的LED灯取反
   j=0;
}                 
  TH1=(65536-50000)/256; //定时器T1的高8位重新赋初值
TL1=(65536-50000)%256; //定时器T1的高8位重新赋初值
  
 }

问题一:数码管常常会遇到显示不出数字,有时,当你在中断加一个条件时,就不能显示了,删掉就可以

解决:中断里的这两行代码必须放在最结尾,则可以显示正常

TH1=(65536-50000)/256; //定时器T1的高8位重新赋初值
TL1=(65536-50000)%256; //定时器T1的高8位重新赋初值

2.定时器初始化部分

EA=1; //中断总开关开  
ET0=1;//定时器T0中断允许   
ET1=1;//定时器T1中断允许  
TR0=1;// 启动定时器T0
TR1=1;// 启动定时器T1
TMOD=0x11;//使用定时器T0的模式1  定时器T1的模式1

下面细说下为什么要这么配置

3.中断寄存器

首先分为6个大部分

IE   – 中断允许控制寄存器(重点)
IP   – 中断优先级控制寄存器
TMOD – 定时器工作方式寄存器(重点)
TCON – 定时器控制寄存器(重点)
SCON – 串口控制寄存器
THx/TLx – 定时器初值寄存器(重点)

3.1中断允许控制寄存器 IE

序号D7D6D5D4D3D2D1D0
符号EA-ET2ESET1EX1ET0EX0
EA -全局中断允许位,当此位是1时中断可用。(重要)
ET2-定时器/计数器2中断允许位
ES -串口中断允许位
ET1-定时器/计数器1中断允许位
EX1-外部中断1允许位
ET0-定时器/计数器0中断允许位 (重要)
EX0-外部中断0允许位

要使用定时器中断,需要将IE寄存器中的EA位设置为1,以及需要将ETx(x = 0,1,2)设置为1

3.2定时器控制寄存器 TCON

该寄存器用于控制中断,如控制定时器的启动,停止、判断定时器的溢出和中断情况。

序号D7D6D5D4D3D2D1D0
符号TF1TR1TF0TR0IE1IT1IE0IT0
TF1 定时器1溢出标志位
TR1 定时器1运行控制位,将该位置1时启动定时器1(重要)
TF0 定时器0溢出标志位
TR0 定时器0运行控制位,将该位置1时启动定时器0 (重要)
IE1 外部中断1请求标志
IT1 外部中断1触发方式选择位
IE0 外部中断0请求标志
IT0 外部中断0触发方式选择位

3.3定时器初值寄存器 THx/TLx

以定时器T0为例,其的工作原理是,每当晶振产生一次脉冲,就将该寄存器TL0加一,当TL0加满溢出后,将TL0清空,TH0加一,TH0计满后产生定时中断。即TH0与TL0组成了一个16位的计数器,这个计数器可以从0x0000(0)加到0xffff(65535)。

常见的有2种设计方式:

第一种
TH0=(65536-50000)/256; //定时器T0的高8位赋初值
TL0=(65536-50000)%256; //定时器T0的高8位赋初值

TH1=(65536-50000)/256; //定时器T1的高8位赋初值
TL1=(65536-50000)%256; //定时器T1的高8位赋初值

50000就是我们设置的时间,比如机械周期是1us,那么

50000*1us=50ms

这种方法很直观,我比较喜欢用这种

第二种
TH0 = 0x3c;//高位
TL0 = 0xb0; //低位

首先把高低位拼在一起

THTL=0x3cb0

需要转换成10进制

THTL =15536

求出我们设定的时间值

65536-15536=50000

如果想要修改时间,也需要反推到源头,十分麻烦,当然也许有其他见解,有待补充。
TH0代表我选用的是定时器0。

4.定时器工作方式寄存器 TMOD

在这里插入图片描述
一共有四种模式
在这里插入图片描述
可以看到 TO受低四位控制,T1受高四位控制。

举个例子

TMOD=0x11;//使用定时器T0的模式1  定时器T1的模式1

根据上面,可以知道
T0定时器采用01工作方式
T1定时器采用01工作方式
如果你没开启定时器1,就置零

TR1=0;// 关闭定时器T1
TMOD=0x01;

下面详细说下四种方式

方式0:13位定时器/计数器,TH0的高8位,TL0的低5位

在这里插入图片描述

方式1:16位定时器/计数器,TH0的高8位,TL0的低8位

在这里插入图片描述

方式2:自动重装的8位计数器,TL0用于计数,TH0用于备份

在这里插入图片描述

方式3:被分为TH0和TL0两个独立的8位计数器(只有T0可以在方式3下工作)

在这里插入图片描述

5.时钟周期/机器周期计算:

在这里插入图片描述

6.中断服务程序的格式

中断写法

void 函数名() interrupt 中断号 using 工作组
{
  //所要执行内容
}

1.中断服务函数要写在主函数后面,且不需要声明 。
2.中断服务函数无返回值,所以用void
3.函数名可以随便起
4.interrupt后的中断号由下表的重点服务号确定
5.using 工作组可省略不写

在这里插入图片描述
举个例子

void int1(void) interrupt 1 //“interrupt”声明函数为中断服务函数
{
i=i+1;
if(i==40){
 
       P0=~P0;   //P0口的LED灯取反
   i=0;
}                 
  TH0=(65536-50000)/256; //定时器T0的高8位重新赋初值
TL0=(65536-50000)%256; //定时器T0的高8位重新赋初值
 }

1对应的是T0 – 定时器/计数器0中断

  • 34
    点赞
  • 257
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值