鸿蒙LiteOS GPIO轮询模式实战教程:电平读取与上升沿检测
B站 配套视频【鸿蒙 LiteOS 实战 11】GPIO轮询模式实战教程
一、前言
在鸿蒙LiteOS嵌入式开发中,GPIO分为轮询模式 和中断模式 两种常用开发方式。
对于入门学习、低速按键检测、普通电平状态采集这类简单场景,GPIO轮询模式逻辑简单、上手无门槛、无需理解中断复杂机制,是新手必学的基础用法。
本文基于RK2206开发板+OpenHarmony LiteOS,手把手讲解GPIO轮询原理、完整源码、电平检测、上升沿识别,代码可直接编译烧录使用,适合嵌入式鸿蒙零基础入门学习。
二、什么是GPIO
GPIO 全称 General Purpose Input Output,即通用输入输出口,可以理解为单片机对外的引脚接口:
- 配置为输入模式:读取外部高低电平,常用于按键、传感器信号采集;
- 配置为输出模式:输出高低电平,常用于控制LED、继电器、蜂鸣器。
本文只讲解GPIO输入轮询模式,重点实现引脚电平循环读取与上升沿事件检测。
三、什么是GPIO轮询模式
轮询模式核心逻辑:
在任务死循环中,周期性不断读取GPIO引脚电平,通过前后电平对比,判断电平变化、识别上升沿/下降沿。
优点:
- 逻辑简单,无需掌握中断机制;
- 配置流程少,代码通俗易懂;
- 适合低速、低实时性的普通场景。
缺点:
- 需要任务持续循环运行,占用CPU资源;
- 轮询间隔设置不合理时,容易漏掉快速电平跳变;
- 不适合高频信号、高精度按键检测场景。
四、基础概念:上升沿与下降沿
- 低电平:逻辑0,近似0V;
- 高电平:逻辑1,近似3.3V。
- 上升沿:低电平0 → 高电平1 的瞬间跳变,对应按键按下、传感器信号生效;
- 下降沿:高电平1 → 低电平0 的瞬间跳变,对应按键松开、传感器信号失效。
轮询模式通过记录上一次电平 + 对比当前电平,即可软件模拟检测边沿跳变。
五、完整实战源码(GPIO轮询+上升沿检测)
c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include "los_task.h"
#include "ohos_init.h"
#include "lz_hardware.h"
#define GPIO_TEST GPIO0_PC5
/* 轮询上升沿触发计数 */
static unsigned int m_gpio_poll_count = 0;
/* 记录上一次引脚电平 */
static unsigned int last_level = 0;
/***************************************************************
* 函数名称: gpio_process
* 说 明: gpio轮询任务:循环读取电平、检测上升沿
* 参 数: 无
* 返 回 值: 无
***************************************************************/
void gpio_process()
{
LzGpioValue cur_level;
/* 初始化引脚为GPIO */
LzGpioInit(GPIO_TEST);
/* 引脚复用配置为GPIO功能 */
PinctrlSet(GPIO_TEST, MUX_FUNC0, PULL_KEEP, DRIVE_LEVEL0);
/* 引脚配置为输入模式 */
LzGpioSetDir(GPIO_TEST, LZGPIO_DIR_IN);
while (1)
{
printf("***************GPIO Polling Example*************\n");
// 读取当前GPIO引脚电平
LzGpioGetVal(GPIO_TEST, &cur_level);
printf("gpio current level = %d\n", cur_level);
// 软件检测上升沿:上一次低电平,当前高电平
if (last_level == 0 && cur_level == 1)
{
m_gpio_poll_count++;
printf("检测到上升沿事件,累计次数:%d\n", m_gpio_poll_count);
}
// 更新历史电平,用于下一次对比
last_level = cur_level;
printf("\n");
// 轮询间隔200ms,降低CPU占用
usleep(200000);
}
}
/***************************************************************
* 函数名称: gpio_pool_example
* 说 明: 开机自启动创建GPIO轮询任务
* 参 数: 无
* 返 回 值: 无
***************************************************************/
void gpio_pool_example()
{
unsigned int thread_id;
TSK_INIT_PARAM_S task = {0};
unsigned int ret = LOS_OK;
task.pfnTaskEntry = (TSK_ENTRY_FUNC)gpio_process;
task.uwStackSize = 2048;
task.pcName = "gpio process";
task.usTaskPrio = 24;
ret = LOS_TaskCreate(&thread_id, &task);
if (ret != LOS_OK)
{
printf("Falied to create task ret:0x%x\n", ret);
return;
}
}
APP_FEATURE_INIT(gpio_pool_example);
六、代码逻辑解析
1. GPIO初始化流程
LzGpioInit:初始化指定GPIO引脚硬件时钟与基础配置;PinctrlSet:配置引脚复用功能为普通GPIO,设置上下拉、驱动能力;LzGpioSetDir:将引脚设置为输入模式,用于读取外部电平。
2. 轮询检测逻辑
- 在while(1)死循环中,周期性调用
LzGpioGetVal读取引脚当前电平; - 用变量
last_level保存上一次循环的电平状态; - 通过
last_level == 0 && cur_level == 1软件判断上升沿跳变; - 检测到上升沿后计数累加并打印提示;
- 加入
usleep(200000)设置200ms轮询间隔,避免CPU空转占用资源。
七、串口运行打印效果

当外部引脚电平从低变高时,会自动识别上升沿并累加计数。
八、轮询模式适用场景与局限
适用场景
- 新手入门学习GPIO基础配置;
- 低速按键状态检测;
- 普通传感器稳态电平采集;
- 对实时性要求不高的简单IO检测。
局限性
- 循环轮询占用CPU资源,不利于低功耗设计;
- 轮询间隔过大时,会丢失快速的电平跳变;
- 无法做到硬件级实时响应,高精度按键、高频信号不推荐使用。
九、总结
- GPIO轮询模式通过循环读取电平+软件对比,即可实现电平状态与上升沿检测;
- 配置流程简单、无中断复杂逻辑,非常适合鸿蒙LiteOS嵌入式新手入门;
- 轮询模式仅适合低速低实时性场景,高精度、高实时性需求建议使用GPIO中断模式;
- 本文源码可直接在RK2206开发板上编译运行,可自行修改引脚、轮询间隔适配项目需求。