4. Hi3861 UART串口通信驱动实现
任务说明
本案例在鸿蒙南向设备(以Hi3861为例)上,使用GPIO中断功能实现按键触发中断并处理。目标是通过中断方式替代轮询检测,提高按键响应效率。完成本案例后,按键按下时CPU不再持续查询引脚电平,而是由硬件中断唤醒处理函数执行相应逻辑。
硬件连接
- 按键一端接GPIO5(对应Hi3861的GPIO05),另一端接GND
- GPIO5配置为上拉输入,按键按下时引脚电平由高变低,产生下降沿中断
实现代码
#include <stdio.h>
#include <unistd.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "iot_gpio.h"
#include "iot_gpio_ex.h"
#include "iot_watchdog.h"
#define KEY_GPIO 5
#define TASK_STACK_SIZE 1024
#define TASK_PRIORITY 25
static volatile int g_keyPressCount = 0;
static volatile int g_interruptTriggered = 0;
/* 按键中断处理函数 */
static void KeyGpioInterruptHandler(char *arg)
{
(void)arg;
g_interruptTriggered = 1;
g_keyPressCount++;
printf("GPIO interrupt triggered, count=%d\n", g_keyPressCount);
}
/* 业务任务:处理中断标志 */
static void *KeyProcessTask(void *args)
{
(void)args;
while (1) {
if (g_interruptTriggered) {
g_interruptTriggered = 0;
/* 实际业务处理:此处可添加按键消抖、事件分发等逻辑 */
printf("Key pressed, processing...\n");
}
usleep(10000); /* 10ms轮询标志位,非阻塞 */
}
return NULL;
}
/* 按键中断初始化 */
static void KeyInterruptInit(void)
{
IoTWatchDogDisable();
/* 初始化GPIO5为上拉输入 */
IoTGpioInit(KEY_GPIO);
IoTGpioSetDir(KEY_GPIO, IOT_GPIO_DIR_IN);
IoTGpioSetPull(KEY_GPIO, IOT_GPIO_PULL_UP);
/* 注册中断:下降沿触发 */
IoTGpioRegisterIsrFunc(KEY_GPIO, IOT_INT_TYPE_EDGE, IOT_GPIO_EDGE_FALL_LEVEL_LOW,
KeyGpioInterruptHandler, NULL);
printf("Key interrupt initialized on GPIO%d\n", KEY_GPIO);
}
/* 创建业务处理任务 */
static void KeyTaskCreate(void)
{
osThreadAttr_t attr = {0};
attr.name = "KeyProcessTask";
attr.stack_size = TASK_STACK_SIZE;
attr.priority = TASK_PRIORITY;
if (osThreadNew((osThreadFunc_t)KeyProcessTask, NULL, &attr) == NULL) {
printf("Failed to create key process task\n");
}
}
/* 入口函数 */
static void KeyInterruptDemoEntry(void)
{
KeyInterruptInit();
KeyTaskCreate();
}
SYS_RUN(KeyInterruptDemoEntry);
代码说明
- 中断注册:
IoTGpioRegisterIsrFunc将GPIO5配置为下降沿触发中断,按键按下时硬件自动调用KeyGpioInterruptHandler。 - 中断处理:回调函数中仅设置标志位并计数,避免在中断上下文中执行耗时操作。
- 业务处理:独立任务
KeyProcessTask轮询标志位(10ms间隔),检测到中断后执行实际业务逻辑。该设计将中断处理与业务逻辑分离,符合嵌入式实时系统规范。
编译与烧录
- 将上述代码保存至
app/demo/src/key_interrupt_demo.c,并在BUILD.gn中添加该源文件。 - 在鸿蒙源码根目录执行
hb build编译固件。 - 使用HiBurn工具将生成的
Hi3861_wifiiot_app_allinone.bin烧录至开发板。
验证方法
- 烧录完成后,开发板串口输出
Key interrupt initialized on GPIO5,表明中断初始化成功。 - 按下按键(GPIO5接地),串口应立即输出
GPIO interrupt triggered, count=1,随后输出Key pressed, processing...。 - 连续多次按键,count值依次递增,每次按键均触发一次中断处理。
判定标准:每次按键均产生一次中断输出,且count计数与按键次数一致,说明中断方式按键处理功能正常。若按键无响应或计数异常,检查GPIO5接线及上拉配置是否正确。
中断触发时序
上图展示了按键中断的完整时序:按键按下产生下降沿,硬件触发中断回调置标志位;业务任务轮询到标志后执行处理,按键释放后电平恢复高电平,等待下一次按下。