现在按自己的思路从头把流程和各种符号梳理一下。
在实验中,通过运行例子程序,程序在k3键按下的下一步进入中断处理程序
此过程涉及到两个寄存器的设置定时/计数器中断
此过程涉及到三个寄存器的设置
这一过程称为中断
中断允许寄存器IE(Interrupt Enable)
CPU对中断系统所有中断以及某个中断源的开放和屏蔽是由中断允许寄存器IE控制的。
TCON定时器/计数器控制寄存器/逻辑板(Timer Control Register)
中断源 | 中断请求标志 | 中断允许控制 | |||||
中断源符号 | 名称 | 中断引起原因 | 中断号 | 优先级 | 控制位 | 标志位 | 允许控制位 |
/INT0 | 外部中断0 | P3.2引脚低电平或下降沿信号 | 0 | 高 | IT0 | IE0 | EXO |
T0 | 定时器0中断 | 定时/计数器0计数0溢出 | 1 | ↓ | TR0 | TF0 | ETO |
/INT1 | 外部中断1 | P3.3引脚低电平或下降沿信号 | 2 | ↓ | IT1 | IE1 | EX1 |
T1 | 定时器1中断 | 定时/计数器1计数0溢出 | 3 | ↓ | TR1 | TF1 | ET1 |
TI/RI | 串行口中断 | 串行通信完成一帧数据发送或接收引起中断 | 4 | 低 | RI或TI | ES | |
EA:CPU中断允许(总允许)位 |
1、设置中断触发方式,即IT0=1或0,IT1=1或0
2、开对应的外部中断,即EX0=1或EX1=1;
3、开总中断,即EA=1;
4、等待外部设备产生中断请求,即通过P3.2,P.3.3口连接外部设备产生中断
5、中断响应,执行中断服务函数
eg. 外部中断0实验 *
实现现象:下载程序后按下K3按键可以对D1小灯状态取反。
#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
sbit k3=P3^2; //定义按键K3
sbit led=P2^0; //定义P20口是led
void delay(u16 i)
{
while(i--);
}
void Int0Init()
{
//设置INT0
IT0=1;//跳变沿出发方式(下降沿)
EX0=1;//打开INT0的中断允许。
EA=1;//打开总中断
}
void main()
{
Int0Init(); // 设置外部中断0
while(1);
}
void Int0() interrupt 0 //外部中断0的中断函数
{
delay(1000); //延时消抖
if(k3==0)
{
led=~led;
}
}
可见,由溢出时计数器的值减去计数初值才是加1计数器的计数值。
51单片机定时/计数器的工作由两个特殊功能寄存器控制。TMOD用于设置其工作方式;TCON用于控制其启动和中断申请。
GATE是门控位, GATE=0时,用于控制定时器的启动是否受外部中断源信号的影响。只要用软件使TCON中的TR0或TR1为1,就可以启动定时/计数器工作;GATA=1时,要用软件使TR0或TR1为1,同时外部中断引脚INT0/1也为高电平时,才能启动定时/计数器工作。即此时定时器的启动条件,加上了INT0/1引脚为高电平这一条件。
C/T :定时/计数模式选择位。C/T =0为定时模式;C/T =1为计数模式。
M1M0:工作方式设置位。定时/计数器有四种工作方式。
工作方式寄存器TMOD(Timer/Counter Mode Control Register)
工作方式寄存器TMOD用于设置定时/计数器的工作方式,低四位用于T0,高四位用于T1。其格式如下:
定时器/计数器控制寄存器/逻辑板TCON(Timer Control Register)
TCON的低4位用于控制外部中断,已在前面介绍。TCON的高4位用于控
制定时/计数器的启动和中断申请。其格式如下
1、方式0
方式0为13位计数,由TL0的低5位(高3位未用)和TH0的8位组成。TL0的低5位溢出时向TH0进位,TH0溢出时,置位TCON中的TF0标志,向CPU发出中断请求。计数初值计算的公式为:X=213-N。
2、方式1
方式1的计数位数是16位,由TL0作为低8位,TH0作为高8位,组成了16位加1计数器 。计数个数与计数初值的关系为:X=216-N
3、方式2
方式2为自动重装初值的8位计数方式。计数个数与计数初值的关系为:X=28-N
工作方式2特别适合于用作较精确的脉冲信号发生器。
4、方式3
方式3只适用于定时/计数器T0,定时器T1处于方式3时相当于TR1=0,停止计数。 工作方式3将T0分成为两个独立的8位计数器TL0和TH0 。
eg.定时器0实验 *
实现现象:下载程序后D1小灯循环点亮1秒,熄灭1秒。使用单片机内部定时器可以实现准确延时。
#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
sbit led=P2^0; //定义P20口是led
void Timer0Init()
{
TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。
TH0=0XFC; //给定时器赋初值,定时1ms
TL0=0X18;
ET0=1;//打开定时器0中断允许
EA=1;//打开总中断
TR0=1;//打开定时器
}
void main()
{
Timer0Init(); //定时器0初始化
while(1);
}
void Timer0() interrupt 1
{
static u16 i;
TH0=0XFC; //给定时器赋初值,定时1ms
TL0=0X18; //此处第二次赋初值是为了让中断程序重复工作,但我的对它的理解还有些模糊,请路过的高手讲解一下
i++;
if(i==1000)
{
i=0;
led=~led;
}
}