stm32F103状态机矩阵键盘
扫描二维码
随时随地手机看文章
矩阵键盘程序,作为麦知club小车项目的一部分,从IAR状态机应用修改而来。
IAR7.4+STM32CUBEMX调试通过。
键盘行4,列3,每条线都有10K上拉电阻。改到4×4矩阵也很容易。
行线设置为 输入,针脚为浮空; 列线设置为开漏输出。
不支持长按和组合键,主要是我不会改。
在OS中使用20ms任务周期调用。
以下贴出代码。
keypad.h
/*
*
*Name:keypad.h
*/
#ifndefKEYPAD_H
#defineKEYPAD_H
#include"stm32f1xx_hal.h"
#include"pinname.h"
#definePORT_KEYGPIOD
#defineCOLS(GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6)
//读pin
//#defineIn(GPIO_Pin)(PORT_KEY->IDR&GPIO_Pin)
#defineIn(GPIO_Pin)HAL_GPIO_ReadPin(PORT_KEY,GPIO_Pin)
//写1到Pin
//#defineHigh(GPIO_Pin)PORT_KEY->BSRR=GPIO_Pin
#defineHigh(GPIO_Pin)HAL_GPIO_WritePin(PORT_KEY,GPIO_Pin,GPIO_PIN_SET)
//写0到Pin
//#defineLow(GPIO_Pin)PORT_KEY->BSRR=(uint32_t)GPIO_Pin<<16
#defineLow(GPIO_Pin)HAL_GPIO_WritePin(PORT_KEY,GPIO_Pin,GPIO_PIN_RESET)
/*
*0123
*4567
*891011
*12131415
*/
typedefenum{
Key_Up=0x02,
Key_Left=0x03,
Key_Right=0x04,
Key_Down=0x08,
Key_On=0x09,
Key_Mode=0x0a,
Key_None=0xFF
}KeyPressed;
staticconstintrow_count=4;
staticconstintcol_count=3;
uint16_tbus_out(void);
voidKeypad(void);
charAnyKey(void);
charSameKey(void);
charScanKey(void);
voidFindKey(void);
voidClearKey(void);
voidRead(void);
/**Startthekeypadinterruptroutines*/
voidStart(void);
/**Stopthekeypadinterruptroutines*/
voidStop(void);
voidCols_out(uint16_tv);
voidScan_Keyboard(void);
KeyPressedgetKey(void);
#endif//KEYPAD_H
keypad.c
/*
*
*Name:keypad.cpp
*
*/
#include"keypad.h"
//State:
charKeyState;
//Bitpatternaftereachscan:
charKeyCode;
//Outputvaluefromthevirtual74HC922:
KeyPressedKeyValue;
//KeyDownissetifkeyisdown:
charKeyDown;
//KeyNewisseteverytimeanewkeyisdown:
charKeyNew;
//映射表
charKeyTable[12][2];
//PinofRow
uint16_t_rows[]={KEYx0,KEYx1,KEYx2,KEYx3};
uint16_t_cols[]={KEYy0,KEYy1,KEYy2};
//构造函数
voidKeypad(void)
{
Stop();
KeyState=0;//按键状态初始0
}
//扫描键盘
voidScan_Keyboard(void){
switch(KeyState){
case0:{
if(AnyKey()){
charscankey=ScanKey();
if(scankey!=0xff)
KeyCode=scankey;
KeyState=1;
}
break;
}
case1:{
if(SameKey()){
FindKey();
KeyState=2;
}
else
KeyState=0;
break;
}
case2:{
if(SameKey()){
}
else
KeyState=3;
break;
}
case3:{
if(SameKey()){
KeyState=2;
}
else{
ClearKey();
KeyState=0;
}
break;
}
}
//funcend
}
//有键按下
charAnyKey(void){
//Start();//拉低
intr=-1;
for(r=0;r if(In(_rows[r])==0)//Inmacro break; } //Stop();//恢复 if(!(0<=r&&r return0; else return1; } //键按下,键值相同 charSameKey(void){ //charKeyCode_new=KeyCode; charKeyCode_new=ScanKey(); if(KeyCode==KeyCode_new) return1; else return0; } //扫描键 charScanKey(void){ /*行扫描*/ intr=-1; for(r=0;r if(In(_rows[r])==0)//Inmacro break; } /*若没有找到有效行,返回*/ if(!(0<=r&&r return0xff; } /*列扫描,找出行上哪个被拉低*/ intc=-1; for(c=0;c //轮流输出列线 Cols_out(~(1< if(In(_rows[r])==0)//Inmacro break; } /*给所有的列重新充电*/ Start(); /*若没有找到有效列,返回*/ if(!(0<=c&&c return0xff; return r * col_count + c;