首页 > 行业资讯 > 正文

需要知识点

按键的原理

GPIO输入输出

寄存器操作,如果学过51或者对C语言很熟练这里不存在问题。寄存器说白了就是操作他们的位(寄存器我理解就是一串羊肉串,让你找出你先吃哪个,比如我要吃中间的哪一个该怎么取出来)

矩阵按键原理

本实验使用STM32F103单片机,主题代码通用的。

如果每个按键占用一个GPIO引脚,对于使用多个按键来说就是一种资源的浪费,因此当我们在设计时,可以考虑矩阵这种方式。本实验使用4*4也就是16个按键。

矩阵按键相对于独立按键稍微麻烦一点。4×4矩阵按键按照矩阵方式分别分为4行4列。主要有两种方式,一种是逐行扫描、一种是行列扫描。

原理图:

基于STM32F103单片机的矩阵按键设计-单片机矩阵键盘程序流程图

逐行扫描

通过在矩阵按键的每一条行线上轮流输出低电平,检测矩阵按键的列线,当检测到的列线不全为高电平的时候,说明有按键按下。然后,根据当前输出低电平的行号和检测到低电平的列号组合,判断是哪一个按键被按下。

行列扫描

首先,在全部行线上输出低电平,检测矩阵按键的列线,当检测到的列线不全为高电平的时候,说明有按键按下,并判断是哪一列有按键按下。

然后,反过来,在全部列线上输出低电平,检测矩阵按键的行线,当检测到的行线不全为高电平的时候,说明有按键按下,并判断是哪一行有按键按下。

最后,根据检测到的行号和检测的列号组合,以判断是哪一个按键被按下。

按键检测说白了就是按键按下之后是不是导通的,而其他没有按下的按键是没有导通的,代码也不唯一,是多种多样的。这里就需要操作寄存器或者使用库函数的位操作。

流程

基于STM32F103单片机的矩阵按键设计-单片机矩阵键盘程序流程图1

矩阵按键程序实现

根据是国内棉矩阵按键电路图,编写矩阵按键应用程序,轮徇K1~K8按键动作,当对应的按键按下后,返回对应的值:

矩阵按键:

复制/************ 按键表盘为: 1 2 3 10 4 5 6 11 7 8 9 12 13 0 14 15 /K1-K4(行)/ /K5-K8(列)/ /************ K1—>PC0 K2—>PC1 K3—>PC2 K4—>PC3 K5—>PC4 K6—>PC5 K7—>PC6 ***********************/

编程要点

(1)使能LED灯和矩阵按键的GPIO时钟。调用函数:

RCC_AHB1PeriphClockCmd();

(2)编写矩阵按键扫描程序。

(3)同2-STM32GPIO输入之按键

矩阵按键引脚配置

复制/************************************************************************ * @brief KEY_Config 按键初始化配置 * @brief 列检测初始化 * @param 无 * @retval 无 ***********************************************************************/ static void KEY_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; /*开启RCC时钟*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); /*K1-K4(行)*/ GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3); //设置引脚为 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //设置引脚速度50MHZ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); /*K5-K8(列)*/ GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7); //设置引脚为推挽输出模式 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //设置引脚速度50MHZ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); }

矩阵按键扫描程序

复制/************************************************************************ * @brief KEY_4_4_Scan 扫描函数 矩阵按键扫描,返回一个键值 * @brief 列检测初始化 * @param 无 * @retval uint8_t *********************************** 按键表盘为: 1 2 3 10 4 5 6 11 7 8 9 12 13 0 14 15 ************************************ 矩阵按键: /************************************ 按键表盘为: 1 2 3 10 4 5 6 11 7 8 9 12 13 0 14 15 /************************************ K1—>PC0 K2—>PC1 K3—>PC2 K4—>PC3 K5—>PC4 K6—>PC5 K7—>PC6 ***********************************************************************/ uint8_t KEY_4_4_Scan(void) { u8 KeyVal = 0; GPIO_Write(GPIOC, (GPIOC->ODR & 0xff00 | 0x000f)); // PC0-PC3全部输出高。 if (((GPIOC->IDR & 0X00F0)) == 0x0000) // PC4-PC7为0则没有按键按下(第一次检测按键是否有按下) { return 0xFF; } else { Delay_ms(10); //软件延时 if (((GPIOC->IDR & 0X00F0)) == 0x0000) // PC4-PC7为0则没有按键按下(第二次检测按键是否有按下) { return 0xFF; } } GPIO_Write(GPIOC, ((GPIOC->ODR & 0xfff0) | 0x0001)); //仅将PC0置高 switch ((GPIOC->IDR & 0X00f0)) //第一行,从PC4开始拉高,其余为0,PC5-PC7一样 { case 0x0010: KeyVal = 1; // PC4 break; case 0x0020: KeyVal = 2; // PC5 break; case 0x0040: KeyVal = 3; // PC6 break; case 0x0080: KeyVal = 10; // PC7 break; } while (((GPIOC->IDR & 0X00F0)) > 0) //等待按键释放, GPIO_Write(GPIOC, 0x0000); //重新让PC0到PC3全部输出低。 GPIO_Write(GPIOC, ((GPIOC->ODR & 0xfff0) | 0x0002)); //仅将PC1置高 switch ((GPIOC->IDR & 0X00F0)) //第一行,从PC4开始拉高,其余为0,PC5-PC7一样 { case 0x0010: KeyVal = 4; break; case 0x0020: KeyVal = 5; break; case 0x0040: KeyVal = 6; break; case 0x0080: KeyVal = 11; break; } while (((GPIOC->IDR & 0X00F0)) > 0) //等待按键释放 GPIO_Write(GPIOC, 0x0000); //重新让PC0到PC3全部输出低。 GPIO_Write(GPIOC, ((GPIOC->ODR & 0xfff0) | 0x0004)); //仅将PC2置高 switch ((GPIOC->IDR & 0X00F0)) { case 0x0010: KeyVal = 7; break; case 0x0020: KeyVal = 8; break; case 0x0040: KeyVal = 9; break; case 0x0080: KeyVal = 12; break; } while (((GPIOC->IDR & 0X00F0)) > 0) GPIO_Write(GPIOC, 0x0000); //重新让PC0到PC3全部输出低。 GPIO_Write(GPIOC, ((GPIOC->ODR & 0xfff0) | 0x0008)); //仅将PC3置高 switch ((GPIOC->IDR & 0X00F0)) { case 0x0010: KeyVal = 13; break; case 0x0020: KeyVal = 0; break; case 0x0040: KeyVal = 15; break; case 0x0080: KeyVal = 16; break; } while (((GPIOC->IDR & 0X00F0)) > 0) //等待按键释放 GPIO_Write(GPIOC, 0x0000); //重新让PC0到PC3全部输出低。 return KeyVal; }

主函数

复制int main(void) { uint8_t Key_value = 0; // 来到这里的时候,系统的时钟已经被配置成72M。 LED_Config(); BEEP_Config(); SysTick_InitUP(); //配置10us中断一次 USART_Config(); KEY_Init(); //矩阵按键代码测试 while (1) { Key_value = KEY_4_4_Scan(); if (Key_value != 0xFF) { Delay_ms(200); printf(“Key_value=%d\\r\\n”, Key_value); } Delay_ms(200); } }

实验现象

基于STM32F103单片机的矩阵按键设计-单片机矩阵键盘程序流程图2

猜你喜欢