当前位置:   article > 正文

矩阵键盘——基于stm32单片机_stm32矩阵键盘

stm32矩阵键盘

目录

基本原理

矩阵按键原理图

初始化

识别键码

GPIO_Write()函数和GPIO_ReadInputData()函数

读取列数

读取行数

返回键码


基本原理

了解矩阵键盘之前,应当要对基本按键的检测要有认识:如下图

图源up主  江协科技

 右边按键一端接低电平,一段接PB1。设置PB1为上拉输入,相当于按键两端分别置0和1(低电平和高电平)。按键未按下时,对PB1检测,PB1电平就为高(1)。那么当按键按下时,PB1与地导通,此时对PB1检测,PB1电平就为低(0)。

所以,通过检测原来高电平的引脚是否变低则可以判断按键是否按下。

矩阵按键原理图

 

初始化

这里我初始化是将高四位引脚设置为上拉输入,低四位引脚设置为推挽输出。

  1. #include "stm32f10x.h" // Device header
  2. #include "Delay.h"
  3. uint16_t keyz=0;
  4. void Key_Init(void)
  5. {
  6. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE );
  7. GPIO_InitTypeDef GPIO_KEY0_3;
  8. GPIO_KEY0_3.GPIO_Mode=GPIO_Mode_Out_PP;
  9. GPIO_KEY0_3.GPIO_Pin=GPIO_Pin_0 |GPIO_Pin_1 |GPIO_Pin_2 |GPIO_Pin_3 ;
  10. GPIO_KEY0_3.GPIO_Speed=GPIO_Speed_50MHz;
  11. GPIO_Init (GPIOA ,&GPIO_KEY0_3);
  12. GPIO_InitTypeDef GPIO_KEY1_4;
  13. GPIO_KEY1_4.GPIO_Mode=GPIO_Mode_IPU;
  14. GPIO_KEY1_4.GPIO_Pin=GPIO_Pin_4 |GPIO_Pin_5 |GPIO_Pin_6 |GPIO_Pin_7 ;
  15. GPIO_KEY1_4.GPIO_Speed=GPIO_Speed_50MHz;
  16. GPIO_Init (GPIOA ,&GPIO_KEY1_4);
  17. }

识别键码

GPIO_Write()函数和GPIO_ReadInputData()函数

GPIO_Write()函数可以对多个引脚同时进行配置,此函数有两个参数,第一个为引脚分组,第二个为一个十六进制数。这个十六进制数就是按其对应的二进制对引脚电平进行配置。如GPIO_Write(GPIOA ,0xF0);为1111 0000,即对PA0-PA3引脚置低电平,对PA4-PA8引脚置高电平。

十六进制转换表

 GPIO_ReadInputData()函数输出的是十六进制表示的引脚状态。

读取列数

当按键未按下时使用 GPIO_ReadInputData()函数读取按键,读取值为0xF0,即1111 0000;

高四位代表 列 对应引脚状态,低四位代表 行 对应引脚状态。

如果当按键按下时使用 GPIO_ReadInputData()函数读取按键,此时按下按键 列数 对应的引脚为0,再进行Lie=~GPIO_ReadInputData (GPIOA ); Lie=Lie&0xF0;    则得到列数。

读取行数

将行对应引脚电位逐次拉高,当轮到 按下按键对应行数时 ,由于按键两端都为1,则(GPIO_ReadInputData (GPIOA )&0xF0)!=0xF0;否则(GPIO_ReadInputData (GPIOA )&0xF0)==0xF0;由此可得行数。

  1. u16 Key_Scan(void)
  2. {
  3. uint8_t Hang,Lie,k,i;
  4. GPIO_Write(GPIOA ,0xF0); //将A0-A3口和A4-7口电位分别置成低电位和高电位
  5. //0xF0 转换成二进制为 1111 0000;
  6. if((GPIO_ReadInputData(GPIOA)&0xF0)!=0xF0) //判断按键是否按下
  7. {
  8. Delay_ms (40); //按键消抖
  9. if((GPIO_ReadInputData(GPIOA)&0xF0)!=0xF0) //再次判断
  10. {
  11. Hang=GPIO_ReadInputData (GPIOA ); //给Hang赋上初值,读取按键按下后得到的代码,假设为1011 0000 (0xB0)
  12. Lie=~Hang; //对Hang按位取反,即0100 1111
  13. Lie=Lie&0xF0; //0100 1111 &1111 0000得到0100 0000 即为列数
  14. //得到列数
  15. for(i=0;i<4 && ((Hang&0xF0)!=0xF0);i++) //逐次将行拉高,判断列数中原来变低的位是否变高
  16. { //读到之前检测到为低的列变高则推出
  17. GPIO_Write (GPIOA ,0xF0|(0x01<<i)); //进行行扫描,逐次将行口线拉高,列保持为按下的状态
  18. Hang=GPIO_ReadInputData (GPIOA ); //读取IO口,用以判断是否扫描到行坐标
  19. }
  20. Hang&=0x0F;
  21. //得到行值
  22. k=Hang|Lie; //行列相加则得到键码
  23. GPIO_Write (GPIOA ,0xF0); //A0-A3拉低,A4-A7拉高,此处用来将行状态初始化为未按下时的状态
  24. while((GPIO_ReadInputData(GPIOA)&0xF0)!=0xF0)//判释放
  25. {
  26. Delay_ms (40); //后延消抖。时间需要长一点
  27. }
  28. return k;
  29. //返回键码
  30. }
  31. }
  32. return (0); //无键按下,返回0
  33. }

返回键码

  1. u16 Key_Get(void)
  2. {
  3. keyz =Key_Scan ();
  4. uint16_t Keyx=0;
  5. if (keyz!=0)
  6. {
  7. switch(keyz)
  8. {
  9. case 0x81:Keyx=1;break;
  10. case 0x82:Keyx=2;break;
  11. case 0x84:Keyx=3;break;
  12. case 0x88:Keyx=4;break;
  13. case 0x41:Keyx=5;break;
  14. case 0x42:Keyx=6;break;
  15. case 0x44:Keyx=7;break;
  16. case 0x48:Keyx=8;break;
  17. case 0x21:Keyx=9;break;
  18. case 0x22:Keyx=10;break;
  19. case 0x24:Keyx=11;break;
  20. case 0x28:Keyx=12;break;
  21. case 0x11:Keyx=13;break;
  22. case 0x12:Keyx=14;break;
  23. case 0x14:Keyx=15;break;
  24. case 0x18:Keyx=16;break;
  25. default:break;
  26. }
  27. }
  28. return Keyx;
  29. }

实例:单数遇到双数按键分别亮两个不同的灯mat key · 灵槐梦/stm32 - 码云 - 开源中国 (gitee.com)

更新,对于行判断的解释: 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/302170
推荐阅读
相关标签
  

闽ICP备14008679号