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;从而实现按键的读取。

相关推荐
沧海一笑-dj1 分钟前
【51单片机】51单片机学习笔记-课程简介
笔记·学习·51单片机·江科大·江科大学习笔记·江科大单片机·江科大51单片机
TESmart碲视1 小时前
HKS201-M24 大师版 8K60Hz USB 3.0 适用于 2 台 PC 1台显示器 无缝切换 KVM 切换器
单片机·嵌入式硬件·物联网·游戏·计算机外设·电脑·智能硬件
景行产品分享1 小时前
2025年游戏鼠标推荐,游戏鼠标推荐,打CSGO(罗技、雷蛇、卓威、ROG、漫步者、赛睿、达尔优)
计算机外设
jubobolv3691 小时前
[深度学习环境踩坑记录]ubuntu22.04安装RTX3060驱动,黑屏、桌面只有壁纸和鼠标,一顿折腾
计算机外设·持续部署
small_wh1te_coder2 小时前
硬件嵌入式学习路线大总结(一):C语言与linux。内功心法——从入门到精通,彻底打通你的任督二脉!
linux·c语言·汇编·嵌入式硬件·算法·c
花落已飘2 小时前
STM32中实现shell控制台(shell窗口输入实现)
stm32·单片机·嵌入式硬件
牵牛老人4 小时前
Qt处理USB摄像头开发说明与QtMultimedia与V4L2融合应用
stm32·单片机·qt
宇钶宇夕6 小时前
针对工业触摸屏维修的系统指南和资源获取途径
单片机·嵌入式硬件·自动化
和风化雨6 小时前
stm32的三种开发方式
stm32·单片机·嵌入式硬件
kanhao1007 小时前
三态逻辑详解:单片机GPIO、计算机总线系统举例
单片机·嵌入式硬件