stm32 4*4矩阵键盘

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 Row
uint16_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 output
void 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]);
                                           
}




你可能感兴趣的:(STM32)