当前位置: 首页 > article >正文

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

目录

一、独立按键读取

二、外部中断读取

1、轮询问题

2、解决方法

3、相关设置

4、外部中断参数

三、矩阵按键读取

1、问题

2、解决方法


一、独立按键读取

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

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、相关设置

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外部中断0IE0(P3.2)

1:请求中断

0:未中断

2外部中断1IE1(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、解决方法

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

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


http://www.kler.cn/a/394513.html

相关文章:

  • 三周精通FastAPI:37 包含 WSGI - Flask,Django,Pyramid 以及其它
  • [JAVAEE] 面试题(四) - 多线程下使用ArrayList涉及到的线程安全问题及解决
  • 项目风险管理的3大要素
  • 微信小程序的主体文件和页面文件介绍
  • 2024年11月12日Github流行趋势
  • 密码学的基本原理
  • windows C#-默认约定(上)
  • 泰矽微重磅发布超高集成度车规触控芯片TCAE10
  • 【机器学习基础】西瓜书阅读笔记task01
  • 游戏设计:推箱子【easyx图形界面/c语言】
  • AcWing 1097 池塘计数 flood fill bfs搜索
  • JFlash添加自定义MCU型号
  • 【汇编语言】包含多个段的程序(二)—— 将数据、代码、栈放入不同的段
  • 图像融合self
  • vscode远程连接+免密登录
  • 【Linux学习】【Ubuntu入门】1-3 ubuntu连接USB设备
  • IntelliJ+SpringBoot项目实战(七)--在SpringBoot中整合Redis
  • 职场中天天工作太累太无趣
  • 前端呈现效果:鱼眼相机城市环境图像分割
  • SQL语句执行的基本架构——数据库
  • Dify + Xinference:一站式本地 LLM 私有化部署和应用开发
  • 【C#设计模式(10)——装饰器模式(Decorator Pattern)】
  • 3D意识(3D Awareness)浅析
  • 《InsCode AI IDE:编程新时代的引领者》
  • 【Java】【Spring框架】【复习】1
  • RFC 2018 即《TCP Selective Acknowledgement Options》