51单片机基础03 矩阵按键读取与外部中断读取

目录

一、独立按键读取

二、外部中断读取

1、轮询问题

2、解决方法

3、相关设置

4、外部中断参数

三、矩阵按键读取

1、问题

2、解决方法


一、独立按键读取

在考虑电路外围复杂度的时候,可以最简单的按键接IO,下拉到GND,这样默认IO上电后输出高电平,被按下为低电平即可实现检测。

cpp 复制代码
sbit Key1=P1^0;
sbit Key2=P1^1;
sbit Key3=P1^2;
sbit Key4=P1^3;
//延时
void DelayMS(uint ms)
{
	uchar t;
	while(ms--) for(t=0;t<120;t++);
}
if(Key1==0)
{
	DelayMS(5);
	if(Key1==0)
	{
		P0=0XF0;
	}
	while(!Key1);
    P0=0XFF;
}

该代码即实现了,判断P1^0的IO是否被按下,如果按下进行一个时延消抖,并再进行一次判断,如果确实按下,则执行P0控制的相应功能,并卡死在等待按键弹起后恢复P0的控制。

二、外部中断读取

1、轮询问题

如果程序很多的情况下,在执行别的代码时按键按下无响应;

按键按下后不弹起,则程序无法执行别的代码。

2、解决方法

将按键介入到INT0或INT1的IO,其作为外部中断,当输入0则自动进入中断服务程序。

3、相关设置

cpp 复制代码
IT0=1;//当IT0=0时,为低电平触发方式;为1时,则为低电平下降沿触发
EX0=1;//允许外部中断0进行中断
EA=1;//开启总中断


//外部按键被按下后,IE0被系统置为1并自动进入void INTO_ISR(void) interrupt 0

void INTO_ISR(void) interrupt 0
{
    EX0=0;    //关闭中断允许,以防还没执行完本次中断服务程序后,再次进入
    delay_ms(1);
    if(P3_2==1)
    {
        //执行相应的功能
    }
    while(P3_2==0);
    IE0=0;//刷新为0,便于下次再进入中断服务
    EX0=1;//打开中断允许
}

至于这些外部中断都有什么命名,请看如下表:

4、外部中断参数

|------|-------|-----------|--------------|
| 中断编号 | 中断名 | 中断源 | 实现 |
| 0 | 外部中断0 | IE0(P3.2) | 1:请求中断 0:未中断 |
| 2 | 外部中断1 | IE1(P3.3) | 1:请求中断 0:未中断 |

中断编号同样决定了中断优先级,当同时发生多个中断的时候,外部中断0(IE0)→定时/计数器0(TF0)→外部中断1(IE1)→定时/计数器1(TF1)→串行口(R1或T1)。

|-------|------------|------------|
| 中断寄存器 | 功能 | 实现 |
| EX0 | 外部中断0中断允许位 | 1:允许 0:不允许 |
| EX1 | 外部中断1中断允许位 | 1:允许 0:不允许 |

中断寄存器决定了是否允许中断,应该在程序开始后,先让EX0=1,并在进入中断后置0,在中断结束时再置1。

|---------|-----------|-----------------|
| 中断触发控制位 | 功能 | 实现 |
| IT0 | 外部中断0触发方式 | 1:低电平触发 0:下降沿触发 |
| IT1 | 外部中断1触发方式 | 1:低电平触发 0:下降沿触发 |

中断触发控制方式。

三、矩阵按键读取

1、问题

可以直到外部中断能够实现很好的按键读取,然而外部中断控制仅有2个;且很多时候并不需要很高效的按键读取,但是按键数量非常多,总不能每一个按键都分配一个IO,那数量太多了。

2、解决方法

可以看到按键的左右侧分别和行、列共享。

cpp 复制代码
P1=0xFE;                  //将第一行置零,以扫描K1-K4是否被按下
if(LIE1==0) KEYbuf=0;     //如果K1键按下,KEYbuf赋值写0
		                            //若K1按下,则LIE1与P1.7导通,则LIE1=0
else if(LIE2==0) KEYbuf=1; //如果K2键按下,KEYbuf赋值写1
		                             //若K2按下,则LIE2与P1.7导通,则LIE2=0
else if(LIE3==0) KEYbuf=2; //如果K3键按下,KEYbuf赋值写2
		                             //若K3按下,则LIE3与P1.7导通,则LIE3=0
else if(LIE4==0) KEYbuf=3; //如果K4键按下,KEYbuf赋值写3
		                             //若K4按下,则LIE4与P1.7导通,则LIE4=0

P1=0xFD;                  //将第二行置零,以扫描K5-K8是否被按下
if(LIE1==0) KEYbuf=4;     //如果K5键按下,KEYbuf赋值写4
else if(LIE2==0) KEYbuf=5; //如果K6键按下,KEYbuf赋值写5
else if(LIE3==0) KEYbuf=6; //如果K7键按下,KEYbuf赋值写6
else if(LIE4==0) KEYbuf=7; //如果K8键按下,KEYbuf赋值写7

P1=0xFB;                  //将第三行置零,以扫描K9-K12是否被按下
if(LIE1==0) KEYbuf=8;     //如果K9键按下,KEYbuf赋值写8
else if(LIE2==0) KEYbuf=9; //如果K10键按下,KEYbuf赋值写9
else if(LIE3==0) KEYbuf=10;//如果K11键按下,KEYbuf赋值写10
else if(LIE4==0) KEYbuf=11;//如果K12键按下,KEYbuf赋值写11

P1=0xF7;                  //将第四行置零,以扫描K13-K16是否被按下
if(LIE1==0) KEYbuf=12;    //如果K13键按下,KEYbuf赋值写12
else if(LIE2==0) KEYbuf=13;//如果K14键按下,KEYbuf赋值写13
else if(LIE3==0) KEYbuf=14;//如果K15键按下,KEYbuf赋值写14
else if(LIE4==0) KEYbuf=15;//如果K16键按下,KEYbuf赋值写15

P1=0XFE,其相当于11111110,所以P1.0为0,故K1、K2、K3、K4一侧为GND,那么此时如果任意一个按键按下,都会导致有一个IO被置位GND。

例如K1按下,P1.4为GND;K2按下,P1.5为GND;K3按下,P1.6为GND;K4按下,P1.7为GND;从而实现按键的读取。

相关推荐
ThreeYear_s1 小时前
基于FPGA 的4位密码锁 矩阵键盘 数码管显示 报警仿真
fpga开发·矩阵·计算机外设
枯无穷肉4 小时前
stm32制作CAN适配器4--WinUsb的使用
stm32·单片机·嵌入式硬件
不过四级不改名6774 小时前
基于HAL库的stm32的can收发实验
stm32·单片机·嵌入式硬件
嵌入式大圣4 小时前
单片机UDP数据透传
单片机·嵌入式硬件·udp
云山工作室5 小时前
基于单片机的视力保护及身姿矫正器设计(论文+源码)
stm32·单片机·嵌入式硬件·毕业设计·毕设
嵌入式-老费5 小时前
基于海思soc的智能产品开发(mcu读保护的设置)
单片机·嵌入式硬件
不知火猪5 小时前
最新雷蛇鼠标键盘驱动Razer Synapse 4(雷云) 下载与安装
计算机外设·驱动·雷云·雷蛇驱动
qq_397562317 小时前
MPU6050 , 设置内部低通滤波器,对于输出数据的影响。(简单实验)
单片机
liyinuo20177 小时前
嵌入式(单片机方向)面试题总结
嵌入式硬件·设计模式·面试·设计规范
艺术家天选7 小时前
STM32点亮LED灯
stm32·单片机·嵌入式硬件