51单片机:02_定时中断和数码管刷新实现

276 阅读4分钟

中断和数码管的显示

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.7EA总中断使能位。1:使能所有中断;0:禁止所有中断。
IE.6-保留,未使用。
IE.5-保留,未使用。
IE.4ES串行口中断使能位。1:使能串行口中断。
IE.3ET1定时器1中断使能位。1:使能定时器1中断。
IE.2EX1外部中断1使能位。1:使能外部中断1。
IE.1ET0定时器0中断使能位。1:使能定时器0中断。
IE.0EX0外部中断0使能位。1:使能外部中断0。

例:要配置定时器0进行中断 EA = 1 ET0 = 1 EX0 =

1.2.2 中断优先寄存器

位位置位名称描述
IP.7-保留,未使用。
IP.6-保留,未使用。
IP.5-保留,未使用。
IP.4PS串行口中断优先级位。1:高优先级;0:低优先级。
IP.3PT1定时器1中断优先级位。1:高优先级;0:低优先级。
IP.2PX1外部中断1优先级位。1:高优先级;0:低优先级。
IP.1PT0定时器0中断优先级位。1:高优先级;0:低优先级。
IP.0PX0外部中断0优先级位。1:高优先级;0:低优先级。

1.2.3 中断服务函数

编号名称标志位中断使能拉默认优先级
0外部中断0IE0EX01高
1TO中断TF0ET02
2外部中断1IE1EX13
3T1中断TF1ET14
4UART中断T1/R1ES5
5T2中断TF2/EXF2ET26低

写代码时 在函数名后面加interrupt x即可

注:另外在使用定时中断时、还需要配置TCON寄存器 TR0=1

拿T0中中断配置举例:

要启用这个中断需要设置EA=1(总使能中断) ET0=1、TR0 = 1;当TF0=1(硬件自定设置)就会触发TO中断。

程序实例

使用定时器、每秒在数码管显示数字+1 ezgif-5-314dfca224.gif

一共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++;
	}
}