您的位置:首页 > 其它

stm32 4*4矩阵键盘

2015-12-23 11:30 621 查看
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]);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: