自己找了别人的代码修改了一下,加了连按和不连续按的功能,很稳定。
原理放在代码的注释里了,就是行扫描和列扫描去确定哪个按键按下。
引脚和单片机的连线
薄膜键盘有8个脚,标好数字的。
1接 B11
2接 B10
3接 B9
4接 B8
5接 C6
6接 C7
7接 C8
8接 C9
.H文件
> #ifndef __MATRIX_KEY_H__
#define __MATRIX_KEY_H__
#include "stm32f10x.h"
#include "sys.h"
#include "delay.h"
#define ROW_1 PCout(6)
#define ROW_2 PCout(7)
#define ROW_3 PCout(8)
#define ROW_4 PCout(9)
#define COL_1 PBout(11)
#define COL_2 PBout(10)
#define COL_3 PBout(9)
#define COL_4 PBout(8)
#define ROW1 GPIO_Pin_6
#define ROW2 GPIO_Pin_7
#define ROW3 GPIO_Pin_8
#define ROW4 GPIO_Pin_9
#define COL1 GPIO_Pin_11
#define COL2 GPIO_Pin_10
#define COL3 GPIO_Pin_9
#define COL4 GPIO_Pin_8
typedef enum
{
Column,
Row,
Normal
} MatirxMode;
extern void MatrixKeyConfiguration(void);
extern uint8_t GetMatrixKeyValue(void);
extern uint8_t GetMatrixKeyValue_Once(void);
#endif
.C文件
#include "matrixkey.h"
//R1,R2,R3,R4,C1,C2,C3,C4
//C6,C7,C8,C9,B11,B10,B9,B8
void MatrixKeyConfiguration(void) //按键初始化
{
GPIO_InitTypeDef GPIO;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB |
RCC_APB2Periph_GPIOC, ENABLE);
//Register IO
GPIO.GPIO_Pin = ROW3 | ROW4 | ROW1 | ROW2;
GPIO.GPIO_Speed = GPIO_Speed_50MHz;
GPIO.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO);
GPIO.GPIO_Pin = COL1 | COL2|COL3|COL4;
GPIO_Init(GPIOB, &GPIO);
ROW_1 = 1;
ROW_2 = 1;
ROW_3 = 1;
ROW_4 = 1;
COL_1 = 1;
COL_2 = 1;
COL_3 = 1;
COL_4 = 1;
//MatrixModeConfig(Column);
}
//R1,R2,R3,R4,C1,C2,C3,C4
//C6,C7,C8,C9,B11,B10,B9,B8
void MatrixModeConfig(MatirxMode mode)//行扫描时,需要把行对应的IO口设置成上拉输入,列设置成推挽输出并全部赋值为0。行对应的IO口检测是否有低电平的输入,从而判断是哪一行按下了。
{
GPIO_InitTypeDef GPIO;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB |
RCC_APB2Periph_GPIOC, ENABLE);
switch(mode)
{
case Column:
GPIO.GPIO_Pin =COL1 | COL2 |COL3 |COL4;
GPIO.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOB, &GPIO); //列扫描模式时,列上拉输入
//==============================================//
GPIO.GPIO_Pin = ROW1 | ROW2|ROW3|ROW4;
GPIO.GPIO_Speed = GPIO_Speed_50MHz;
GPIO.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO); //行推挽输出0
//BIT_ADDR(GPIOA_IDR_Addr,n)
BIT_ADDR(GPIOC_ODR_Addr,6) = 0;
BIT_ADDR(GPIOC_ODR_Addr,7) = 0;
BIT_ADDR(GPIOC_ODR_Addr,8) = 0;
BIT_ADDR(GPIOC_ODR_Addr,9) = 0;
break;
case Row:
GPIO.GPIO_Pin = COL1 | COL2|COL3|COL4;
GPIO.GPIO_Speed = GPIO_Speed_50MHz;
GPIO.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO); //行扫描模式时,行上拉,列推挽输出0
BIT_ADDR(GPIOB_ODR_Addr,11) = 0;
BIT_ADDR(GPIOB_ODR_Addr,10) = 0;
BIT_ADDR(GPIOB_ODR_Addr,9) = 0;
BIT_ADDR(GPIOB_ODR_Addr,8) = 0;
//==============================================//
GPIO.GPIO_Pin = ROW1 | ROW2|ROW3|ROW4;
GPIO.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOC, &GPIO);
break;
}
}
/************************************/
/*return 1 to 16 */
/*erturn 0 is error or not respnose */
/************************************/
//R1,R2,R3,R4,C1,C2,C3,C4
//C6,C7,C8,C9,B11,B10,B9,B8
uint8_t GetMatrixKeyValue(void) //支持连按
{
uint8_t value = 0;
uint8_t Rowvalue = 0;
MatrixModeConfig(Row);//行扫描
if (BIT_ADDR(GPIOC_IDR_Addr,9) == 0)
{
delay_ms(5);
if (BIT_ADDR(GPIOC_IDR_Addr,9) == 0)
{
value += 0;
}
}
else if (BIT_ADDR(GPIOC_IDR_Addr,8) == 0)
{
delay_ms(5);
if (BIT_ADDR(GPIOC_IDR_Addr,8) == 0)
{
value += 4;
}
}
else if (BIT_ADDR(GPIOC_IDR_Addr,7) == 0)
{
delay_ms(5);
if (BIT_ADDR(GPIOC_IDR_Addr,7) == 0)
{
value += 8;
}
}
else if (BIT_ADDR(GPIOC_IDR_Addr,6) == 0)
{
delay_ms(5);
if (BIT_ADDR(GPIOC_IDR_Addr,6) == 0)
{
value +=12;
}
}
else
{
value = 0;
}
Rowvalue=value;
MatrixModeConfig(Column); //列扫描
if (BIT_ADDR(GPIOB_IDR_Addr,8) == 0)
{
delay_ms(5);
if (BIT_ADDR(GPIOB_IDR_Addr,8) == 0)
{
value += 1;
}
}
else if (BIT_ADDR(GPIOB_IDR_Addr,9) == 0)
{
delay_ms(5);
if (BIT_ADDR(GPIOB_IDR_Addr,9) == 0)
{
value += 2;
}
}
else if (BIT_ADDR(GPIOB_IDR_Addr,10) == 0)
{
delay_ms(5);
if (BIT_ADDR(GPIOB_IDR_Addr,10) == 0)
{
value += 3;
}
}
else if (BIT_ADDR(GPIOB_IDR_Addr,11) == 0)
{
delay_ms(5);
if (BIT_ADDR(GPIOB_IDR_Addr,11) == 0)
{
value += 4;
}
}
else
{
value = 0;
}
if(value==Rowvalue){return 0;} //说明列扫描失败,可能按键已经松开,防止行扫描成功后按键松开而导致列扫描失败的错误情况。
return value;
}
uint8_t GetMatrixKeyValue_Once(void) //不支持连按
{
static u8 key_up=1;//按键按松开标志
u8 t;
t=GetMatrixKeyValue();
if(key_up&&t)
{
key_up=0;
return t;
}else if(t==0)key_up=1;
return 0;// 无按键按下
}