51单片机中断说明与应用数码管秒表计时,顺手解决最后一位数码管过亮问题----day4

51单片机中断说明与应用----day4
1.中断概念:
当CPU在处理某项任务的时候, 在外界发生了紧急事件, 要求CPU暂停现在的工作而去处理这个紧急事件, 待事件处理完后, 再回到原
来中断的地方, 继续执行原来被中断的程序, 这个过程叫做中断。
在这里插入图片描述
优先级顺序:高级中断可以打断低优先级中断,低优先级中断可以打断普通任务。
51单片机中断请求源:
1.外部中断请求源
外部中断0和外部中断1, 是通过外部引脚引入的。
2.内部中断请求源
两个定时器/计数器溢出中断和一个串行口中断。
中断向量表:
在这里插入图片描述
序号 中断向量入口地址
0 3
1 11
2 19
3 27
4 35

       *0*8+3=3
       1*8+3=11
       2*8+3=19
       3*8+3=27
       4*8+3=35
       (中断向量表地址-3)/8=中断向量表序号
       void interrupt_time() **interrupt **3*****

中断内部流程如下图所示:
在这里插入图片描述
1.定时器控制寄存器(TCON)内容

IT0和(IT1) = 1 脉冲触发方式, 下降沿有效
IT0和(IT1) = 0 电平触发方式, 低电平有效
IE0和IE1——外部中断请求标志位
当CPU采样到 (或) 端出现有效请求时, IE0(IE1)位由硬件置“1” 。 当中
断响应完成转向中断服务程序时
, 由硬件把IE0( IE1) 清“0” 。
INT0 INT1
TR0和TR1——定时器运行控制位
TR0和(TR1) = 0 定时器/计数器不工作
TR0和(TR1) = 1 定时器/计数器开始工作
TF0和TF1——计数溢出标志位
当计数器产生计数溢出时, 相应的溢出标志位由硬件置“1” 。 当转向中断服务时,
再由硬件自动清“0” 。 计数溢出标志位的使用有两种情况: 采用中断方式时, 作中
断请求标志位来使用; 采用查询方式时, 作查询状态使用。
2.串行控制寄存器(SCON)内容
在这里插入图片描述

TI——串行口发送中断请求标志位
当发送完一帧数据后, 由硬件置位“1” ; 在转向中断服务后程序后, 用软件清
“0” 。
RI——串行口接收中断请求标志位
当接收完一帧数据后, 由硬件置“1” ; 在转向中断服务程序后, 用软件请“0” 。
串行中断请求由RI和TI的逻辑或得到。
2.1串行控制寄存器(IE)内容
在这里插入图片描述
EA——中断允许总控制位
EA = 0 中断总禁止, 禁止所有中断
EA = 1 中断总允许, 总允许后中断的禁止或允许由各中断源的中断允许位进行设置
需要先打开总中断,其他中断才能使能。

EX0和EX1——外部中断允许控制位
EX0(EX1) = 0 禁止外部中断
EX0(EX1) = 1 允许外部中断

ET1 =0 禁止定时器1中断
ET1 =1 使能定时器1中断
ET0 =0 禁止定时器0中断
ET0 =1 使能定时器0中断

ES——串行中断允许控制位
ES = 0 禁止串行中断
ES = 1 允许串行中断

3.中断优先级控制寄存器(IP)内容
在这里插入图片描述
PX0——外部中断0优先级设定位;
PT0——定时中断0优先级设定位;
PX1——外部中断1优先级设定位;
PT1——定时中断1优先级设定位;
PS——串行中断优先级设定位。
如果同级的多个中断同时出现, CPU的查询次序为:
外部中断0 ->定时器中断0-> 外部中断1-> 定时器中断1-> 串行中断

注:当设置为默认中断优先级时:
1.当几个中断同时发生时, 则先处理中断
优先级高
的中断程序, 在处理任意中断期间发生中断, 都不会响应。
2. 当人为配置了中断优先级,同时发生中断, 优先级高的先响应, 在处理任意中断时, 发生同级别或低级的中断, 则不响应, 发生优先级更高的中断时, 则先处理高优先级中断, 处理
完毕, 再回来处理当前中断。
当设置为默认中断优先级时:假设“ 水开” 默认优先级高于“ 门铃” 优先级,当先听到“ 水开” 则先处理“ 水开” 这件事, 当先听到“ 门铃” 则先处理“ 门铃” 这件事。 只有当两件事同时发生时, 则会先去处理“ 水开” , 再处理“ 门铃” 。
人为配置了中断优先级
配置“ 水开” 为高优先级, 则当“ 水开” 事件发生时, 直接处理“ 水开” , 在处理“ 水开” 的过程中,即使“ 门铃” 响了, 也不会去理会。 当“ 门铃” 响了, 正在走向门口时, 这个时候, “ 水开” 事件又发生了, 那么从门口转向, 先去处理“ 水开” , 处理好了后, 再回头到门口, 处理“ 门铃” 事件。
程序代码如下所示:
注意:
该程序出现HC595驱动的最后一位数码管过亮的问题,主要是由于最后一位数码管时导通时间过长,解决方法是在软件上添加一位不存在的数码段,显示为空,即可,程序如下所示:实现的是秒表计时。
在shu_wei_data数组中增加0x3F这一位数码管但是硬件不存在,在段选中增加0x00消显示代码即可实现均衡显示

#include<reg52.h>

typedef unsigned char uchar;
typedef unsigned int  uint16;

code unsigned char ShU_Duan_Data[11] = {0x3f,0x06,0x5b ,0x4f ,0x66 ,0x6d ,0x7d,0x07,0x7f,0x6f,0x00};
code unsigned char ShU_Wei_Data[9] = {0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F,**0x3F**};


sbit HC595_RCK = P1^0;
sbit hc595_SCK = P1^1;
sbit HC595_DATA = P1^4;		

uchar  k;
uint16  Counter = 0;


//void Delay_1MS(unsigned int i)
//{
//   unsigned char j;
//   for(;i >0;i--)
//   {
//       for(j=0;j < 110;j++);
//   }
//}

void  Shu_Ma_Data(unsigned char Shu_Data_One,unsigned char Shu_Data_Two)
{
    unsigned char i;

	HC595_RCK = 0;

	for(i=0; i<8;i++)
	{
	    hc595_SCK = 0;
		if(0 != (Shu_Data_One & 0x80))
		{
	    	HC595_DATA = 1;    
		}
		else
		{
	   		HC595_DATA = 0;
		}

		Shu_Data_One = Shu_Data_One<<1;
		hc595_SCK = 1;   
	}

	for(i=0; i<8;i++)
	{
	    hc595_SCK = 0;
		if(0 != (Shu_Data_Two & 0x80))
		{
	    	HC595_DATA = 1;    
		}
		else
		{
	   		HC595_DATA = 0;
		}
		Shu_Data_Two = Shu_Data_Two << 1;
		hc595_SCK = 1;   
	}
    HC595_RCK = 1;  
}
void display1(unsigned int data_s)
{
	unsigned char data_u,data_t,data_h,data_th,data_hh,data_ha=0,data_hb=0,data_hv=0;
	data_u=data_s%10;
	data_t = data_s/10%10;
	data_h = data_s/100%10;
	data_th = data_s/1000%10;
	data_hh=data_s/10000%10;
//	
	Shu_Ma_Data(ShU_Duan_Data[data_u],ShU_Wei_Data[7]);	
  	Shu_Ma_Data(ShU_Duan_Data[data_t],ShU_Wei_Data[6]);	
  	Shu_Ma_Data(ShU_Duan_Data[data_h],ShU_Wei_Data[5]);	
  	Shu_Ma_Data(ShU_Duan_Data[data_th],ShU_Wei_Data[4]);
	Shu_Ma_Data(ShU_Duan_Data[data_hh],ShU_Wei_Data[3]);
	Shu_Ma_Data(ShU_Duan_Data[data_ha],ShU_Wei_Data[2]);
	Shu_Ma_Data(ShU_Duan_Data[data_hb],ShU_Wei_Data[1]);
	Shu_Ma_Data(ShU_Duan_Data[data_hv],ShU_Wei_Data[0]);
	Shu_Ma_Data(ShU_Duan_Data[10],ShU_Wei_Data[8]);					
}


void Time1_Init()
{
   TMOD &= 0X0F;
   TMOD |= 0X10;
   TH1 = 0XFC;
   TL1 = 0X66;
   TR1 = 1;	       //启动定时器1
    ET1 = 1;	
}



void main()
{
   Time1_Init();
   EA = 1;      //开总中断

   while(1);
}



void interrupt_time_1()  interrupt  3	   //向量入口为3
{
    static unsigned int sec = 0;
	TH1 = 0XFC;								//重新填入初值,
	TL1 = 0X66;
	TF1=0;								// 硬件清0可省
	Counter ++;
	if(1000 == Counter)
	{
	   Counter = 0;
	   sec ++;
	}
	 display1(sec);	   

}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

从小白到大师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值