电子工程师技术服务社区
公告
登录
|
注册
首页
技术问答
厂商活动
正点原子
板卡试用
资源库
下载
文章
社区首页
文章
一个ADC实现多个按键检测
分 享
扫描二维码分享
一个ADC实现多个按键检测
鸿蒙
Harmony
ADC
嵌入式从0到1
关注
发布时间: 2020-11-16
丨
阅读: 2380
### 获取按键值的方式 按键作为常用的输入系统,如何准确并高效的获取按键值,是一个经常要面对的问题,常用的按键检测方式有如下几种方式: ##### 1. 独立按键 每个按键的检测占用单片机的一个GPIO引脚,原理图如下图所示: ![图片来源程序员小哈自制核心板原理图](https://img-blog.csdnimg.cn/20201114094657894.png?#pic_center) 我们以BTN1按键为例,当按键没有按下的时候,网络标号KEY1处的电压被10K的上拉电阻拉至3.3V,PB14(KEY1)引脚设为输入引脚后,程序中读取该引脚的值将为1,当按键按下之后,网络标号KEY1处接地,读取该输入引脚的值将为0,进而通过此电路实现的独立按键,可以区分按键弹起和按下两种不同的状态。 独立按键的每个按键的工作不会影响其他I/O的状态。独立按键缺点是浪费MCU管脚,优点是编程比较简单。 独立按键的实现原理详见我们之前分享的网文: [**基于鸿蒙OS的按键驱动**](https://mp.weixin.qq.com/s/Ddb4h6EnlYI5yn45_qIQSA) ##### 2. 矩阵按键 矩阵按键又称为矩阵键盘或称行列键盘,其实现的原理我们之前分享过如下网文: [矩阵键盘的行列扫描原理详解](https://mp.weixin.qq.com/s/pntm2KrtqRZtvet7ABXKlw) 这种行列式键盘结构能有效地提高单片机系统中I/O口的利用率。在MCU管脚有限的情况下,矩阵按键大大的节省了I/O资源。 ##### 3. ADC分压键盘 利用电阻串联分压的原理实现一个ADC管脚去检测多个按键。 按键被按下之后,与ADC引脚相连的点的电压会随着参与分压的电阻变化而变化,我们只要让每个按键按下之后的电压处于不同的区间,我们理论上就能够将各个按键区分开。 为了避免由于ADC精度、电阻的误差或者温漂等因素造成的按键检测失效,提高按键检测的可靠性,我们可以减少按键数量,适当放宽各个按键检测的电压范围。 经过上面的分析,独立按键的方式是最浪费GPIO口,矩阵按键的效率适中,而ADC分压实现的键盘使用的GPIO引脚最少。 ### ADC检测按键原理 ![](https://img-blog.csdnimg.cn/20201114094748598.png?#pic_center) 如果Vcc = 3.3V ,那么没有按键被按下时,ADC为3.3V,如果有按键被按下: | **被按下的按键** | **ADC值** | | :---: | :---: | | Key1 | 0 V | | Key2 | 1.65 V | | Key3 | 2.2 V | | Key4 | 2.475 V | | Key5 | 2.64 V | | Key6 | 2.75 V | 我们由上可以看到,一串相同电阻(10K)组成的多个按键,相连按键之间的电压差越来越小,不利于继续进行扩展。 ![](https://img-blog.csdnimg.cn/20201114094810522.png?#pic_center) 如果 +5V 换成 3.3V ,那么没有按键被按下时,ADC为3.3V,如果有按键被按下: | **被按下的按键** | **ADC值** | | :---: | :---: | | sw1 | 0 V | | sw2 | 0.163 V | | sw3 | 0.503 V | | sw4 | 0.819 V | | sw5 | 1.157 V | | sw6 | 1.487 V | 由上我们看出,这组电阻组成的多个按键检测电路,相连按键之间的电压差值基本在0.3V左右,可以在此电路基础上继续进行扩展,设计成更多的按键扫描电路。 有了上面的经验,大家算一下下图中,不同按键按下的话,ADC的值应该为多少呢? ![](https://img-blog.csdnimg.cn/20201114094830371.png?#pic_center) ### 按键原理图 ![](https://img-blog.csdnimg.cn/20201114094847153.png?#pic_center) 核心板左下角的按键S2的原理图: ![](https://img-blog.csdnimg.cn/20201114094900364.png?#pic_center) OLED板上的按键1和按键2的原理图: ![](https://img-blog.csdnimg.cn/20201114094912439.png?#pic_center) 由上面两个原理图可知,三个按键都是与GPIO05这个引脚相连,根据上面ADC分压的原理我们可知,当三个按键按下时,GPIO05处的理论电压如下: | **被按下的按键** | **理论电压** | | :---: | :---: | | 常态(没有按键按下时) | 3.3 V | | S2(核心板) | 0V | | S1(OLED) | (1/(4.7+1))\*3.3=0.579 V | | S2(OLED) | (2/(4.7+1+1))\*3.3=0.985 V | ### 获取ADC值 官方手册ADC功能描述如下: ![](https://img-blog.csdnimg.cn/20201114094929990.png?#pic_center) ##### 1. 引脚初始化 ![](https://img-blog.csdnimg.cn/20201114094949222.png?#pic_center) 由于GPIO5默认被复用为串口引脚,我们这里要想使用ADC功能,而上图表格中没有对应的ADC复用信号,所以我们只需要将GPIO_05设为普通GPIO输入引脚即可。初始化代码如下: ```C (hi_void)hi_gpio_init(); hi_io_set_func(HI_IO_NAME_GPIO_5, HI_IO_FUNC_GPIO_5_GPIO); ret = hi_gpio_set_dir(HI_GPIO_IDX_5, HI_GPIO_DIR_IN); if (ret != HI_ERR_SUCCESS) { printf("=====ERROR======gpio -> hi_gpio_set_dir1 ret:%d\r\n", ret); return; } ``` ##### 2. 获取ADC值 这里使用hi_adc_read函数获取adc的值,为了使得到的数据相对准确,我们对数据进行多次采集,然后将得到的数据缓存到数组中,然后再对数组中的数据进行集中处理。 ```C memset_s(g_adc_buf, sizeof(g_adc_buf), 0x0, sizeof(g_adc_buf)); for (i = 0; i < ADC_TEST_LENGTH; i++) { ret = hi_adc_read((hi_adc_channel_index)HI_ADC_CHANNEL_2, &data, HI_ADC_EQU_MODEL_1, HI_ADC_CUR_BAIS_DEFAULT, 0); if (ret != HI_ERR_SUCCESS) { printf("ADC Read Fail\n"); return; } g_adc_buf[i] = data; } ``` 其中函数hi_adc_read在如下文件中实现: \vendor\hisi\hi3861\hi3861\platform\drivers\adc\hi_adc.c ![](https://img-blog.csdnimg.cn/20201114095013447.png?#pic_center) ##### 3. 对数组中的ADC值进行数据处理,计算方法为取这些数据的和,然后减去其中的最大值和最小值,然后再取平均值。 ```C hi_u32 i; float vlt_max = 0; float vlt_min = VLT_MIN; float vlt_sum = 0; float vlt_val = 0; hi_u16 vlt; for (i = 0; i < data_len; i++) { vlt = g_adc_buf[i]; float voltage = hi_adc_convert_to_voltage(vlt); vlt_max = (voltage > vlt_max) ? voltage : vlt_max; vlt_min = (voltage < vlt_min) ? voltage : vlt_min; vlt_sum += voltage; } vlt_val = (vlt_sum - vlt_min - vlt_max) / (data_len - 2.0); ``` 其中函数hi_adc_convert_to_voltage的实现位于:\vendor\hisi\hi3861\hi3861\platform\drivers\adc\hi_adc.c ![](https://img-blog.csdnimg.cn/20201114095027766.png?#pic_center) ### 串口打印输出 为了按键能够准确识别,我们首先要知道各个按键被按下时,ADC的值的范围,我们在程序中获取GPIO5 引脚处的ADC值,利用下面的函数进行打印输出,进而观察各种状态下,ADC的值是多少: ```C printf("KEY adc value is %f \r\n",key_adc_value); ``` 具体打印输出如下: ##### 1. 常态没有按键按下时,ADC值的范围在 3.262 ~ 3.266之间,串口打印输出如下: ![](https://img-blog.csdnimg.cn/20201114095048422.png#pic_center) ##### 2. 当按下按键S2(核心板)时,ADC值的范围在 0.214 ~ 0.218之间,串口打印输出如下: ![](https://img-blog.csdnimg.cn/20201114095101285.png#pic_center) ##### 3. 当按下按键S1(OLED)时,ADC值的范围在 0.569 ~ 0.573之间,串口打印输出如下: ![](https://img-blog.csdnimg.cn/20201114095108803.png#pic_center) ##### 4. 当按下按键S2(OLED)时,ADC值的范围在 0.970 ~ 0.974之间,串口打印输出如下: ![](https://img-blog.csdnimg.cn/20201114095118229.png#pic_center) ##### 5. 结果汇总 | **被按下的按键** | **理论电压** | **实际电压** | | :---: | :---: | :---: | | 常态(没有按键按下时) | 3.3 V | 3.266 V | | S2(核心板) | 0V | 0.214 V | | S1(OLED) | (1/(4.7+1))\*3.3=0.579 V | 0.573 V | | S2(OLED) | (2/(4.7+1+1))\*3.3=0.985 V | 0.973 V | 由上可以看出,理论值跟实际值偏差不是很大,而且值相对稳定,我们只需要在实际值基础上增加一个偏差,比如0.15 V,即可区分出板子上的三个按键。 | **被按下的按键** | **理论电压** | **实际电压** | **判断区间** | | :---: | :---: | :---: | :---: | | 常态(没有按键按下时) | 3.3 V | 3.266 V | vlt_val > 3 V | | S2(核心板) | 0V | 0.214 V | vlt_val < 0.3 V | | S1(OLED) | 0.579 V | 0.573 V | 0.4 V < vlt_val < 0.7 V | | S2(OLED) | 0.985 V | 0.973 V | 0.8 V < vlt_val < 1.1 V | ##### 6. 按adc值的范围区间,判断按键值 具体判断的实现如下: ```C if(vlt_val < 0.3)) { if(key_flag == 0) { key_flag = 1; key_status = KEY_EVENT_S2_CORE; } } if((vlt_val > 0.4) && (vlt_val < 0.7)) { if(key_flag == 0) { key_flag = 1; key_status = KEY_EVENT_S1_OLED; } } if((vlt_val > 0.8) && (vlt_val < 1.1)) { if(key_flag == 0) { key_flag = 1; key_status = KEY_EVENT_S2_OLED; } } if(vlt_val > 3.0) { key_flag = 0; key_status = KEY_EVENT_NONE; } ``` ##### 7. 编译脚本文件BUILD.gn 工程中两个编译使用的BUILD.gn脚本文件具体实现如下图所示: ![](https://img-blog.csdnimg.cn/20201114095132568.png?#pic_center) ### 获得HiBurn软件 ##### 1. 解压DevEcoDeviceTool-1.0.0.zip ![](https://img-blog.csdnimg.cn/2020111409514455.png#pic_center) 此文件,在下面网文中分享过,可以自提: [HarmonyOS智能设备开发工具—DevEco Device Tool 安装配置](https://mp.weixin.qq.com/s/C8yk8s3ega6T6iC_Abj7TQ) ##### 2. 将解压后生成的.vsix文件重命名为.zip结尾的任意名称,比如:DevEcoDeviceTool-1.0.0-temp.zip , 然后解压此文件。 ![](https://img-blog.csdnimg.cn/20201114095155661.png?#pic_center) ##### 3. 在 \devicetool-device-1.0.0.0\extension\deveco\tools 文件夹下即有HiBurn.exe 文件。 ![](https://img-blog.csdnimg.cn/20201114095211598.png#pic_center) ### 使用HiBurn烧写.bin文件至Hi3861 1. 双击HiBurn.exe文件,在弹出界面中,选择菜单:Setting-->Com settings ,在弹出窗口中,Baud选择一个稍微高点的波特率,加快文件传输速度; ![](https://img-blog.csdnimg.cn/2020111409522350.png?#pic_center) 2. 选择Hi3861核心板对应的串口,点击“Select file”按钮,选择要下载的固件文件:Hi3861_wifiiot_app_allinone.bin,我们打开此文件之后,会发现下面列表中出现了三个文件,实际上这个.bin文件由列表中的三个文件组成。勾选“Auto burn”复选框,然后选择“Connect”按钮,进入如下待下载界面: ![](https://img-blog.csdnimg.cn/20201114095236679.png?#pic_center) 3. 复位核心板模块,进入下载模式,下载完成后点击“Disconnect”按钮断开连接。 ![](https://img-blog.csdnimg.cn/2020111409525067.png?#pic_center) ### 和DevEco Device Tool方式对比 使用HiBurn烧录相对于VSCode中使用DevEco Device Tool烧录而言,好处主要有以下几点: ##### 1. 不依赖VSCode,所以下面网文的配置过程可以省略了; [HarmonyOS智能设备开发工具—DevEco Device Tool 安装配置](https://mp.weixin.qq.com/s/C8yk8s3ega6T6iC_Abj7TQ) ##### 2. 下载速度更快,HiBurn.exe最大波特率可以设置到4000000,而DevEco Device Tool最大只能为921600,是它的4.34倍; ![](https://img-blog.csdnimg.cn/2020111409530878.png?#pic_center) HiBurn方式烧录的缺点主要是: ##### 1. 烧录完成标志不是很明显,需要认真观察; ##### 2. 烧录完成之后需要手动点Disconnect,主动断开连接,否则将一直占用此串口;如果再未断开的情况下,再次按了一下RESET按键,HiBurn软件将会再一次对固件进行烧录。 ### 结果展示 依次按三次Hi3861开发套件上的三个按键S2(CORE)、S1(OLED)、S2(OLED),串口打印输出如下: ![](https://img-blog.csdnimg.cn/2020111409532899.png?#pic_center) ADC获取的电压波动在我们设定的范围内,所以我们看到能够正确的识别对应的按键。 ### 小结 学习实现的思想,自己可以使用自己的板子实现一下,无论51单片机还是STM32作为主控,实现的原理都是一样的,文中提供的代码,除了获取ADC值的方式不一样外,其他代码都是可以通用参考的。 ### 参考网文 https://bbs.elecfans.com/jishu_2000829_1_1.html ### 资料获取 公众号**留言区置顶留言**获取本文使用的HiBurn.exe软件及示例源码。 ps: 文章首发于电子发烧友。 ### 欢迎关注 程序员小哈带你玩转嵌入式,微信搜索:**嵌入式从0到1**,更多干货等着你。 ![](https://img-blog.csdnimg.cn/20201114095347796.png?#pic_center)
原创作品,未经权利人授权禁止转载。详情见
转载须知
。
举报文章
点赞
(
0
)
嵌入式从0到1
关注
评论
(0)
登录后可评论,请
登录
或
注册
相关文章推荐
MK-米客方德推出工业级存储卡
Beetle ESP32 C3 蓝牙数据收发
Beetle ESP32 C3 wifi联网获取实时天气信息
开箱测评Beetle ESP32-C3 (RISC-V芯片)模块
正点原子数控电源DP100测评
DP100试用评测-----开箱+初体验
Beetle ESP32 C3环境搭建
【花雕体验】16 使用Beetle ESP32 C3控制8X32位WS2812硬屏之二
X
你的打赏是对原创作者最大的认可
请选择打赏IC币的数量,一经提交无法退回 !
100IC币
500IC币
1000IC币
自定义
IC币
确定
X
提交成功 ! 谢谢您的支持
返回
我要举报该内容理由
×
广告及垃圾信息
抄袭或未经授权
其它举报理由
请输入您举报的理由(50字以内)
取消
提交