记录学习中断的使用。
使用开发板:
普中科技开发板
编译软件:
keil
CPU在处理 事件A 时,中断源 发出中断请求,请求cpu处理事件B ,cpu 中断 当前工作,转去处理事件B(中断响应和中断服务),待cpu将 事件B 处理完成后,再回到原来被中断的地方,继续处理事件A。
作用:分时操作,提高计算机的利用率。实时响应,及时处理应用系统的随机事件。可靠性高,具有处理设备故障及掉电等突发性事件。
89C51的中断系统有5个中断源 (INT0, T0, INT1, T1, RI/TI)
CPU 对 中断系统所有中断是否打开及相应控制 由 中断允许寄存器IE 控制的。
中断标志
各个中断源响应优先级及中断服务。当同一等级优先级的有多个时,存在排队问题。
51单片机的中断优先级三条原则:
#include "reg52.h"
typedef unsigned int u16;
typedef unsigned char u8;
sbit k3=P3^2;
sbit k4=P3^3;
sbit led=P2^0;
/*******************************************************************************
* 函 数 名 : delay
* 函数功能 : 延时函数,i=1时,大约延时10us
*******************************************************************************/
void delay(u16 i)
{
while(i--);
}
/*******************************************************************************
* 函 数 名 : Interrupt0Init
* 函数功能 : 设置外部中断0
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Interrupt0Init()
{
//设置中断0 INT0
IT0 = 1;//跳变沿出发方式(1:下降沿,0:低电平触发)
EX0 = 1;//打开INT0 的中断允许
EA= 1 ;//打开总中断
}
/*******************************************************************************
* 函 数 名 : Interrupt1Init
* 函数功能 : 设置外部中断1
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Interrupt1Init()
{
//设置中断1 INT1
IT1 = 1;//跳变沿出发方式(下降沿)
EX1 = 1;//打开INT1 的中断允许
EA= 1 ;//打开总中断
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
Interrupt0Init();// 设置外部中断0
while(1);
}
/**************************************************************************************
* 外部中断0实验 *
实现现象:下载程序后按下K3按键可以对D1小灯状态取反。
注意事项:无。
***************************************************************************************/
void InterruptTest0() interrupt 0 //外部中断0 的 中断函数
{
delay(1000); //延时消抖
if(k3 == 0)
{
led=~led;
}
}
/**************************************************************************************
* 外部中断0实验 *
实现现象:下载程序后按下K3按键可以对D1小灯状态取反。
注意事项:无。
***************************************************************************************/
void InterruptTest2() interrupt 2 //外部中断1 的 中断函数
{
delay(1000); //延时消抖
if(k4 == 0)
{
led=~led;
}
}
振荡周期:为单片机提供定时信号的振荡源的周期(晶振周期或外加振荡周期)
状态周期:2个振荡周期为1个状态周期。
机器周期:1个机器周期含6个状态周期, 12 个振荡周期。
指令周期:完成1条指令所占用的全部时间。它心机器周期为单位。
例如:常用外接晶振为12MHz, 振荡周期为 1/12us, 状态周期:1/6us, 机器周期:1us,指令周期:1~4us。
定时器/计数器需要注意以下几点:
第一点:定时器/计数器和单片机的CUP是相互独立的。定时器/计数器工作过程是自动完成的, 不需要CPU的参与。
第二点:51单片机中的定时器/计数器量根据机器内部的时钟或者是的脉冲信号对寄存器中的数据加1。
定时/计数器的工作原理:
定时/计数器实质上是一个加1计数器。它随着计数器的输入脉冲进行自加1。也就是每来一个脉冲计数器就自动加1,池加到计数器为全1时,再输入一个脉冲就使计数器回零,且计数器的溢出使相应的中断标志位置 1, 向CPU发出中断请求(定时/计数器中断允许时)。
由溢出时计数器的值 减 去计数初值才是加1 计数器的计数值。
定时/计数器的实质量加1 计数器(16位),由高8位和低8位两个寄存器THx和TLx组成。TMOD是定时/计数器的工作方式寄存器,确定工作方式和功能: TCOM 是控制寄存器T0,T1的启动和停止胡设置溢出标志。
低四位用于T0,高四位用于T1。
GATE是门控位,GATE=0时,用于控制定时器 的 启动是否受外部中断 中断源信号 的影响。只要用软件TCON中TR0或TR1为1,就可以启动定时/计数器工作:GATE=1时,要用软件TR0或TR1为1,同时外部中断引脚INT0/1也为高电平时,才能启动定时/计数器工作。
C/T::定时、计数模式选择位。C/T=0 为定时模式;C/T=1时,为计数模式。
M1M0:工作方式设置位。定时/计数器有四种工作方式。
TCON的低4位用于控制外部中断,高4位用于控制定时/计数器的启动和中断申请。
定时器模式时 N=t/Tcy
计数初值的公式为:X= 2^n-N;n为计数位数(方式0为13位,方式1为16位)。定时器的初值还可以采用计数个数直接取补法获得。
计数模式时,计数脉冲是T0引脚上的外部脉冲。
门控位GATE具有特殊的作用。当GATE=0时,经反相后使或门输出为1 ,此时仅由TR0控制与门的开启。当GATE=1时,由外中断引脚信号控制或门输出,此时控制与门的开启由外中断引脚信号和TR0共同控制。当TR0=1时,外中断引脚信号引脚的高电平启动计数,外中断引脚信号引脚的低电平停止计数。常用来测量外中断引脚上正脉冲的宽度。
方式0:
方式0为13位计数。由TL0的低5位和TH0的8位组成。TL0的低5位溢出时向TH0进位,TH0溢出时,置位TCON中的TF0标志,向CPU发出中断请求。
方式1:
方式1的计数位数是16位,由TL0作为低8位,TH0作为高8位,组成了16位加1计数器。
计数个数与计数初值的关系为:X=2^16-N
方式2:
方式2为看上去重装初值的8拉计数方式。
计数个数与计数初值的关系为:X=2^8-N
工作方式2特别适合用于作较精确的脉冲信号发生器。
方式3:
方式3只适用于定时/计数器T0,定时器T1处于方式3时相当于TR1-0,停止计数。
使用定时器步骤:
计数器初值的计算
时钟周期与时钟频率互为倒数。例如:频率为20赫兹(Hz),周期为1/20=0.05秒(s)。
例如:要求1s的初值,1s/1us=1000000 ,需要计数1000000,初值=0XFFFF-1000000+1(65535=0xFFFF 即 16位计数),注意:此时计数已经超过 65535 所以 不能直接 定时1 s.
示例代码:
#include "reg52.h"
typedef unsigned int u16;
typedef unsigned char u8;
sbit k3=P3^2;
sbit k4=P3^3;
sbit led=P2^0;
u16 m = 0;
/*******************************************************************************
* 函 数 名 : delay
* 函数功能 : 延时函数,i=1时,大约延时1s
*******************************************************************************/
void delay(u16 i)
{
while(1)
{
if(m == i*20)
{
m = 0;
led=~led;
}
}
}
/*******************************************************************************
* 函 数 名 : Timer0Init
* 函数功能 : 定时器0初始化
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Timer0Init()
{
TMOD |= 0X01;//启用定时模式
TH0= 0Xfc; //给定时器赋初值,定时1ms
TL0 = 0X18;
ET0=1;//打开定时器0中断允许
EA = 1;//打开总中断
TR0 =1; //打开定时器
}
/*******************************************************************************
* 函 数 名 : Timer1Init
* 函数功能 : 定时器1初始化
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Timer1Init()
{
TMOD |= 0X10;//启用定时模式 ,使用或(|),防止0位对TMOD寄存器产生干扰
TH1= 0X3c; //给定时器赋初值,定时50ms
TL1 = 0Xb0;
ET1=1;//打开定时器1中断允许
EA = 1;//打开总中断
TR1 =1; //打开定时器
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
//Interrupt0Init();// 设置外部中断0
Timer1Init();
delay(5);
}
/**************************************************************************************
* 外部中断0实验 *
实现现象:下载程序后按下K3按键可以对D1小灯状态取反。
注意事项:无。
***************************************************************************************/
void InterruptTest0() interrupt 0 //外部中断0 的 中断函数
{
delay(1000); //延时消抖
if(k3 == 0)
{
led=~led;
}
}
/**************************************************************************************
* 外部中断0实验 *
实现现象:下载程序后按下K3按键可以对D1小灯状态取反。
注意事项:无。
***************************************************************************************/
void InterruptTest2() interrupt 2 //外部中断1 的 中断函数
{
delay(1000); //延时消抖
if(k4 == 0)
{
led=~led;
}
}
/*******************************************************************************
* 函 数 名 : void Timer0InterruptTest() interrupt 1
* 函数功能 : 定时器0中断函数
* 输 入 : 无
* 输 出 : 无
* 注意事项 :如果执行程序过长,则不能放在中断中
*******************************************************************************/
void Timer0InterruptTest() interrupt 1
{
static u16 i;
TH0= 0Xfc;
TL0 = 0X18;
i++;
if(i == 1000)
{
i=0;
led=~led;
}
}
/*******************************************************************************
* 函 数 名 : void Timer1InterruptTest() interrupt 3
* 函数功能 : 定时器1中断函数
* 输 入 : 无
* 输 出 : 无
* 注意事项 :如果执行程序过长,则不能放在中断中,否则将会影响产生中断时间,将执行程序放入延时delay函数中
*******************************************************************************/
void Timer1InterruptTest() interrupt 3
{
TH1= 0X3c;
TL1 = 0Xb0;
m++;
}