凌乱的DSP笔记(5)-按键
1. 按键介绍
按键是一种电子开关,使用时轻轻按开关按钮就可使开关接通,当松开手时,开关断开。
相距较长的脚始终导通,相距较短的脚初始不导通,在按键按下时导通。
按键抖动:
硬件消抖是通过采用外加零件来消除干扰抖动杂脉冲波,通常采用电容滤波、单稳延时电路等等。
软件消抖是通过采用软件程序的方法来达到消除干扰抖动杂脉冲波,最常见的是软件采用延时(5~10ms)再次检测的方法来消抖。
2. 矩阵键盘介绍
矩阵键盘检测方法有多种,最常用的是行列扫描和线翻转法。
行列扫描法检测时, 先送一列为低电平,其余几列全为高电平(此时我们确定了列数),然后立即轮流检测一次各行是否有低电平, 若检测到某一行为低电平(这时我们又确定了行数),则我们便可确认当前被按下的键是哪一行哪一列的, 用同样方法轮流送各列一次低电平,再轮流检测一次各行是否变为低电平, 这样即可检测完所有的按键,当有键被按下时便可判断出按下的键是哪一个键。 当然我们也可以将行线置低电平, 扫描列是否有低电平。 从而达到整个键盘的检测。
线翻转法,就是使所有行线为低电平时,检测所有列线是否有低电平,如果有,就记录列线值;然后再翻转, 使所有列线都为低电平, 检测所有行线的值, 由于有按键按下,行线的值也会有变化, 记录行线的值。 从而就可以检测到全部按键。
3. 硬件设计
4. 软件设计
4.1 key
/* * key.c * * Created on: 2020-4-7 * Author: Administrator */ #include "key.h" void KEY_Init(void) { EALLOW; SysCtrlRegs.PCLKCR3.bit.GPIOINENCLK = 1;// 开启GPIO时钟 //KEY端口配置 //行为输入方向 GpioCtrlRegs.GPAMUX1.bit.GPIO12=0; GpioCtrlRegs.GPADIR.bit.GPIO12=0; GpioCtrlRegs.GPAPUD.bit.GPIO12=0; GpioCtrlRegs.GPAMUX1.bit.GPIO13=0; GpioCtrlRegs.GPADIR.bit.GPIO13=0; GpioCtrlRegs.GPAPUD.bit.GPIO13=0; GpioCtrlRegs.GPAMUX1.bit.GPIO14=0; GpioCtrlRegs.GPADIR.bit.GPIO14=0; GpioCtrlRegs.GPAPUD.bit.GPIO14=0; //列为输出方向 GpioCtrlRegs.GPBMUX2.bit.GPIO48=0; GpioCtrlRegs.GPBDIR.bit.GPIO48=1; GpioCtrlRegs.GPBPUD.bit.GPIO48=0; GpioCtrlRegs.GPBMUX2.bit.GPIO49=0; GpioCtrlRegs.GPBDIR.bit.GPIO49=1; GpioCtrlRegs.GPBPUD.bit.GPIO49=0; GpioCtrlRegs.GPBMUX2.bit.GPIO50=0; GpioCtrlRegs.GPBDIR.bit.GPIO50=1; GpioCtrlRegs.GPBPUD.bit.GPIO50=0; EDIS; GpioDataRegs.GPBSET.bit.GPIO48=1; GpioDataRegs.GPBSET.bit.GPIO49=1; GpioDataRegs.GPBSET.bit.GPIO50=1; } char KEY_Scan(char mode) { static char keyl1=1; static char keyl2=1; static char keyl3=1; //第1列扫描 KEY_L1_SetL; KEY_L2_SetH; KEY_L3_SetH; if(keyl1==1&&(KEY_H1==0||KEY_H2==0||KEY_H3==0)) { DELAY_US(10000);//延时10ms,软件消抖 keyl1=0; if(KEY_H1==0) { return KEY1_PRESS; } else if(KEY_H2==0) { return KEY4_PRESS; } else if(KEY_H3==0) { return KEY7_PRESS; } } else if(KEY_H1==1&&KEY_H2==1&&KEY_H3==1) { keyl1=1;//标志置1,可以接收下一次按键输入 } if(mode) keyl1=1;//mode为1,可以连按,否则只能单按 //第2列扫描 KEY_L2_SetL; KEY_L1_SetH; KEY_L3_SetH; if(keyl2==1&&(KEY_H1==0||KEY_H2==0||KEY_H3==0)) { DELAY_US(10000); keyl2=0; if(KEY_H1==0) { return KEY2_PRESS; } else if(KEY_H2==0) { return KEY5_PRESS; } else if(KEY_H3==0) { return KEY8_PRESS; } } else if(KEY_H1==1&&KEY_H2==1&&KEY_H3==1) { keyl2=1; } if(mode) keyl2=1; //第3列扫描 KEY_L3_SetL; KEY_L1_SetH; KEY_L2_SetH; if(keyl3==1&&(KEY_H1==0||KEY_H2==0||KEY_H3==0)) { DELAY_US(10000); keyl3=0; if(KEY_H1==0) { return KEY3_PRESS; } else if(KEY_H2==0) { return KEY6_PRESS; } else if(KEY_H3==0) { return KEY9_PRESS; } } else if(KEY_H1==1&&KEY_H2==1&&KEY_H3==1) { keyl3=1; } if(mode) keyl3=1; return KEY_UNPRESS; }
按键采用行列扫描法,根据返回值确定被按下的按键。
/* * key.h * * Created on: 2020-4-7 * Author: Administrator */ #ifndef KEY_H_ #define KEY_H_ #include "DSP2833x_Device.h" // DSP2833x 头文件 #include "DSP2833x_Examples.h" // DSP2833x 例子相关头文件 #define KEY_L1_SetL (GpioDataRegs.GPBCLEAR.bit.GPIO48=1) #define KEY_L2_SetL (GpioDataRegs.GPBCLEAR.bit.GPIO49=1) #define KEY_L3_SetL (GpioDataRegs.GPBCLEAR.bit.GPIO50=1) #define KEY_L1_SetH (GpioDataRegs.GPBSET.bit.GPIO48=1) #define KEY_L2_SetH (GpioDataRegs.GPBSET.bit.GPIO49=1) #define KEY_L3_SetH (GpioDataRegs.GPBSET.bit.GPIO50=1) #define KEY_H1 (GpioDataRegs.GPADAT.bit.GPIO12) #define KEY_H2 (GpioDataRegs.GPADAT.bit.GPIO13) #define KEY_H3 (GpioDataRegs.GPADAT.bit.GPIO14) #define KEY1_PRESS 1 #define KEY2_PRESS 2 #define KEY3_PRESS 3 #define KEY4_PRESS 4 #define KEY5_PRESS 5 #define KEY6_PRESS 6 #define KEY7_PRESS 7 #define KEY8_PRESS 8 #define KEY9_PRESS 9 #define KEY_UNPRESS 0 void KEY_Init(void); char KEY_Scan(char mode); #endif /* KEY_H_ */
4.2 main.c
通过1~6号按键控制LED。
/* * main.c * * Created on: 2020年4月7日 * Author: lenovo */ #include "DSP2833x_Device.h" // DSP2833x Headerfile Include File #include "DSP2833x_Examples.h" // DSP2833x Examples Include File #include "leds.h" #include "key.h" /******************************************************************************* * 函 数 名 : main * 函数功能 : 主函数 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void main() { int i=0; char key=0; InitSysCtrl(); LED_Init(); KEY_Init(); while(1) { key=KEY_Scan(0); switch(key) { case KEY1_PRESS: LED2_TOGGLE;break; case KEY2_PRESS: LED3_TOGGLE;break; case KEY3_PRESS: LED4_TOGGLE;break; case KEY4_PRESS: LED5_TOGGLE;break; case KEY5_PRESS: LED6_TOGGLE;break; case KEY6_PRESS: LED7_TOGGLE;break; } i++; if(i%2000==0) { LED1_TOGGLE; } DELAY_US(100); } }
5. 效果