中断和数码管的显示
PRE
-
IE Interrupt Enable 中断使能寄存器
-
IP Interrupt Priority 中断优先寄存器
-
EX: External Interrupt Enable(外部中断使能)
-
ET: Timer Interrupt Enable(定时器中断使能)
-
ES: Serial Interrupt Enable(串行口中断使能)
-
EA: Enable All Interrupts(总中断使能)
1.中断
1.1 什么是中断
例1:代码执行过程中、遇到异常 比如 1/0 除0异常、将会中断程序、去执行异常的处理。
例2: 通信时经常用到,通信分为发送端S和接收端R,当R没有收到S的数据时、这时R不能就等待S发送数据,而不执行其他代码。解决:当R未收到S的数据时、处理其他程序。当R收到S的数据时触发中断,执行处理接收数据的程序。
例3: 程序执行过程中断电,触发系统中断保护现场。
1.2 中断配置
1.2.1 中断使能寄存器
| 位位置 | 位名称 | 描述 |
|---|---|---|
| IE.7 | EA | 总中断使能位。1:使能所有中断;0:禁止所有中断。 |
| IE.6 | - | 保留,未使用。 |
| IE.5 | - | 保留,未使用。 |
| IE.4 | ES | 串行口中断使能位。1:使能串行口中断。 |
| IE.3 | ET1 | 定时器1中断使能位。1:使能定时器1中断。 |
| IE.2 | EX1 | 外部中断1使能位。1:使能外部中断1。 |
| IE.1 | ET0 | 定时器0中断使能位。1:使能定时器0中断。 |
| IE.0 | EX0 | 外部中断0使能位。1:使能外部中断0。 |
例:要配置定时器0进行中断 EA = 1 ET0 = 1 EX0 =
1.2.2 中断优先寄存器
| 位位置 | 位名称 | 描述 |
|---|---|---|
| IP.7 | - | 保留,未使用。 |
| IP.6 | - | 保留,未使用。 |
| IP.5 | - | 保留,未使用。 |
| IP.4 | PS | 串行口中断优先级位。1:高优先级;0:低优先级。 |
| IP.3 | PT1 | 定时器1中断优先级位。1:高优先级;0:低优先级。 |
| IP.2 | PX1 | 外部中断1优先级位。1:高优先级;0:低优先级。 |
| IP.1 | PT0 | 定时器0中断优先级位。1:高优先级;0:低优先级。 |
| IP.0 | PX0 | 外部中断0优先级位。1:高优先级;0:低优先级。 |
1.2.3 中断服务函数
| 编号 | 名称 | 标志位 | 中断使能拉 | 默认优先级 |
|---|---|---|---|---|
| 0 | 外部中断0 | IE0 | EX0 | 1高 |
| 1 | TO中断 | TF0 | ET0 | 2 |
| 2 | 外部中断1 | IE1 | EX1 | 3 |
| 3 | T1中断 | TF1 | ET1 | 4 |
| 4 | UART中断 | T1/R1 | ES | 5 |
| 5 | T2中断 | TF2/EXF2 | ET2 | 6低 |
写代码时 在函数名后面加interrupt x即可
注:另外在使用定时中断时、还需要配置TCON寄存器 TR0=1
拿T0中中断配置举例:
要启用这个中断需要设置EA=1(总使能中断) ET0=1、TR0 = 1;当TF0=1(硬件自定设置)就会触发TO中断。
程序实例
使用定时器、每秒在数码管显示数字+1
一共3个主文件
main.c
Digtal.c 数码管相关功能
Timer.c 定时器、定时中断相关功能
Digtal.c 数码管相关
#include <REGX52.H>
#include "Delay.h"
//数码管 段码 NixieTable[0]显示数字0、NixieTable[1]显示数字1
unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
//当前数码管显示的数字
unsigned char digits[8] = {0,0,0,0,0,0,0,0};
/**
*
* @brief 在数码管上显示单个数字
* @param
* @retval
*/
void DigTalShow_Single(unsigned char Location,Number)
{
switch(Location) //位码输出
{
case 1:P2_4=0;P2_3=0;P2_2=0;break;
case 2:P2_4=0;P2_3=0;P2_2=1;break;
case 3:P2_4=0;P2_3=1;P2_2=0;break;
case 4:P2_4=0;P2_3=1;P2_2=1;break;
case 5:P2_4=1;P2_3=0;P2_2=0;break;
case 6:P2_4=1;P2_3=0;P2_2=1;break;
case 7:P2_4=1;P2_3=1;P2_2=0;break;
case 8:P2_4=1;P2_3=1;P2_2=1;break;
}
P0=NixieTable[Number]; //段码输出
Delay(1);//显示一段时间
P0=0x00;//段码清0,消影
}
/**
*
* @brief 根据数字 设置数码管上的数据
* @param
* @retval
*/
void DigTal_SetAndShow(unsigned int Number)
{
//取出
unsigned char i=0;
while (Number != 0) {
digits[i++] = Number % 10;
if(Number!=0){
Number /= 10;
}
}
for(i=0;i<8;i++){
DigTalShow_Single((i+1),digits[i]);
}
}
Timer.c 定时器相关
#include <REGX52.H>
/**
*
* @brief 初始化T0 中断
* @param
* @retval
*/
void Timer0_Interupt_init()
{
EA =1;//总使能
ET0=1;//使能T0定时器
TR0 = 1; //定时器0开始计时
TMOD =0X01;//定时器、工作模式1 即16位模式
}
/**
*
* @brief 设置5ms中断一次
* @param
* @retval
*/
void Timer0_05ms_Init()
{
TL0 = 0x00; //设置定时初值
TH0 = 0x4C; //设置定时初值
}
/* 定时器模板
void Timer0_Interrupt() interrupt 1
{
Timer0_05msStart();
// Code ...
}
*/
main.c 主函数
#include <REGX52.H>
#include "Digtal.h"
#include "Delay.h"
unsigned char Count =0;
unsigned int num = 1000;
void main()
{
// EA=1;
// TMOD=0X01;
// TL0 = 0x00; //设置定时初值
// TH0 = 0x4C; //设置定时初值
// ET0=1;
// TR0=1;
Timer0_Interupt_init();
Timer0_05ms_Init();
while(1)
{
DigTal_SetAndShow(num);
}
}
//使用 TO中断
void Timer0_Interrupt() interrupt 1
{
// TL0 = 0x00; //设置定时初值
// TH0 = 0x4C; //设置定时初值
Timer0_05ms_Init();
Count++;
if(Count>=20){
Count=0;
num++;
}
}