完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
STM32的矩阵键盘扫描及处理
前言 由于最近帮做一个毕业设计需要用到直接输入目标值去控制输出,所以才写这么一个按键处理的程序。对于一个才接触单片机没多久的大学生菜鸟来说,实现毕设里的每一项功能都有一定的挑战。接下来就分享一下我在写这按键扫描及处理中的一些经验吧。 整个工程所需要的输出值可通过键盘任意控制,有一位小数。 一、按键扫描 1.矩阵按键的原理图 矩阵键盘原理图示意图,具体键值根据自己需求设置 2、按键扫描代码 总体思路:先设置两个初始化函数,KeyPad_Init1()是高四位初始化为下拉输入、低四位为上拉输入(相当于就是给高四位低电平,低四位为高电平);KeyPad_Init2()是高四位初始化为上拉输入、低四位为下拉输入(相当于就是给高四位高电平,低四位为高电平)。程序首先使用KeyPad_Init1(),如果读取低8位引脚不是0x0f,就说明有按键被按下,然后短暂延时消抖后再次检测到低8位引脚不是0x0f,就储存高四位的的值然后进行初始化KeyPad_Init2(),然后又读取低8位引脚不是0x0f,储存其中的低四位的值,然后将高低四位值加起来就对应了一个键值。 在这段扫描程序里面,由于扫描出的键值后面还需要处理,所以只有当有键按下后才返回才是有效的键值,没有按键按下就返回的是个无效值-1,目的是为了对每一次按键按下值进行处理,没有按下就不去处理。 //函数名:扫描函数 //返回值:有效键值或-1 //功能:矩阵按键扫描,返回一个值 short KeyPad_Scan(void) { short num = -1; //保持按键值返回 u16 readvalue = 0; u16 re=0; u16 re1=0; u16 re2=0; KeyPad_Init1(); //低4位引脚上拉输入,高4位引脚下拉输入 readvalue = GPIO_ReadInputData(GPIOA); //读GPIOA引脚电平 readvalue &= 0x00ff; //保留低8位的值(PA7-PA0) if(readvalue != 0x000f) //高4位引脚有一个被按下 { delay_ms(10);//消抖10ms readvalue = GPIO_ReadInputData(GPIOA); //读GPIOA引脚电平 if(readvalue != 0x000f) { re1 = GPIO_ReadInputData(GPIOA); //再次读取状态 re1 &= 0x00f0; //保留PA4-PA7的值 KeyPad_Init2(); //低4位引脚下拉输入,高4位引脚上拉输入 delay_ms(50);//经我测试,这里延迟50ms反应最快而很少出现不反应的状况 re2 = GPIO_ReadInputData(GPIOA); //再次读取状态 re2 &= 0x000f; //保留PA0-PA3的值 re=re1|re2; //相与,就知道哪一行哪一列被按下啦 switch(re) { case 0x0011: num = 12;break; case 0x0012: num = 8;break; case 0x0014: num = 4;break; case 0x0018: num = 0;break; case 0x0021: num = 13;break; case 0x0022: num = 9;break; case 0x0024: num = 5;break; case 0x0028: num = 1;break; case 0x0041: num = 14;break; case 0x0042: num = 10;break; case 0x0044: num = 6;break; case 0x0048: num = 2;break; case 0x0081: num = 15;break; case 0x0082: num = 11;break; case 0x0084: num = 7;break; case 0x0088: num = 3;break; } return num; } } return -1; } 二、键值处理 1、键值处理代码 在这段程序中我要的是按下【确定】键按下后返回确定键按下前所输入的键值(0-99.9),返回更高的值也行,不过小数点后面只能有一位数。 /**************** //按键值处理函数,返回最后需要的目标值, 返回-1,按键没有按下 返回-2或0,有按键按下,无效可适当延时 返回其他,键值处理后的值 *******************/ float Key_value_processing(void) { float key=0.0; int key_flag = -1; static int key2 = 0; //按键扫描返回值暂存处 static u8 key1 = 0; static int Point_flag=0; //判断‘.’是否按下标志,(Point_flag=2表示按下,Point_flag=1表示按下后进行了一次小数后一位赋值) static int key1_temp = 0; //缓存key1值 key_flag=KEYPAD_Scan(); // if(-1 == key_flag) //如果按键没有按下 { return -1; } else if(0 <= key_flag && key_flag <= 9) //返回数字键,根据小数点是否按下,对数字进行 { key1 = key_flag+key1*10; //如有多位值,进行累加 key1_temp = key1; if(2 == Point_flag) { printf("xiaoshudianhou:%d rn",key1); OLED_ShowNum(103,16,key1,1,16); OLED_Refresh(); Point_flag = 1; } else if(1 == Point_flag) //点按下 { key1=key_flag; } else { printf("shuqian:%d rn",key1); OLED_ShowNum(63,16,key1,2,16); OLED_Refresh(); } return -2; } /***无效按键**/ else if(10 <= key_flag && key_flag <= 13) //暂时没有用的值,不处理 { printf("无效值::%d rn",key_flag); return -2; } else if(Point == key_flag) // { key2 = key1_temp; Point_flag=2; key1=0; printf("float-----rn"); OLED_ShowString(83,16,":",16); OLED_Refresh(); return -2; } else if(Sure == key_flag) //确定键按下后,返回处理好的值 { if(1==Point_flag) { key = key2 + (float)key1/10.0; Point_flag=0; } else { key=key1; } printf(":%f rn",key); key_flag = -1,key1 = 0,key2 = 0; return key; } return -1; } 三、总结 学习这个专业来第一次对自己所学的知识进行总结,虽然是一个做完后看起来很简单的一个知识点,在键值处理的过程中还是遇到了很多的问题。多亏了学长的帮忙才算比较轻松的完成了。这其中发现了自己以前很多的盲点,比如对于数据类型把握得不是很清楚,还有就是if else语句与if if语句的使用,在这之前写有关单片机的代码都是只用if语句,没考虑到当有多个条件时可以用if else语句可以有更快地执行效率。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1909 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1678 浏览 1 评论
1171 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
770 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1730 浏览 2 评论
1970浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
807浏览 4评论
stm32f4下spi+dma读取数据不对是什么原因导致的?
254浏览 3评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
624浏览 3评论
634浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-23 19:55 , Processed in 0.609087 second(s), Total 43, Slave 38 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号