stm32F103状态机矩阵键盘

发布者:哈哈哈33最新更新时间:2017-09-27 来源: eefocus关键字: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太少。


关键字:stm32F103  状态机  矩阵键盘 引用地址:stm32F103状态机矩阵键盘

上一篇:STM32F103利用模拟I2C驱动ADS1115
下一篇:STM32F103控制ADS1115采集模拟信号

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

STM32F103学习笔记三 串口通信
1、串口通信背景知识 1.1、 设备之间的通信方式 并行通信 串行通信 传输原理 数据各个位同时传输 数据按位顺序传输 优点 速度快 占用引脚资源少 缺点 占用引脚资源多 速度相对较慢 1.2、 串行通信分类 1.2.1、按照通信方式,分为: 同步通信:带时钟同步信号传输。比如:SPI,I²C通信接口 异步通信:不带时钟同步信号。比如:UART(通用异步收发器),单总线 1.2.2、按照数据传送方向,分为: 单工:数据传输只支持数据在一个方向上传输; 半双工:允许数据在两个方向上传输。但是,在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信;它不需要独立的接收端和发送端,两者可以合并一起使用一个端口。 全
[单片机]
<font color='red'>STM32F103</font>学习笔记三 串口通信
怎样用ArduinoIDE对STM32F103C8T6进行编程
STM32F103C8T6板 - 也称为Blue Pill - 是ARM Cortex的开发板M3微控制器。它看起来与Arduino Nano非常相似,但它包含更多功能。 在本文中,我将向您展示如何使用Arduino IDE设置STM32并向您展示如何直接来自USB UART模块的程序。 STM32概述“Blue Pill” 如果你看看这个2美元的微控制器,您看到的第一件事就是它的跳线引脚,用于使用默认的USART引导加载程序。板上还有一个微型USB端口,但遗憾的是它不能用于编程,因为它没有相关的引导加载程序。 与官方的Arduino板相比,这些板非常便宜,而且硬件是开源的。除了微控制器外,该板还可以容纳两个晶体振荡器
[单片机]
怎样用ArduinoIDE对<font color='red'>STM32F103</font>C8T6进行编程
STM32f103-实例睡眠模式的唤醒
main.c /***************************************************************************/ // environment : writ by Chen maolin in 2010/9/23 on Kiel 4.0 // finktion : about a projiect to setup EXTI // hardware optimization : // update : 2010/9/26 陈茂林 /*************************************************
[单片机]
51单片机矩阵键盘与8051连接设计
众所周知,51单片机一般的键盘检测原理为非编码键盘检测,没有专门用来产生键编码号或键值的电路芯片;而我们使用的电脑键盘为编码键盘,通过编码电路芯片为每个按键产生一个编码号,可以通过串行总线把键值传输给电脑。在进行矩阵键盘检测时,书本或老师一般教的都是扫描检测,即一行一行地检测或者一列一列地检测,代码繁琐复杂,且缺点很多(例如执行效率较低)。 举例电路: 矩阵键盘与8051连接如上图所示,首先,令P3=0x0f,检测P30、P31、P32、P33哪一行被按下,将此时P3的值存入寄存器1。然后,令P3=0xf0 | 寄存器1,检测P34、P35、P36、P37哪一列被按下,将此时P3的值存入寄存器2。最后,把寄存器1的值和寄存
[单片机]
51单片机<font color='red'>矩阵键盘</font>与8051连接设计
STM32F103x的USB多路数据采集系统设计
   引 言   目前,在工业和许多其他场合依然使用基于PCI板卡、ISA板卡的数据采集系统,价格昂贵、接插不方便。USB(Universal Serial Bus,通用串行总线)是计算机上的一种新型接口技术,它使得计算机和外部设备的连接十分方便。USB具有高效、快速、价格低廉、体积小和支持热拔插等优点,使其成为数据采集系统设计的新宠儿。然而当前的USB数据采集设备大多采用的是专门的USB接口芯片,而且根据不同的需求,需要外扩一定数量的A/D 转换芯片,使得接口非常复杂,增加了系统的开发难度,进而对系统的稳定性产生影响。本设计采用意法半导体公司开发的基于Cortex-M3内核的新型32 位微控制器STM32F103x作为主控芯片
[单片机]
STM32F103单片机学习笔记(2):外部中断
对于STM32的中断首先需要用到的文件是startup_stm32f10x_hd.s和stm32f10x_it.c这两个文件,其中startup_stm32f10x_hd.s是启动文件,stm32f10x_it.c是中断响应函数。对于外部中断,它的过程是外部的IO口监测到电平的变化,触发外部中断,所以它又涉及到3个库文件,stm32f10x_gpio.c、stm32f10x_exti.c和misc.c,misc.c包含中断库,stm32f10x_exti.c是外部的IO口中断,stm32f10x_gpio.c是IO口的配置。还有一个我们上一篇中说的所有的外设都要用到的库文件时钟stm32f10x_rcc.c。 一、启动文件 说
[单片机]
<font color='red'>STM32F103</font>单片机学习笔记(2):外部中断
4×4矩阵键盘,控制数码管显示
题目要求: 两个数码管显示0-59秒的秒表。一矩阵键盘,输入0-F。 当A键按下后,进入修改时间状态,此时在分别按下0-9中的任意两个数,数码管时间更改。 如按下09,数码管此时显示09。 再按下A键,数码管从09继续跑。 写出C语言程序,端口随便接。 问题关键是如何实现A按下后,数码管秒数的改变。麻烦行家帮帮忙。非常感谢。 悬赏分:100 | 解决时间:2011-3-11 16:55 //======================================= 最佳答案: 下列程序已经调好,按键显示电路可见: http://hi.baidu.com/%D7%F6%B6%F8%C2%DB%B5%C0/blog/item/ef
[单片机]
4×4<font color='red'>矩阵键盘</font>,控制数码管显示
基于stm32f103zet6的FAT16文件系统学习0(读SD卡扇区)
SD卡已经看了两天了,主要是因为测试出来的卡容量不对,所以一直找原因,最终还是发现了,总比不过是单位上面出现了问题,或许是之前没有接触到SD的缘故吧,所以对其中的一些寄存器很不了解,一切都是重新开始,对照这寄存器手册,理解程序,修改程序。一步步还是总结一下! 首先关于SD卡的协议是有必要了解的,我今天花了一上午的课堂时间来理解这个SD卡的协议,就是基于这个文档的,这个文档很适合入门SD协议的(个人认为)。 http://download.csdn.net/detail/king_bingge/5218183 初识SD之后,就可以开始正式学习SD卡了! 一、要使用SD卡,那么首先肯定得对SD卡进行初始化,那么如何进行初始化呢?(命
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

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

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

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