stm32 4*4矩阵键盘

发布者:SereneSpirit最新更新时间:2017-09-27 来源: eefocus关键字:stm32  4*4  矩阵键盘 手机看文章 扫描二维码
随时随地手机看文章

stm32f030开发板。


使用HAL库。

状态机做debounce消抖。


col列,Pin配置为PP推挽输出模式;

row行,Pin配置为Input模式,启用内部上拉电阻。


代码如下:

.h文件


  1. /* 

  2. * Name: keypad.h 

  3. * Faq: www.mazclub.com 

  4. */  

  5. #ifndef KEYPAD_H  

  6. #define KEYPAD_H  

  7.   

  8. #include "stm32f0xx_hal.h"  

  9. //#include "pinname.h"  

  10.   

  11.   

  12.   

  13.   

  14. #define COLS (GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6)  

  15.   

  16. #define PORT_COL GPIOB  

  17. #define KEYy0    GPIO_PIN_6  

  18. #define KEYy1    GPIO_PIN_5  

  19. #define KEYy2    GPIO_PIN_4  

  20. #define KEYy3    GPIO_PIN_3  

  21.   

  22. #define PORT_ROW GPIOA  

  23. #define KEYx0    GPIO_PIN_12  

  24. #define KEYx1    GPIO_PIN_11  

  25. #define KEYx2    GPIO_PIN_10  

  26. #define KEYx3    GPIO_PIN_9  

  27.   

  28. // 读pin  

  29. //#define In(GPIO_Pin) (PORT_KEY->IDR & GPIO_Pin)  

  30. #define In(GPIO_Pin) HAL_GPIO_ReadPin(PORT_ROW, GPIO_Pin)  

  31. // 写1到Pin  

  32. //#define High(GPIO_Pin) PORT_KEY->BSRR = GPIO_Pin  

  33. #define High(GPIO_Pin) HAL_GPIO_WritePin(PORT_COL, GPIO_Pin, GPIO_PIN_SET)  

  34. // 写0到Pin  

  35. //#define Low(GPIO_Pin) PORT_KEY->BSRR = (uint32_t)GPIO_Pin << 16   

  36. #define Low(GPIO_Pin) HAL_GPIO_WritePin(PORT_COL, GPIO_Pin, GPIO_PIN_RESET)  

  37.   

  38. /*  

  39. *  0  1  2   3 

  40. *  4  5  6   7 

  41. *  8  9  10  11 

  42. *  12 13 14  15 

  43. */  

  44.   

  45. typedef enum {  

  46.     Key_Up = 0x02,  

  47.     Key_Left = 0x03,  

  48.     Key_Right = 0x04,  

  49.     Key_Down = 0x08,  

  50.     Key_Power =  0x09,  

  51.     Key_Mode = 0x0a,  

  52.     Key_None = 0xFF  

  53. } KeyPressed;  

  54.       

  55. static const int row_count = 4;  

  56. static const int col_count = 4;  

  57.   

  58. uint16_t bus_out(void);  

  59.   

  60. void Keypad(void);  

  61. char AnyKey(void);  

  62. char SameKey(void);  

  63. char ScanKey(void);  

  64. void FindKey(void);  

  65. void ClearKey(void);  

  66. void Read(void);  

  67. /** Start the keypad interrupt routines */  

  68. void Start(void);  

  69. /** Stop the keypad interrupt routines */  

  70. void Stop(void);  

  71. void Cols_out(uint16_t v);  

  72. void Scan_Keyboard(void);  

  73. KeyPressed getKey(void);  

  74. #endif // KEYPAD_H  




.c文件


  1. /* 

  2. * Name: keypad.cpp 

  3. * Faq: www.mazclub.com 

  4. */  

  5.   

  6. #include "keypad.h"  

  7.   

  8. // State:  

  9. char KeyState;  

  10. // Bit pattern after each scan:  

  11. char KeyCode;  

  12. // Output value from the virtual 74HC922:  

  13. KeyPressed KeyValue;  

  14. // KeyDown is set if key is down:  

  15. char KeyDown;  

  16. // KeyNew is set every time a new key is down:  

  17. char KeyNew;  

  18. // 映射表  

  19. char KeyTable[12][2];    

  20. // Pin of Row  

  21. uint16_t _rows[] = {KEYx0, KEYx1, KEYx2, KEYx3};  

  22. uint16_t _cols[] = {KEYy0, KEYy1, KEYy2, KEYy3};  

  23.   

  24. //构造函数  

  25. void Keypad(void)  

  26. {  

  27.        

  28.    Stop();     

  29.    KeyState = 0; // 按键状态初始 0  

  30. }  

  31.   

  32.   

  33. //扫描键盘  

  34. void Scan_Keyboard(void){  

  35. switch (KeyState) {  

  36.   case 0: {  

  37.   if (AnyKey()) {      

  38.     char scankey = ScanKey();  

  39.     if (scankey != 0xff)  

  40.         KeyCode = scankey;  

  41.       

  42.     KeyState = 1;  

  43.   }  

  44.     

  45.   break;  

  46.   }  

  47.   case 1: {  

  48.   if (SameKey()) {  

  49.     FindKey();  

  50.     KeyState = 2;    

  51.   }  

  52.   else   

  53.     KeyState = 0;  

  54.     

  55.   break;  

  56.   }  

  57.   case 2: {  

  58.     if (SameKey()) {  

  59.     }  

  60.     else   

  61.       KeyState = 3;  

  62.       

  63.     break;  

  64.     }  

  65.   case 3: {  

  66.     if (SameKey()) {  

  67.       KeyState = 2;  

  68.     }  

  69.     else {  

  70.       ClearKey();  

  71.       KeyState = 0;  

  72.     }  

  73.       

  74.     break;  

  75.    }  

  76.   }  

  77. // func end  

  78. }  

  79.   

  80. // 有键按下  

  81. char AnyKey(void) {  

  82.  //Start();  //拉低  

  83.    

  84.  int r = -1;  

  85.  for (r = 0; r < row_count; r++) {  

  86.      if (In(_rows[r]) == 0)  // In macro  

  87.          break;    

  88.  }  

  89.    

  90.  //Stop();  //恢复  

  91.    

  92.  if (!(0 <= r && r < row_count))  

  93.     return 0;  

  94.  else  

  95.     return 1;  

  96. }  

  97.   

  98. // 键按下, 键值相同  

  99. char SameKey(void) {  

  100.     

  101.   // char KeyCode_new = KeyCode;  

  102.   char KeyCode_new = ScanKey();  

  103.   if (KeyCode == KeyCode_new)    

  104.     return 1;  

  105.   else  

  106.     return 0;  

  107. }  

  108.   

  109. // 扫描键  

  110. char ScanKey(void) {  

  111.   

  112.  /* 行扫描 */  

  113.     int r = -1;  

  114.     for (r = 0; r < row_count; r++) {  

  115.         if (In(_rows[r]) == 0)  // In macro  

  116.             break;  

  117.     }  

  118.   

  119.     /* 若没有找到有效行,返回 */  

  120.     if (!(0 <= r && r < row_count)) {  

  121.       return 0xff;  

  122.           

  123.     }  

  124.   

  125.     /* 列扫描,找出行上哪个被拉低 */  

  126.     int c = -1;  

  127.     for (c = 0; c < col_count; c++) {  

  128.         // 轮流输出列线  

  129.         Cols_out(~(1 << c));  

  130.           

  131.         if (In(_rows[r]) == 0)  // In macro  

  132.             break;  

  133.     }  

  134.   

  135.     /* 给所有的列重新充电 */  

  136.     Start();  

  137.   

  138.     /* 若没有找到有效列,返回 */  

  139.     if (!(0 <= c && c < col_count))  

  140.         return 0xff;  

  141.   

  142.     return r * col_count + c;  

  143.    

  144. }  

  145.   

  146. // FindKey compares KeyCode to values in KeyTable.  

  147. // If match, KeyValue, KeyDown and KeyNew are updated.  

  148. void FindKey(void) {  

  149.  KeyValue = (KeyPressed)KeyCode;  

  150.  KeyDown = 1;  

  151.  KeyNew = 1;  

  152. }  

  153.   

  154.   

  155. void ClearKey(void) {  

  156.  KeyDown = 0;  

  157. }  

  158.   

  159. KeyPressed getKey(void) {  

  160.   if(KeyNew)  

  161.   {  

  162.     KeyNew = 0;  

  163.     return KeyValue;  

  164.   }  

  165.   else  

  166.     return Key_None;  

  167. }  

  168.   

  169. void Start(void)  

  170. {  

  171.     /* 列输出0, 拉低行 */  

  172.     PORT_COL->BRR = COLS;  

  173. }  

  174.   

  175. void Stop(void)  

  176. {  

  177.     /* 列输出1,使行不被拉低 */  

  178.     PORT_COL->BSRR = COLS;  

  179. }  

  180.   

  181. // cols bus output  

  182. void Cols_out(uint16_t v)  

  183. {  

  184.   if ((v & 0x01) > 0) //0b001  

  185.     High(_cols[0]);  

  186.   else  

  187.     Low(_cols[0]);  

  188.     

  189.   if ((v & 0x02) > 0) //0b010  

  190.     High(_cols[1]);  

  191.   else  

  192.     Low(_cols[1]);  

  193.     

  194.   if ((v & 0x04) > 0) //0b100  

  195.     High(_cols[2]);  

  196.   else  

  197.     Low(_cols[2]);  

  198.     

  199.   if ((v & 0x08) > 0) //0b100  

  200.     High(_cols[3]);  

  201.   else  

  202.     Low(_cols[3]);  

  203.                                              

  204. }  


关键字:stm32  4*4  矩阵键盘 引用地址:stm32 4*4矩阵键盘

上一篇:stm32定时器之Output Compare
下一篇:理解stm32开漏输出与推挽输出

推荐阅读最新更新时间:2024-03-16 15:38

STM32串口中断 RXNE TXE
RXNE中断 (使能位为RXNEIE) 串口接收寄存器非空中断, 通过读取接收寄存器清除中断标志位 TXE中断(使能位为TXEIE) 串口发送寄存器空中断, 当不需要发送数据时,需要失能此中断,否则由于满足发送寄存器为空的条件,会一直进入中断 通过写接收寄存器清除中断标志位,当发送完成时寄存器为空,此位又会被被硬件置1 进入中断时,需要判断中断标志位和中断使能位,当两个标志位同时为1时才满足中断的条件,否则由于不同中断源共用中断入口而导致错误。(如RXNE触发了中断,此时TXE标志位也可能为1,若没有对TXEIE位进行判断可能会误认为产生了TXE中断,造成错误)
[单片机]
无源型低成本两线制4-20mA电流转模拟电压信号I/V转换信号隔离器
ISO 4-20mA-O系列(SIP12 Pin封装)两线制无源型4-20mA转电压信号隔离转换器,可以将输入有源4-20mA的电流信号隔离转换成电压信号I/V转换输出。该方案采用两线制输入回路供电方式,独有高效信号回路窃电技术,无须外接工作电源,大大简化了用户的设计,降低用户布线成本。该模块内部包含有电流信号调制解调电路、信号耦合隔离变换电路、电源逆变电路、减法电路,缓冲处理输出电路等,很小的输入等效电阻,使该产品能够从传感器信号输出回路中采集电流信号,并能达到输入20mA信号时电压降 ≤10V。以满足用户无需外接辅助电源而实现信号远距离、无失真传输变换的需要。
[嵌入式]
无源型低成本两线制<font color='red'>4</font>-20mA电流转模拟电压信号I/V转换信号隔离器
苹果4寸新机消息整理
    市场传闻许久的4寸iPhone可能将在近期内发表,同时预期以更快速度进入市场,我们将近期传闻内容作整理,让大家可在新机实际发表之前作简单回顾。 苹果为什么要推4寸新机? 由于目前在美国、欧洲市场仍有多数使用者偏好4寸机种,加上iPhone 5s在市场销售也已经有一段时间,因此苹果可能针对此类市场需求提供新机,并且加入更多应用在iPhone 6、iPhone 6s系列硬体设计与功能,藉此吸引这些用户族群可进一步移转到主流产品,同时也预期可增加本身服务使用比例,例如Apple Pay、iCloud等。 名称就叫“iPhone se”? 目前苹果尚未对外公布,因此目前绝大部分都是市场揣测消息,但有部分说法
[手机便携]
官宣:荣耀30系列支持4K超暗光视频、支持AIS视频超级防抖
此前荣耀官宣荣耀30系列新品发布会将于4月15日举行 。荣耀业务部副总裁(产品)熊军民也确认荣耀30系列将首发麒麟985芯片。 今(12)日,荣耀30系列的新特性也被曝光,支持4K超暗光视频、AIS视频超级防抖、1920fps超级慢动作等功能。 综合集微网此前报道,荣耀30系列还有以下信息: 1.充电快:搭载40W超级快充,获得莱茵安全快充认证,无线快充也没有缺席。 2.音量足:搭载全频段大振幅双扬声器,音色细腻,听感极为震撼。Histen智能音效,游戏听声辨位。 3.有高刷:有网友问荣耀30系列有没有高刷新率的屏幕,荣耀业务部副总裁(产品)熊军民回应说一个都不少,必须有。 4.真轻薄:熊军民发微博称荣耀30系列中的荣耀30机
[手机便携]
或为EOS R套机镜头 佳能公布RF 24-70/4专利
来自CanonRumors的消息,佳能近日公布了一项新的镜头专利技术。据专利描述文件显示,这是一支RF 24-70mm f/4 L IS USM镜头,内含12枚镜片,这或许将成为未来新款EOS R相机的套机镜头。 RF 24-70mm f/4 L IS USM镜头专利 ·RF 24-70mm f/4L IS USM:   焦距:24.71-39.93-67.99   光圈值:4.12-4.12-4.12   半场角:41.20-28.45-17.65   图像高度:21.64-21.64-21.64   整体镜头长度:99.36-108.69-132.25   BF:13.50-24.36-42.60    ·编辑观点:
[家用电子]
STM32的RCC配置流程
在STM32中,有五个时钟源,为HSI、HSE、LSI、LSE、PLL。 ①HSI是高速内部时钟,RC振荡器,频率为8MHz。 ②HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。 ③LSI是低速内部时钟,RC振荡器,频率为40kHz。 ④LSE是低速外部时钟,接频率为32.768kHz的石英晶体。 ⑤PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为2~16倍,但是其输出频率最大不得超过72MHz。 用户可通过预分频器配置AHB,APB2,APB1总线的频率,AHB和APB2域的最大频率是72MHZ。APB1域的最大允许频
[单片机]
分区域升级 三星S4 Mini"品尝棒棒糖"
    虽然2015年不少老款智能机都陆续升级Android 5.0,但也有个别产品的升级前景不太乐观,三星S4 Mini就是其中之一。英国运营商Three不久前通过推特表示,三星S4 Mini将无缘Android 5.0。 三星S4 Mini     至于其中的原因Three表示三星S4 Mini的存储空间限制是一大因素,而三星官方也向Three确认了这一原因。三星S4 Mini于2013年发布,是一款机身紧凑功能也比较全面的产品。   不过根据最新消息,Three设在爱尔兰的分支机构表示三星S4 Mini存在Android 5.0的升级包,或许这款产品会根据不同的地域来更新,而更新的时间表现在还不清楚。
[手机便携]
基于STM32 MCU应用的EMC指南之软件篇
在基于微控制器的电子系统中,强壮的软件设计是提高 EMC 性能的主要因素。必须尽量在项目设计阶段的早期考虑 EMC 干扰导致的问题。EMC 导向的软件提高了应用的安全性和可靠性。强化 EMC 性能的软件的实施成本低,可提高最终的抗扰性能,并节约硬件和开发成本。用户应考虑到模拟或数字数据受到的 EMC 干扰,就像任何其它应用参数一样。 EMC 干扰导致的问题示例: 微控制器无响应 程序计数器失控 执行意外指令 地址指向错误 子程序执行错误 寄生复位和 / 或寄生中断 IP 配置损坏 I/O 失灵 软件故障的后果示例: 产品意外响应 上下文丢失 进程中的意外分支 中断丢失 数据完整性缺失 输入值误读 01使用看门狗或时间控制 为了
[单片机]
基于<font color='red'>STM32</font> MCU应用的EMC指南之软件篇
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved