C51学习笔记 5.中断系统

C51 5.中断系统

前言

补上定时器篇的中断系统。

C51内部的中断结构较为复杂,看得比较晕的话结合上篇定时器内的简易中断图对比来看,他们的大体结构是对应的。

祝愉快

1.中断

在这里插入图片描述

如果没有中断,我们的很多操作就只能在main里面完成。

想想看如果我们按下按键后,因为Key函数内因为按键消抖需求写下的Delay函数会带来什么样的后果。

Delay把整个main停下,那么如果我们这时候还要运行一个数码管每过一秒加1的函数,这个数码管函数就会被按键消抖的Delay给停下。

所以我们需要把各个函数给区分开来,放到不同的执行周期里面。(代码会展示)

2.中断结构

此为C51内部中断结构

在这里插入图片描述

中断源

我们从左往右看,左边为输入中断系统的中断源。

在这里插入图片描述

每一个中断源对应一个中断号

在这里插入图片描述

IE

在这里插入图片描述

  • 中断的开关
    • EA为公共中断开关
    • ET为定时器/计数器中断开关
    • ES为UART中断开关
    • EX为外部中断开关

XICON

在这里插入图片描述

xicon中有中断允许和中断优先级的额外内容。

因为C51相较简单的中断系统额外增加了多个中断源和中断优先级,所以需要额外的寄存器来配置增加的功能。

IP

在这里插入图片描述

为了达到4优先级,它使用了三个寄存器来保存配置信息。

我们不看优先级选择寄存器的标识哪个中断源的标识符,(PX3H为INT3的一个标识符,PX3为宁外一个,这里我们把它看成PH和P)

由PH和P组成的二位序列:

  • 0 0 最低优先级
  • 0 1 较低优先级
  • 1 0 较高优先级
  • 1 1 最高优先级

这样就做到了4优先级,如果想设计成8优先级那就用3位二进制序列就好了,当然这要分配更多的寄存器资源,以及我们一般也不需要这么细化的优先级秩序。

基本规则

在这里插入图片描述

3.C代码

在函数的末尾加上interrupt 中断号,一个中断函数就设置好了。

//定时器中断函数模板
void Timer0_Routine() interrupt 1
{
	static unsigned int T0Count;
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	T0Count++;
	if(T0Count>=1000)
	{
		T0Count=0;
		
	}
}

定时器扫描按键和数码管

  • 我们需要对key函数和Nixie函数进行改造。
  • 改造的基本原理是
    • 定时器扫描按一个周期取一个时间点调用函数
    • 那么Key函数里面的消抖Delay就不需要了,因为我们是离散的采触发点,没准就跳过了抖动的时间端
    • 其实就算取到了抖动的时间点也没有问题,抖动为1那就是判断按下了,也符合我们的要求,抖动为0那取下一个点就好了
    • 改造后的Loop函数记得要符合循环的要求
void Timer0_Routine() interrupt 1
{
	static unsigned int T0Count1,T0Count2,T0Count3;
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	T0Count1++;
	if(T0Count1>=20)
	{
		T0Count1=0;
		Key_Loop();	//20ms调用一次按键驱动函数
	}
	T0Count2++;
	if(T0Count2>=2)
	{
		T0Count2=0;
		Nixie_Loop();//2ms调用一次数码管驱动函数
	}
	T0Count3++;
	if(T0Count3>=10)
	{
		T0Count3=0;
		Sec_Loop();	//10ms调用一次数秒表驱动函数
	}
}

Key_Loop函数

#include <REGX52.H>
#include "Delay.h"

unsigned char Key_KeyNumber;

/**
  * @brief  获取按键键码
  * @param  无
  * @retval 按下按键的键码,范围:0,1~4,0表示无按键按下
  */
unsigned char Key(void)
{
	unsigned char Temp=0;
	Temp=Key_KeyNumber;	//Key_KeyNumber的数值快速变化,为了保存稳定,先存在中间变量里,传也是传中间变量
	Key_KeyNumber=0;	//注意标志位要写清零,这端代码的清零写在这里,为了保障Temp能接收到数值
	return Temp;
}

/**
  * @brief  获取当前按键的状态,无消抖及松手检测
  * @param  无
  * @retval 按下按键的键码,范围:0,1~4,0表示无按键按下
  */
unsigned char Key_GetState()
{
	unsigned char KeyNumber=0;
	
	if(P3_1==0){KeyNumber=1;}
	if(P3_0==0){KeyNumber=2;}
	if(P3_2==0){KeyNumber=3;}
	if(P3_3==0){KeyNumber=4;}
	
	return KeyNumber;
}

/**
  * @brief  按键驱动函数,在中断中调用
  * @param  无
  * @retval 无
  */
void Key_Loop(void)
{
	static unsigned char NowState,LastState;
	LastState=NowState;				//按键状态更新
	NowState=Key_GetState();		//获取当前按键状态
	//如果上个时间点按键按下,这个时间点未按下,则是松手瞬间,以此避免消抖和松手检测
	if(LastState==1 && NowState==0) //我们调换LastState和NowState的判定数值,可以达到按下就响应
	{
		Key_KeyNumber=1;
	}
	if(LastState==2 && NowState==0)
	{
		Key_KeyNumber=2;
	}
	if(LastState==3 && NowState==0)
	{
		Key_KeyNumber=3;
	}
	if(LastState==4 && NowState==0)
	{
		Key_KeyNumber=4;
	}
}

总结

中断的资源和单片机的型号是有关的,它到底有几个中断源,几个优先级,几个寄存器,具体查看它的手册,本篇只是带着看一下C51的中断资源。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值