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定时器之Output Compare
下一篇:理解stm32开漏输出与推挽输出
推荐阅读最新更新时间:2024-03-16 15:38
设计资源 培训 开发板 精华推荐
- 希润医疗孟铭强:手功能软体机器人,让脑卒中患者重获新生
- 柔灵科技陈涵:将小型、柔性的脑机接口睡眠设备,做到千家万户
- 微灵医疗李骁健:脑机接口技术正在开启意识与AI融合的新纪元
- USB Type-C® 和 USB Power Delivery:专为扩展功率范围和电池供电型系统而设计
- 景昱医疗耿东:脑机接口DBS治疗技术已实现国产替代
- 首都医科大学王长明:针对癫痫的数字疗法已进入使用阶段
- 非常见问题解答第223期:如何在没有软启动方程的情况下测量和确定软启动时序?
- 兆易创新GD25/55全系列车规级SPI NOR Flash荣获ISO 26262 ASIL D功能安全认证证书
- 新型IsoVu™ 隔离电流探头:为电流测量带来全新维度
- 英飞凌推出简化电机控制开发的ModusToolbox™电机套件