基于STM32F103单片机的矩阵按键设计

需要知识点
按键的原理
gpio输入输出
寄存器操作,如果学过51或者对c语言很熟练这里不存在问题。寄存器说白了就是操作他们的位(寄存器我理解就是一串羊肉串,让你找出你先吃哪个,比如我要吃中间的哪一个该怎么取出来)
矩阵按键原理
本实验使用stm32f103单片机,主题代码通用的。
如果每个按键占用一个gpio引脚,对于使用多个按键来说就是一种资源的浪费,因此当我们在设计时,可以考虑矩阵这种方式。本实验使用4*4也就是16个按键。
矩阵按键相对于独立按键稍微麻烦一点。4x4矩阵按键按照矩阵方式分别分为4行4列。主要有两种方式,一种是逐行扫描、一种是行列扫描。
原理图:
逐行扫描
通过在矩阵按键的每一条行线上轮流输出低电平,检测矩阵按键的列线,当检测到的列线不全为高电平的时候,说明有按键按下。然后,根据当前输出低电平的行号和检测到低电平的列号组合,判断是哪一个按键被按下。
行列扫描
首先,在全部行线上输出低电平,检测矩阵按键的列线,当检测到的列线不全为高电平的时候,说明有按键按下,并判断是哪一列有按键按下。
然后,反过来,在全部列线上输出低电平,检测矩阵按键的行线,当检测到的行线不全为高电平的时候,说明有按键按下,并判断是哪一行有按键按下。
最后,根据检测到的行号和检测的列号组合,以判断是哪一个按键被按下。
按键检测说白了就是按键按下之后是不是导通的,而其他没有按下的按键是没有导通的,代码也不唯一,是多种多样的。这里就需要操作寄存器或者使用库函数的位操作。
流程
矩阵按键程序实现
根据是国内棉矩阵按键电路图,编写矩阵按键应用程序,轮徇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); }}实验现象

联想首款自研工业机器人亮相,AR技术加持具备两种模式
关于RISC-V发展现状与应用分析和介绍
造车新势力不只是涨价还要造手机?
关于光纤熔接过程六大问题的详细剖析
瑞士斯沃琪将推手表操作系统 与谷歌和苹果手表竞争市场
基于STM32F103单片机的矩阵按键设计
详谈分布式系统的定义及属性
COMWIN仪器设备电源及供电注意事项及常见问题
AIoT生态系统走上云端 资源共享强化竞争力
iPhone8续航能力怎么样?续航测试大反转,让三星note8无地自容
英特尔推出了Pohoiki Beach模拟芯片集群
石头扫地机器人T6用起来怎么样
天数智芯与百度联合发起飞桨+文心大模型硬件生态共创计划
高精准UWB室内定位系统的详细介绍
电子芯闻早报:英特尔领投机器人厂商Savioke
如何保障高镍化趋势下的动力电池安全性?
黑客初步成功破解PS5的镜像游戏
广汽集团9月销售汽车24.36万辆,新能源汽车同比增长70.36%
谷歌发布针对Android2.2操作系统的软件开发工具包Fr
今年手机出货量或是十年来最低水平