打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
stm32F103状态机矩阵键盘

矩阵键盘程序,作为麦知club小车项目的一部分,从IAR状态机应用修改而来。

IAR7.4+STM32CUBEMX调试通过。

键盘行4,列3,每条线都有10K上拉电阻。改到4×4矩阵也很容易。

行线设置为 输入,针脚为浮空; 列线设置为开漏输出。


不支持长按和组合键,主要是我不会改。

在OS中使用20ms任务周期调用。


以下贴出代码。

keypad.h

  1. /* 
  2. * Name: keypad.h 
  3. */  
  4. #ifndef KEYPAD_H  
  5. #define KEYPAD_H  
  6.   
  7. #include "stm32f1xx_hal.h"  
  8. #include "pinname.h"  
  9.   
  10. #define PORT_KEY GPIOD  
  11. #define COLS (GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6)  
  12.   
  13. // 读pin  
  14. //#define In(GPIO_Pin) (PORT_KEY->IDR & GPIO_Pin)  
  15. #define In(GPIO_Pin) HAL_GPIO_ReadPin(PORT_KEY, GPIO_Pin)  
  16. // 写1到Pin  
  17. //#define High(GPIO_Pin) PORT_KEY->BSRR = GPIO_Pin  
  18. #define High(GPIO_Pin) HAL_GPIO_WritePin(PORT_KEY, GPIO_Pin, GPIO_PIN_SET)  
  19. // 写0到Pin  
  20. //#define Low(GPIO_Pin) PORT_KEY->BSRR = (uint32_t)GPIO_Pin << 16   
  21. #define Low(GPIO_Pin) HAL_GPIO_WritePin(PORT_KEY, GPIO_Pin, GPIO_PIN_RESET)  
  22.   
  23. /*  
  24. *  0  1  2   3 
  25. *  4  5  6   7 
  26. *  8  9  10  11 
  27. *  12 13 14  15 
  28. */  
  29.   
  30. typedef enum {  
  31.     Key_Up = 0x02,  
  32.     Key_Left = 0x03,  
  33.     Key_Right = 0x04,  
  34.     Key_Down = 0x08,  
  35.     Key_On =  0x09,  
  36.     Key_Mode = 0x0a,  
  37.     Key_None = 0xFF  
  38. } KeyPressed;  
  39.       
  40. static const int row_count = 4;  
  41. static const int col_count = 3;  
  42.   
  43. uint16_t bus_out(void);  
  44.   
  45. void Keypad(void);  
  46. char AnyKey(void);  
  47. char SameKey(void);  
  48. char ScanKey(void);  
  49. void FindKey(void);  
  50. void ClearKey(void);  
  51. void Read(void);  
  52. /** Start the keypad interrupt routines */  
  53. void Start(void);  
  54. /** Stop the keypad interrupt routines */  
  55. void Stop(void);  
  56. void Cols_out(uint16_t v);  
  57. void Scan_Keyboard(void);  
  58. KeyPressed getKey(void);  
  59. #endif // KEYPAD_H  

keypad.c

  1. /* 
  2. * Name: keypad.cpp 
  3. */  
  4.   
  5. #include "keypad.h"  
  6.   
  7. // State:  
  8. char KeyState;  
  9. // Bit pattern after each scan:  
  10. char KeyCode;  
  11. // Output value from the virtual 74HC922:  
  12. KeyPressed KeyValue;  
  13. // KeyDown is set if key is down:  
  14. char KeyDown;  
  15. // KeyNew is set every time a new key is down:  
  16. char KeyNew;  
  17. // 映射表  
  18. char KeyTable[12][2];    
  19. // Pin of Row  
  20. uint16_t _rows[] = {KEYx0, KEYx1, KEYx2, KEYx3};  
  21. uint16_t _cols[] = {KEYy0, KEYy1, KEYy2};  
  22.   
  23. //构造函数  
  24. void Keypad(void)  
  25. {  
  26.        
  27.    Stop();     
  28.    KeyState = 0; // 按键状态初始 0  
  29. }  
  30.   
  31.   
  32. //扫描键盘  
  33. void Scan_Keyboard(void){  
  34. switch (KeyState) {  
  35.   case 0: {  
  36.   if (AnyKey()) {      
  37.     char scankey = ScanKey();  
  38.     if (scankey != 0xff)  
  39.         KeyCode = scankey;  
  40.       
  41.     KeyState = 1;  
  42.   }  
  43.     
  44.   break;  
  45.   }  
  46.   case 1: {  
  47.   if (SameKey()) {  
  48.     FindKey();  
  49.     KeyState = 2;    
  50.   }  
  51.   else   
  52.     KeyState = 0;  
  53.     
  54.   break;  
  55.   }  
  56.   case 2: {  
  57.     if (SameKey()) {  
  58.     }  
  59.     else   
  60.       KeyState = 3;  
  61.       
  62.     break;  
  63.     }  
  64.   case 3: {  
  65.     if (SameKey()) {  
  66.       KeyState = 2;  
  67.     }  
  68.     else {  
  69.       ClearKey();  
  70.       KeyState = 0;  
  71.     }  
  72.       
  73.     break;  
  74.    }  
  75.   }  
  76. // func end  
  77. }  
  78.   
  79. // 有键按下  
  80. char AnyKey(void) {  
  81.  //Start();  //拉低  
  82.    
  83.  int r = -1;  
  84.  for (r = 0; r < row_count; r++) {  
  85.      if (In(_rows[r]) == 0)  // In macro  
  86.          break;    
  87.  }  
  88.    
  89.  //Stop();  //恢复  
  90.    
  91.  if (!(0 <= r && r < row_count))  
  92.     return 0;  
  93.  else  
  94.     return 1;  
  95. }  
  96.   
  97. // 键按下, 键值相同  
  98. char SameKey(void) {  
  99.     
  100.   // char KeyCode_new = KeyCode;  
  101.   char KeyCode_new = ScanKey();  
  102.   if (KeyCode == KeyCode_new)    
  103.     return 1;  
  104.   else  
  105.     return 0;  
  106. }  
  107.   
  108. // 扫描键  
  109. char ScanKey(void) {  
  110.   
  111.  /* 行扫描 */  
  112.     int r = -1;  
  113.     for (r = 0; r < row_count; r++) {  
  114.         if (In(_rows[r]) == 0)  // In macro  
  115.             break;  
  116.     }  
  117.   
  118.     /* 若没有找到有效行,返回 */  
  119.     if (!(0 <= r && r < row_count)) {  
  120.       return 0xff;  
  121.           
  122.     }  
  123.   
  124.     /* 列扫描,找出行上哪个被拉低 */  
  125.     int c = -1;  
  126.     for (c = 0; c < col_count; c++) {  
  127.         // 轮流输出列线  
  128.         Cols_out(~(1 << c));  
  129.           
  130.         if (In(_rows[r]) == 0)  // In macro  
  131.             break;  
  132.     }  
  133.   
  134.     /* 给所有的列重新充电 */  
  135.     Start();  
  136.   
  137.     /* 若没有找到有效列,返回 */  
  138.     if (!(0 <= c && c < col_count))  
  139.         return 0xff;  
  140.   
  141.     return r * col_count + c;  
  142.    
  143. }  
  144.   
  145. // FindKey compares KeyCode to values in KeyTable.  
  146. // If match, KeyValue, KeyDown and KeyNew are updated.  
  147. void FindKey(void) {  
  148.  KeyValue = (KeyPressed)KeyCode;  
  149.  KeyDown = 1;  
  150.  KeyNew = 1;  
  151. }  
  152.   
  153.   
  154. void ClearKey(void) {  
  155.  KeyDown = 0;  
  156. }  
  157.   
  158. KeyPressed getKey(void) {  
  159.   if(KeyNew)  
  160.   {  
  161.     KeyNew = 0;  
  162.     return KeyValue;  
  163.   }  
  164.   else  
  165.     return Key_None;  
  166. }  
  167.   
  168. void Start(void)  
  169. {  
  170.     /* 列输出0, 拉低行 */  
  171.     PORT_KEY->BRR = COLS;  
  172. }  
  173.   
  174. void Stop(void)  
  175. {  
  176.     /* 列输出1,使行不被拉低 */  
  177.     PORT_KEY->BSRR = COLS;  
  178. }  
  179.   
  180. // cols bus output  
  181. void Cols_out(uint16_t v)  
  182. {  
  183.   if ((v & 0x01) > 0) //0b001  
  184.     High(_cols[0]);  
  185.   else  
  186.     Low(_cols[0]);  
  187.     
  188.   if ((v & 0x02) > 0) //0b010  
  189.     High(_cols[1]);  
  190.   else  
  191.     Low(_cols[1]);  
  192.     
  193.   if ((v & 0x04) > 0) //0b100  
  194.     High(_cols[2]);  
  195.   else  
  196.     Low(_cols[2]);  
  197.                                              
  198. }  


按键操作可以改到寄存器操作,提高速度。

使用mbed写,会更省事,可惜VBT6的RAM太少。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
单片机按键处理方式(一)——典型的按键处理方式
stm32的按键扫描[操作寄存器+库函数]-Changing's Blog
单片机STM32的LCD12864显示(1)
工程师为你讲解,如何看懂时序图!
stm32驱动 LCD1602
am2302稳定读取传感器数据驱动代码
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服