stm32 4*4矩阵键盘

来源:互联网 发布:民国纪年法的算法 编辑:程序博客网 时间:2024/05/17 15:19

stm32f030开发板。


使用HAL库。

状态机做debounce消抖。


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

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


代码如下:

.h文件

/*** Name: keypad.h* Faq: www.mazclub.com*/#ifndef KEYPAD_H#define KEYPAD_H#include "stm32f0xx_hal.h"//#include "pinname.h"#define COLS (GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6)#define PORT_COL GPIOB#define KEYy0 GPIO_PIN_6#define KEYy1 GPIO_PIN_5#define KEYy2 GPIO_PIN_4#define KEYy3 GPIO_PIN_3#define PORT_ROW GPIOA#define KEYx0 GPIO_PIN_12#define KEYx1 GPIO_PIN_11#define KEYx2 GPIO_PIN_10#define KEYx3 GPIO_PIN_9// 读pin//#define In(GPIO_Pin) (PORT_KEY->IDR & GPIO_Pin)#define In(GPIO_Pin) HAL_GPIO_ReadPin(PORT_ROW, GPIO_Pin)// 写1到Pin//#define High(GPIO_Pin) PORT_KEY->BSRR = GPIO_Pin#define High(GPIO_Pin) HAL_GPIO_WritePin(PORT_COL, GPIO_Pin, GPIO_PIN_SET)// 写0到Pin//#define Low(GPIO_Pin) PORT_KEY->BSRR = (uint32_t)GPIO_Pin << 16 #define Low(GPIO_Pin) HAL_GPIO_WritePin(PORT_COL, GPIO_Pin, GPIO_PIN_RESET)/* *  0  1  2   3*  4  5  6   7*  8  9  10  11*  12 13 14  15*/typedef enum {    Key_Up = 0x02,    Key_Left = 0x03,    Key_Right = 0x04,    Key_Down = 0x08,    Key_Power =  0x09,    Key_Mode = 0x0a,    Key_None = 0xFF} KeyPressed;static const int row_count = 4;static const int col_count = 4;uint16_t bus_out(void);void Keypad(void);char AnyKey(void);char SameKey(void);char ScanKey(void);void FindKey(void);void ClearKey(void);void Read(void);/** Start the keypad interrupt routines */void Start(void);/** Stop the keypad interrupt routines */void Stop(void);void Cols_out(uint16_t v);void Scan_Keyboard(void);KeyPressed getKey(void);#endif // KEYPAD_H


.c文件

/*** Name: keypad.cpp* Faq: www.mazclub.com**/#include "keypad.h"// State:char KeyState;// Bit pattern after each scan:char KeyCode;// Output value from the virtual 74HC922:KeyPressed KeyValue;// KeyDown is set if key is down:char KeyDown;// KeyNew is set every time a new key is down:char KeyNew;// 映射表char KeyTable[12][2];  // Pin of Rowuint16_t _rows[] = {KEYx0, KEYx1, KEYx2, KEYx3};uint16_t _cols[] = {KEYy0, KEYy1, KEYy2, KEYy3};//构造函数void Keypad(void){        Stop();      KeyState = 0; // 按键状态初始 0}//扫描键盘void Scan_Keyboard(void){switch (KeyState) {  case 0: {  if (AnyKey()) {        char scankey = ScanKey();    if (scankey != 0xff)        KeyCode = scankey;        KeyState = 1;  }    break;  }  case 1: {  if (SameKey()) {    FindKey();    KeyState = 2;    }  else     KeyState = 0;    break;  }  case 2: {    if (SameKey()) {    }    else       KeyState = 3;        break;    }  case 3: {    if (SameKey()) {      KeyState = 2;    }    else {      ClearKey();      KeyState = 0;    }        break;   }  }// func end}// 有键按下char AnyKey(void) { //Start();  //拉低  int r = -1; for (r = 0; r < row_count; r++) {     if (In(_rows[r]) == 0)  // In macro         break;  }  //Stop();  //恢复  if (!(0 <= r && r < row_count))    return 0; else    return 1;}// 键按下, 键值相同char SameKey(void) {    // char KeyCode_new = KeyCode;  char KeyCode_new = ScanKey();  if (KeyCode == KeyCode_new)      return 1;  else    return 0;}// 扫描键char ScanKey(void) { /* 行扫描 */    int r = -1;    for (r = 0; r < row_count; r++) {        if (In(_rows[r]) == 0)  // In macro            break;    }    /* 若没有找到有效行,返回 */    if (!(0 <= r && r < row_count)) {      return 0xff;            }    /* 列扫描,找出行上哪个被拉低 */    int c = -1;    for (c = 0; c < col_count; c++) {        // 轮流输出列线        Cols_out(~(1 << c));                if (In(_rows[r]) == 0)  // In macro            break;    }    /* 给所有的列重新充电 */    Start();    /* 若没有找到有效列,返回 */    if (!(0 <= c && c < col_count))        return 0xff;    return r * col_count + c; }// FindKey compares KeyCode to values in KeyTable.// If match, KeyValue, KeyDown and KeyNew are updated.void FindKey(void) { KeyValue = (KeyPressed)KeyCode; KeyDown = 1; KeyNew = 1;}void ClearKey(void) { KeyDown = 0;}KeyPressed getKey(void) {  if(KeyNew)  {    KeyNew = 0;    return KeyValue;  }  else    return Key_None;}void Start(void){    /* 列输出0, 拉低行 */    PORT_COL->BRR = COLS;}void Stop(void){    /* 列输出1,使行不被拉低 */    PORT_COL->BSRR = COLS;}// cols bus outputvoid Cols_out(uint16_t v){  if ((v & 0x01) > 0) //0b001    High(_cols[0]);  else    Low(_cols[0]);    if ((v & 0x02) > 0) //0b010    High(_cols[1]);  else    Low(_cols[1]);    if ((v & 0x04) > 0) //0b100    High(_cols[2]);  else    Low(_cols[2]);    if ((v & 0x08) > 0) //0b100    High(_cols[3]);  else    Low(_cols[3]);                                           }




0 0