51单片机基础03 矩阵按键读取与外部中断读取
目录
一、独立按键读取
在考虑电路外围复杂度的时候,可以最简单的按键接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 | 外部中断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、解决方法
可以看到按键的左右侧分别和行、列共享。
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;从而实现按键的读取。
原文地址:https://blog.csdn.net/qq_39376872/article/details/143787792
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!