51单片机独立按键以及矩阵按键的使用以及其原理

您所在的位置:网站首页 键盘状态指示灯不亮了 51单片机独立按键以及矩阵按键的使用以及其原理

51单片机独立按键以及矩阵按键的使用以及其原理

2024-05-27 13:28| 来源: 网络整理| 查看: 265

IO 的使用–按键

本文主要涉及8051单片机按键的使用,包括独立按键以及矩阵按键的使用以及其原理,其中代码实例包括: 1.独立按键 K1 控制 D1 指示灯亮灭 2.通过数码管显示矩阵按键 S1-S16 按下后键值 0-F

文章目录 IO 的使用--按键一、按键消抖二、独立按键独立按键 K1 控制 D1 指示灯亮灭 二、 矩阵按键通过数码管显示矩阵按键 S1-S16 按下后键值 0-F 按键是一种电子开关,使用时轻轻按开关按钮就可使开关接通,当松开手时, 开关断开。

在了解按键之前,我们需要先了解一下按键消抖

一、按键消抖

通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,电压信号 如下图所示: 在这里插入图片描述

由于机械点的弹性作用,按键开关在闭合时不会马上稳定的接通,在断开时也不会一下子断开,因而在闭合和断开的瞬间均伴随着一连串的抖动。抖动时间的长短由按键的机械特性决定的,一般为 5ms 到 10ms。

按键消抖有两种方式,一种是硬件消抖,另一种是软件消抖。为了使电路更加简单,通常采用软件消抖。

常用的软件去抖动方法: 1,先设置 IO 口为高电平(由于开发板 IO 都有上拉电阻,所以默认 IO 为高 电平)。 2,读取 IO 口电平确认是否有按键按下。 3,如有 IO 电平为低电平后,延时几个毫秒。 4,再读取该 IO 电平,如果仍然为低电平,说明按键按下。 5,执行按键控制程序。

二、独立按键

独立按键电路构成是由各个按键的一个管脚连接在一起接地,按键其他引脚分别接到单片机 IO 口。

独立按键的原理图如下: 在这里插入图片描述

从上图中可以看出,4 个独立按键的控制管脚连接到 51 单片机的 P3.0-P3.3脚上。其中 K1 连接在 P3.1 上,K2 连接在 P3.0 上,K3 连接在 P3.2 上,K4 连接在 P3.3 上。4 个按键另一端全部连接在 GND,当按键按下后,对应 IO 口即为低电平。

独立按键 K1 控制 D1 指示灯亮灭 #include "reg52.h" typedef unsigned int u16; //对系统默认数据类型进行重定义 typedef unsigned char u8; //定义独立按键控制脚 sbit KEY1=P3^1; sbit KEY2=P3^0; sbit KEY3=P3^2; sbit KEY4=P3^3; //定义 LED1 控制脚 sbit LED1=P2^0; //使用宏定义独立按键按下的键值 #define KEY1_PRESS 1 #define KEY2_PRESS 2 #define KEY3_PRESS 3 #define KEY4_PRESS 4 #define KEY_UNPRESS 0 void delay_10us(u16 ten_us) { while(ten_us--); } u8 key_scan(u8 mode) { static u8 key=1; if(mode)key=1;//连续扫描按键 if(key==1&&(KEY1==0||KEY2==0||KEY3==0||KEY4==0))//任意按键按下 { delay_10us(1000);//消抖 key=0; if(KEY1==0) return KEY1_PRESS; else if(KEY2==0) return KEY2_PRESS; else if(KEY3==0) return KEY3_PRESS; else if(KEY4==0) return KEY4_PRESS; } else if(KEY1==1&&KEY2==1&&KEY3==1&&KEY4==1) //无按键按下 { key=1; } return KEY_UNPRESS; } void main() { u8 key=0; while(1) { key=key_scan(0); if(key==KEY1_PRESS)//检测按键 K1 是否按下 LED1=!LED1;//LED1 状态翻转 } }

key_scan 函数带一个形参 mode,该参数用来设定是否连续扫描按键,如果mode 为 0,只能操作一次按键,只有当按键松开后才能触发下次的扫描,这样做的好处是可以防止按下一次出现多次触发的情况。如果 mode 为 1,函数是支持连续扫描的,即使按键未松开,在函数内部有 if(mode==1)这条判断语句,因此 key 始终是等于 1 的,所以可以连续扫描按键,当按下某个按键,会一直返回这 个按键的键值,这样做的好处是可以很方便实现连按操作.

二、 矩阵按键

无论是独立键盘还是矩阵键盘,单片机检测其是否被按下的依据都是一样的,也就是检测与该键对应的 I/O 口是否为低电平。独立键盘有一端固定为低电平,此种方式编程比较简单。 而矩阵键盘两端都与单片机 I/O 口相连,因此在检测时需编程通过单片机 I/O 口送出低电平。检测方法有多种,最常用的是行列扫描和线翻转法。

行列扫描法检测时,先送一列为低电平,其余几列全为高电平(此时我们确定了列数),然后立即轮流检测一次各行是否有低电平,若检测到某一行为低电平(这时我们又确定了行数),则我们便可确认当前被按下的键是哪一行哪一列的,用同样方法轮流送各列一次低电平,再轮流检测一次各行是否变为低电平,这样即可检测完所有的按键,当有键被按下时便可判断出按下的键是哪一个键。当然我们也可以将行线置低电平,扫描列是否有低电平。从而达到整个键盘的检测。

线翻转法,就是使所有行线为低电平时,检测所有列线是否有低电平,如果有,就记录列线值;然后再翻转,使所有列线都为低电平,检测所有行线的值,由于有按键按下,行线的值也会有变化,记录行线的值。从而就可以检测到全部按键。

在这里插入图片描述

4*4 矩阵按键引出的 8 根控制线直接连接到 51 单片机的P1 口上。电路中的 P17 连接矩阵键盘的第 1 行,P13 连接矩阵键盘第 1 列

通过数码管显示矩阵按键 S1-S16 按下后键值 0-F #include "reg52.h" typedef unsigned int u16; //对系统默认数据类型进行重定义 typedef unsigned char u8; #define KEY_MATRIX_PORT P1 //使用宏定义矩阵按键控制口 #define SMG_A_DP_PORT P0 //使用宏定义数码管段码口 //共阴极数码管显示 0~F 的段码数据 u8 gsmg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; void delay_10us(u16 ten_us) { while(ten_us--); } //行列式扫描方式 u8 key_matrix_ranks_scan(void) { u8 key_value=0; KEY_MATRIX_PORT=0xf7;//给第一列赋值 0,其余全为 1 if(KEY_MATRIX_PORT!=0xf7)//判断第一列按键是否按下 { delay_10us(1000);//消抖 switch(KEY_MATRIX_PORT)//保存第一列按键按下后的键值 { case 0x77: key_value=1;break; case 0xb7: key_value=5;break; case 0xd7: key_value=9;break; case 0xe7: key_value=13;break; } } while(KEY_MATRIX_PORT!=0xf7);//等待按键松开 KEY_MATRIX_PORT=0xfb;//给第二列赋值 0,其余全为if(KEY_MATRIX_PORT!=0xfb)//判断第二列按键是否按下 { delay_10us(1000);//消抖 switch(KEY_MATRIX_PORT)//保存第二列按键按下后的键值 { case 0x7b: key_value=2;break; case 0xbb: key_value=6;break; case 0xdb: key_value=10;break; case 0xeb: key_value=14;break; } } while(KEY_MATRIX_PORT!=0xfb);//等待按键松开 KEY_MATRIX_PORT=0xfd;//给第三列赋值 0,其余全为 1 if(KEY_MATRIX_PORT!=0xfd)//判断第三列按键是否按下 { delay_10us(1000);//消抖 switch(KEY_MATRIX_PORT)//保存第三列按键按下后的键值 { case 0x7d: key_value=3;break; case 0xbd: key_value=7;break; case 0xdd: key_value=11;break; case 0xed: key_value=15;break; } } while(KEY_MATRIX_PORT!=0xfd);//等待按键松开 KEY_MATRIX_PORT=0xfe;//给第四列赋值 0,其余全为 1 if(KEY_MATRIX_PORT!=0xfe)//判断第四列按键是否按下 { delay_10us(1000);//消抖 switch(KEY_MATRIX_PORT)//保存第四列按键按下后的键值 { case 0x7e: key_value=4;break; case 0xbe: key_value=8;break; case 0xde: key_value=12;break; case 0xee: key_value=16;break; } } while(KEY_MATRIX_PORT!=0xfe);//等待按键松开 return key_value; } //线翻转式扫描方式 u8 key_matrix_flip_scan(void) { static u8 key_value=0; KEY_MATRIX_PORT=0x0f;//给所有行赋值 0,列全为 1 if(KEY_MATRIX_PORT!=0x0f)//判断按键是否按下 { delay_10us(1000);//消抖 if(KEY_MATRIX_PORT!=0x0f) { //测试列 KEY_MATRIX_PORT=0x0f; switch(KEY_MATRIX_PORT)//保存行为 0,按键按下后的列值 { case 0x07: key_value=1;break; case 0x0b: key_value=2;break; case 0x0d: key_value=3;break; case 0x0e: key_value=4;break; } //测试行 KEY_MATRIX_PORT=0xf0; switch(KEY_MATRIX_PORT)//保存列为 0,按键按下后的键值 { case 0x70: key_value=key_value;break; case 0xb0: key_value=key_value+4;break; case 0xd0: key_value=key_value+8;break; case 0xe0: key_value=key_value+12;break; } while(KEY_MATRIX_PORT!=0xf0);//等待按键松开 } } else key_value=0; return key_value; } void main() { u8 key=0; while(1) { key=key_matrix_ranks_scan(); if(key!=0) SMG_A_DP_PORT=gsmg_code[key-1];//得到的按键值减 1 换算成数组下标 对应 0-F 段码 } }

上述学习资料都是来自普中科技😀



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3