3. Hi3861按键输入与LED响应
任务说明
本案例在OpenHarmony南向设备上实现按键控制LED:读取GPIO按键输入状态,每次按下按键时切换LED的亮灭状态。需要完成GPIO初始化、按键状态读取、消抖处理及LED状态翻转的完整逻辑。
硬件连接
硬件连接说明:
LED正极 → GPIO2(输出)
LED负极 → GND(串联220Ω限流电阻)
按键一端 → GPIO3(输入,启用内部上拉)
按键另一端 → GND
LED正极 → GPIO2(输出)
LED负极 → GND(串联220Ω限流电阻)
按键一端 → GPIO3(输入,启用内部上拉)
按键另一端 → GND
完整代码实现
创建文件 key_led_demo.c,代码如下:
#include <stdio.h>
#include <unistd.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "iot_gpio.h"
#include "iot_gpio_ex.h"
#define LED_GPIO 2 // LED 控制引脚
#define KEY_GPIO 3 // 按键输入引脚
#define KEY_PRESS_DOWN 0 // 按下为低电平(内部上拉)
static int g_led_on = 0; // 当前LED状态:0-灭,1-亮
/* 按键消抖延时 */
static void KeyDebounceDelay(void)
{
usleep(20000); // 20ms 消抖
}
/* 读取按键状态(带消抖) */
static int ReadKeyState(void)
{
if (IoTGpioGetInputVal(KEY_GPIO, NULL) == 0) {
return 0; // 读取失败,返回未按下
}
// 第一次读取
IotGpioValue val1 = IOT_GPIO_VALUE1;
IoTGpioGetInputVal(KEY_GPIO, &val1);
if (val1 != KEY_PRESS_DOWN) {
return 0; // 未按下
}
KeyDebounceDelay(); // 延时消抖
// 第二次读取确认
IotGpioValue val2 = IOT_GPIO_VALUE1;
IoTGpioGetInputVal(KEY_GPIO, &val2);
return (val2 == KEY_PRESS_DOWN) ? 1 : 0;
}
/* 切换LED状态 */
static void ToggleLed(void)
{
g_led_on = !g_led_on;
IoTGpioSetOutputVal(LED_GPIO, g_led_on ? IOT_GPIO_VALUE1 : IOT_GPIO_VALUE0);
printf("LED %s\n", g_led_on ? "ON" : "OFF");
}
/* 按键扫描任务 */
static void KeyScanTask(void)
{
while (1) {
if (ReadKeyState()) {
ToggleLed();
// 等待按键释放,防止连续触发
while (ReadKeyState()) {
usleep(10000);
}
}
usleep(10000); // 10ms 扫描周期
}
}
/* 初始化函数 */
static void KeyLedDemoInit(void)
{
// 初始化 GPIO
IoTGpioInit(LED_GPIO);
IoTGpioInit(KEY_GPIO);
// 设置LED为输出模式
IoTGpioSetDir(LED_GPIO, IOT_GPIO_DIR_OUT);
IoTGpioSetOutputVal(LED_GPIO, IOT_GPIO_VALUE0); // 初始LED灭
// 设置按键为输入模式,启用内部上拉
IoTGpioSetDir(KEY_GPIO, IOT_GPIO_DIR_IN);
IoSetPull(KEY_GPIO, IOT_GPIO_PULL_UP);
printf("Key LED demo initialized.\n");
// 创建按键扫描任务
osThreadAttr_t attr = {0};
attr.name = "KeyScanTask";
attr.stack_size = 4096;
attr.priority = osPriorityNormal;
if (osThreadNew(KeyScanTask, NULL, &attr) == NULL) {
printf("Failed to create task.\n");
}
}
SYS_RUN(KeyLedDemoInit);
代码说明
- GPIO初始化:LED引脚设为推挽输出,初始输出低电平(LED灭);按键引脚设为输入并启用内部上拉电阻,按键未按下时读到高电平,按下时读到低电平。
- 消抖处理:检测到按键第一次为低电平后延时20ms再次确认,避免机械抖动导致的误触发。
- 状态切换:确认按键按下后翻转LED输出状态,并等待按键释放后再继续扫描,防止长按连续切换。
- 任务调度:创建独立任务以10ms周期循环扫描按键状态,不阻塞主流程。
编译与烧录
- 将
key_led_demo.c放入设备应用的src目录,并在BUILD.gn中添加该源文件。 - 在
config.py或构建配置中确认目标芯片为Hi3861,执行编译命令:
python build.py wifiiot
- 编译完成后,使用HiBurn工具将生成的
Hi3861_wifiiot_app_allinone.bin烧录至开发板。
验证方法
烧录成功后,开发板上电运行,通过串口观察日志输出。验证步骤如下:
- 系统启动后,串口打印
Key LED demo initialized.,此时LED处于熄灭状态。 - 按下按键并释放,观察LED应点亮,串口打印
LED ON。 - 再次按下并释放按键,LED应熄灭,串口打印
LED OFF。 - 快速连续按键多次,每次按下释放LED状态都应翻转一次,无漏检或误触发。
判定标准:每次按键按下并释放后LED亮灭状态切换一次,串口输出与LED状态一致,且无抖动导致的多次翻转,即判定功能正常。