楼主使用的是下面这种矩阵键盘,由于网上大多资源都是同一GPIO配置的,如果我们使用了其他模块例如蓝牙模块,OLED等等,会占用同一GPIO口引脚,导致无法照搬网上。而且网上一些代码质量比较差,垃圾,难懂。以下具体原理不介绍,大家应该也在别的博客了解过,直接看代码。
下面这是我引脚配置代码:
在stm32F103上PA15 PB3 PB4等等一些引脚需要我们重映射。
void Key_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);
GPIO_PinRemapConfig( GPIO_Remap_SWJ_Disable,ENABLE);
// 列
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
GPIO_Init(GPIOB,&GPIO_InitStructure);
// 行
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15 ;
GPIO_Init(GPIOA,&GPIO_InitStructure);
for(int i= 0;i < ROWS;i++)
{
GPIO_SetBits(gpio_Key[i].GPIO_X, gpio_Key[i].GPIO_PIN_X); //行置高电平
}
}
按键应用层定义:
#define ROWS 4
#define COLS 4
uint8_t keyboard_value[ROWS][COLS] = {
{0x01, 0x02, 0x03, 0x0C},
{0x04, 0x05, 0x06, 0x0D},
{0x07, 0x08, 0x09, 0x0E},
{0x0A, 0x00, 0x0B, 0x0F},
};
struct GPIO_Key gpio_Key[ROWS+COLS] =
{
{GPIOA,GPIO_Pin_15}, // row
{GPIOB,GPIO_Pin_3},
{GPIOB,GPIO_Pin_4},
{GPIOB,GPIO_Pin_5},
{GPIOB,GPIO_Pin_6}, // col
{GPIOB,GPIO_Pin_7},
{GPIOB,GPIO_Pin_8},
{GPIOB,GPIO_Pin_9},
};
按键读取函数:
uint8_t Key_Scan(u8 i)
{
uint8_t j;
GPIO_ResetBits(gpio_Key[i].GPIO_X, gpio_Key[i].GPIO_PIN_X);
for (j = 0; j < COLS; j++)
{
if(!GPIO_ReadInputDataBit(gpio_Key[ROWS+j].GPIO_X, gpio_Key[ROWS+j].GPIO_PIN_X)) // 按下
{
delay_ms(10);
if(!GPIO_ReadInputDataBit(gpio_Key[ROWS+j].GPIO_X, gpio_Key[ROWS+j].GPIO_PIN_X)) // 按下
{
GPIO_SetBits(gpio_Key[i].GPIO_X, gpio_Key[i].GPIO_PIN_X);
return keyboard_value[i][j];
}
}
}
GPIO_SetBits(gpio_Key[i].GPIO_X, gpio_Key[i].GPIO_PIN_X);
return 0xFF;
}
使用案例:(可以实现松手触发按下)
// 按键第一行
void key0_Task(void)
{
u8 row0_val = 0;
static u8 key0_flag = false;
row0_val = Key_Scan(0);
if(row0_val != 0xFF && key0_flag == false)
{
key0_flag = true;
printf("%d\n\r",row0_val);
key_val = row0_val;
}else if(row0_val == 0xFF)
{
key0_flag = false;
}
}
// 按键第二行
void key1_Task(void)
{
u8 row1_val = 0;
static u8 key1_flag = false;
row1_val = Key_Scan(1);
if(row1_val != 0xFF && key1_flag == false)
{
key1_flag = true;
printf("%d\n\r",row1_val);
key_val = row1_val;
}else if(row1_val == 0xFF)
{
key1_flag = false;
}
}
效果展示: