农村四月闲人少,勤学苦攻把名扬。这篇文章主要讲述基于鸿蒙OS的按键驱动相关的知识,希望能为你提供帮助。
按键作为常用的输入系统,如何准确并高效的获取按键值,是一个经常要面对的问题,今天我们看看在鸿蒙系统中,如何得到独立按键的按键值。
实现目标
我们这次以Hi3861核心板左下角的USER按键S2为例,当按键按下时,通过USB Type-c对应的串口输出信息。
按键S2在实物中的对应关系如下图黄线所示:
文章图片
按键原理图
核心板左下角的按键S2的原理图如下:
文章图片
当S2被按下之后,GPIO05与GND相连,此时GPIO05输入为低电平。
代码实现
实现方式一:读取输入IO的状态
#include <
stdio.h>
#include <
unistd.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "wifiiot_gpio.h"
#include "wifiiot_gpio_ex.h"
#include "wifiiot_errno.h"static void Key_Task(const char* arg)
{
(void)arg;
printf("Enter the Key_Task ... \\n");
while (1)
{
WifiIotGpioValue wigv;
GpioGetInputVal(WIFI_IOT_IO_NAME_GPIO_5,&
wigv);
if (wigv == WIFI_IOT_GPIO_VALUE0)
{
usleep(10*1000);
//10mswhile(1)
{
GpioGetInputVal(WIFI_IOT_IO_NAME_GPIO_5,&
wigv);
if (wigv == WIFI_IOT_GPIO_VALUE1){
printf("[DEMO] GPIO05 Low level.\\n");
break;
}
}
}
}return;
}static void KeyExampleEntry(void)
{
unsigned int ret = 0;
GpioInit();
iosetFunc(WIFI_IOT_IO_NAME_GPIO_5, WIFI_IOT_IO_FUNC_GPIO_5_GPIO);
GpioSetDir(WIFI_IOT_GPIO_IDX_5, WIFI_IOT_GPIO_DIR_IN);
if (ret != WIFI_IOT_SUCCESS)
{
printf("===== ERROR ======gpio ->
GpioSetDir ret:%d\\r\\n", ret);
return;
}osThreadAttr_t attr = {0};
attr.name = "Key_Task";
attr.attr_bits = 0U;
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.stack_mem = NULL;
attr.stack_size = 1024;
attr.priority = osPriorityNormal;
if(osThreadNew((osThreadFunc_t)Key_Task,NULL,&
attr) == NULL)
{
printf("Failed to create Key_Task !\\n");
}
}SYS_RUN(KeyExampleEntry);
编译代码:
python build.py wifiiot
文章图片
更新固件之后重启最小系统板,打开串口助手,点击核心板上的USER按键S2,串口助手输出信息如下:
文章图片
注意:
此实例新建了一个任务用于循环读取按键的状态,KeyExampleEntry作为应用程序的入口函数,不能随意使用while(1)这种耗时的操作,必须快速返回,否则会妨碍鸿蒙OS中其他应用程序的运行,因此,在这个入口函数中创建一个按键状态监测的专属任务(线程)用于判断按键的状态。
GPIO中断通过上面的原理图我们可知,当按键S2没有被按下的时候,GPIO05为默认状态高电平,当按键S2被按下时,GPIO05与GND相连,GPIO05被拉低,当松开按键S2的时候,GPIO05又恢复高电平。
在此过程中,当按键S2被按下时,GPIO05会收到一个由高到低的电平变化,我们称这个过程为下降沿;当按键S2被松开时,GPIO05会收到一个由低到高的电平变化,我们称这个过程为上升沿。
综上所述,在不考虑抖动影响的前提下,每次按键被按下,GPIO05将会收到一个下降沿;按键被释放,GPIO05会收到一个上升沿。
我们在GPIO05这个引脚上注册一个边沿触发函数(上升沿或者下降沿触发都可以),那么这个注册的边沿触发回调函数被调用一次,理论上就是有一次按键的动作发生。
#include <
stdio.h>
#include <
unistd.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "wifiiot_gpio.h"
#include "wifiiot_gpio_ex.h"
#include "wifiiot_errno.h"/* gpio callback func */
void gpio5_isr_func(char *arg)
{
(void)arg;
printf("----- gpio05 isr success -----\\r\\n");
}static void KeyExampleEntry(void)
{
unsigned int ret = 0;
GpioInit();
IoSetFunc(WIFI_IOT_IO_NAME_GPIO_5, WIFI_IOT_IO_FUNC_GPIO_5_GPIO);
GpioSetDir(WIFI_IOT_GPIO_IDX_5, WIFI_IOT_GPIO_DIR_IN);
//IoSetPull(WIFI_IOT_GPIO_IDX_5,WIFI_IOT_IO_PULL_UP);
if (ret != WIFI_IOT_SUCCESS)
{
printf("===== ERROR ======gpio ->
GpioSetDir ret:%d\\r\\n", ret);
return;
}
ret = GpioRegisterIsrFunc(WIFI_IOT_GPIO_IDX_5,WIFI_IOT_INT_TYPE_EDGE,WIFI_IOT_GPIO_EDGE_RISE_LEVEL_HIGH, gpio5_isr_func, NULL);
if (ret != WIFI_IOT_SUCCESS)
{
printf("===== ERROR ======gpio ->
hi_gpio_register_isr_function ret:%d\\r\\n", ret);
}
}SYS_RUN(KeyExampleEntry);
代码说明:
- WIFI_IOT_IO_NAME_GPIO_5是与按键S2相连的GPIO,要实现按键中断捕获,需要先使用IoSetFunc() 函数进行端口功能重定义;
- 调用GpioSetDir()函数,设置GPIO05为输入,并通过IoSetPull() 函数将端口设置为上拉输入(Pull Up);
- 调用GpioRegisterIsrFunc()函数,完成GPIO05和回调函数gpio5_isr_func()的注册绑定,设置触发模式为上升沿触发:WIFI_IOT_GPIO_EDGE_RISE_LEVEL_HIGH,当按键S2被抬起的时候,产生上升沿,触发回调函数gpio5_isr_func()工作。
文章图片
通过上面两种方式,我们学会了独立按键状态的获取、鸿蒙系统中如何创建任务和外部中断的使用,利用此代码,我们还可以用于识别热释红外传感器的响应信号。
资料获取
公众号留言区置顶留言获取本文相关代码。
ps: 文章首发于电子发烧友。
小哈有话说
最近在鸿蒙交流群中看到下面一大批开发板要移植鸿蒙操作系统了,等到这些厂商将板卡移植好了,那么鸿蒙就真的成气候了,作为一个嵌入式开发者,学习一个实时操作系统是必不可少的,学什么都是学,为什么不学一个有前途的呢?
文章图片
欢迎关注
【基于鸿蒙OS的按键驱动】程序员小哈带你玩转嵌入式,微信搜索:嵌入式从0到1,更多干货等着你。
推荐阅读
- 中断 Hwi(提高鸿蒙轻内核系统实时性及执行效率的秘密武器)
- 鸿蒙开源第三方组件——自定义图片缩放组件PinchImageView-ohos
- 鸿蒙第三方组件——SwipeCaptcha滑动拼图验证组件
- 鸿蒙编译构建丨hb工具分析
- 鸿蒙内核源码分析(源码注释篇) | 鸿蒙必定成功,也必然成功 | 百篇博客分析HarmonyOS源码
- 鸿蒙开源第三方组件——日期和时间处理组件JodaTime-ohos
- Spring Bean定义的加载解析过程之注解的过程
- Java ASM系列((051)opcode: constant)
- 如何在Android中使用JSCH(SFTP)将文件上传到服务器