gpio开发指南
本文档以 gpio_demo 为例,带你在 HiDiTing 开发板上快速跑通第一个 GPIO(通用输入输出)控制应用,并了解如何基于它构建自己的应用。
GPIO 驱动背景知识
GPIO 工作原理
GPIO(通用输入输出)是微控制器最基本的数字接口,可配置为输入或输出模式:
| 功能 | 说明 | 应用场景 |
|---|---|---|
| 输出模式 | 通过软件控制引脚输出高电平或低电平 | 控制 LED、蜂鸣器、继电器 |
| 输入模式 | 读取引脚上的电平状态(高或低) | 读取按键、传感器信号、开关信号 |
| 设置方向 | 将引脚配置为输入模式或输出模式 | 动态切换引脚功能、复用引脚控制 |
| 电平反转 | 将当前输出电平取反 | 闪烁 LED、脉冲信号生成 |
设置方向说明:
- 设置方向是 GPIO 操作的基础步骤,决定了引脚是用于输出控制还是输入读取。
- 通过 uapi_gpio_set_dir(
pin,direction) 接口配置:GPIO_DIRECTION_OUTPUT:配置为输出模式GPIO_DIRECTION_INPUT:配置为输入模式
- 在输出和电平反转操作前,必须先将引脚方向设置为输出模式。
操作流程
本示例支持四种 GPIO 操作,每种操作都遵循标准的初始化流程:
通用初始化步骤(所有操作共享):
- PIN 初始化:调用
uapi_pin_init()初始化 PIN 模块。 - GPIO 初始化:调用 uapi_gpio_init() 初始化 GPIO 模块。
- 设置 GPIO 模式:调用 uapi_pin_set_mode(
pin,PIN_MODE_0) 将引脚配置为 GPIO 功能。
各操作特有流程:
| 操作 | 流程 |
|---|---|
| GPIO 输出 | 设置方向为输出 → 设置输出电平 → 读取电平验证 |
| GPIO 输入 | 使能输入 → 读取电平 → 关闭输入使能 |
| 设置方向 | 根据参数设置输出或输入方向 |
| 电平反转 | 设置方向为输出 → 设置初始电平 → 调用反转函数 → 读取电平验证 |
接口说明:本示例基于AT命令框架实现,通过串口发送AT指令控制GPIO,每个操作函数都封装了完整的初始化、配置、操作和验证流程。
电平值说明
| 宏定义 | 值 | 说明 |
|---|---|---|
GPIO_LEVEL_HIGH |
1 | 高电平 |
GPIO_LEVEL_LOW |
0 | 低电平 |
快速跑通 GPIO Demo
功能说明
GPIO Demo 通过 AT 命令方式提供交互式控制,支持以下命令:
| AT 命令 | 功能 | 参数说明 |
|---|---|---|
AT+GPIOOUTPUT=pin,level |
GPIO 输出电平 | pin: 引脚号(0-5), level:电平( 0-1) |
AT+GPIOINPUT=pin |
GPIO 输入电平 | pin: 引脚号(0-5) |
AT+GPIOSETDIR=pin,dir |
设置 GPIO 方向 | pin: 引脚号(0-5), dir: 0(输入)/1(输出) |
AT+GPIOTOGGLE=pin,level |
GPIO 电平反转 | pin: 引脚号(0-5), level:电平( 0-1) |
编译
完成一站式 CLI 环境配置后执行:
# 编译固件,编译生成的固件从 output/3322/fwpkg 中获取 diting-community.fwpkg
fbb set-target pack_diting_community
fbb build
构建成功后,使用一站式 CLI 烧写固件并打开 UART2 串口监视器。以下为 Windows USB DFU 示例;将 COM3 替换为实际日志串口,其他平台和串口烧写参数参见一站式 CLI 开发环境使用指南。
fbb flash -f "$env:FBB_SDK_DIR\output\3322\fwpkg\diting-community.fwpkg" --chip 3322 -d --timeout 180
fbb monitor --port COM3 --baud 750000
使用方式
- 烧录固件并启动设备
-
通过串口发送 AT 命令,格式如下:

预期结果
GPIO 输出(AT+GPIOOUTPUT)

GPIO 输入(AT+GPIOINPUT)

GPIO 设置方向(AT+GPIOSETDIR)

GPIO 电平反转(AT+GPIOTOGGLE)

文件结构与代码走读
文件职责
| 文件 | 作用 |
|---|---|
| samples/native_samples/gpio/CMakeLists.txt | 定义 gpio_sample 组件及驱动依赖。 |
| samples/native_samples/gpio/gpio.h | 定义串口测试参数结构和命令表。 |
| samples/native_samples/gpio/gpio.c | 实现输入、输出、方向设置、电平翻转和资源释放。 |
| samples/native_samples/gpio/README.md | 给出完整命令和预期结果。 |
关键参数与常量
| 名称 | 作用 | 开发注意事项 |
|---|---|---|
pin |
指定 GPIO 编号。 | 使用前核对原理图、复用关系和目标电压域。 |
PIN_MODE_0 |
当前 Sample 使用的 GPIO 复用模式。 | 不同引脚的 GPIO 复用模式可能不同,应以 pinctrl 配置为准。 |
GPIO_DIRECTION_INPUT / GPIO_DIRECTION_OUTPUT |
设置输入或输出方向。 | 方向必须在读写电平前配置。 |
GPIO_LEVEL_LOW / GPIO_LEVEL_HIGH |
表示低、高电平。 | 不要用未经范围检查的业务参数直接转换为电平枚举。 |
PIN_IE_ENABLE |
打开输入使能。 | 输入场景结束后按产品资源策略关闭输入使能。 |
gpio_args_t、gpio_intput_args_t 和 gpio_setdir_args_t 是 AT 适配层参数,不是 GPIO 驱动要求的业务数据结构。
核心业务流程
- 调用
uapi_pin_init()和uapi_gpio_init(),再用uapi_pin_set_mode()将目标引脚切换到 GPIO 功能。 - 输出场景先设置
GPIO_DIRECTION_OUTPUT,再写入并回读电平;输入场景先打开输入使能,再读取电平。 - 翻转场景先设置已知输出电平,再调用
uapi_gpio_toggle()并回读确认结果。 - 每一步检查返回值;失败和正常退出都按实际所有权释放 pin 和 GPIO 资源。
AT 命令表只负责参数校验和调用转发。自定义应用不复制四套 AT 处理函数,直接在任务、服务或 UI 事件中复用上述初始化、操作和释放顺序;可构建的 app_run 示例见下一节。
基于 GPIO Demo 开发自己的应用
上面的demo是使用AT指令触发运行,HiDiTing还支持app_run方式触发应用在系统启动时自动运行,以下示例将以app_run的方式开发一个开发者自己的应用
- app_run(func) 是HiDiTing中应用层注册应用函数的宏,基于 GCC 编译器属性和自定义段区(section)自动注册来实现集中调用应用函数,系统启动时会自动遍历所有用 app_run 注册过的函数并执行,无需在 系统 main 函数里逐个调用函数。
代码清单
新建一个 GPIO 控制应用(以 my_gpio_demo 为例)通常只需要以下改动:
- 新建
my_gpio_demo.c源文件 - 新建
my_gpio_demo.h头文件 - 新建
CMakeLists.txt源文件 - 在
my_gpio_demo.c中实现GPIO操作函数 - 在
my_gpio_demo.h中定义宏常量和函数声明 - 在
CMakeLists.txt源文件编译规则
my_gpio_demo文件结构:
CMakeLists.txt 修改示例
# 在新建的 CMakeLists.txt 中添加应用的源文件
set(SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/my_gpio_demo.c
)
set(PUBLIC_HEADER
${CMAKE_CURRENT_SOURCE_DIR}
)
set(PRIVATE_HEADER
)
set(PUBLIC_DEFINES
MY_GPIO_DEMO_ENABLE
)
build_component()
关键代码片段
my_gpio_demo.c —— GPIO 控制实现
#include "my_gpio_demo.h"
#include "pinctrl.h"
#include "pinctrl_porting.h"
#include "errcode.h"
#include "hal_gpio.h"
#include "debug_print.h"
#include "driver/gpio.h"
#include "driver/pinctrl.h"
#include "app_init.h"
#include "soc_osal.h"
#define GPIO_TEST_PIN 1 // 测试使用的引脚号
#define TASK_PRIO 26
#define TASK_STACK_SIZE 0x1000
static void *my_gpio_task(const char *arg)
{
unused(arg);
printf("my_gpio_demo start\n");
// 初始化
uapi_pin_init();
uapi_gpio_init();
uapi_pin_set_mode(GPIO_TEST_PIN, PIN_MODE_0);
// 设置为输出模式
uapi_gpio_set_dir(GPIO_TEST_PIN, GPIO_DIRECTION_OUTPUT);
// 输出高电平
uapi_gpio_set_val(GPIO_TEST_PIN, GPIO_LEVEL_HIGH);
printf("gpio set high\n");
// 读取并验证
gpio_level_t level = uapi_gpio_get_val(GPIO_TEST_PIN);
printf("read level: %d\n", level);
// 翻转电平
uapi_gpio_toggle(GPIO_TEST_PIN);
level = uapi_gpio_get_val(GPIO_TEST_PIN);
printf("after toggle, read level: %d\n", level);
printf("my_gpio_demo done\n");
return NULL;
}
static void my_gpio_entry(void)
{
osal_task *task_handle = NULL;
osal_kthread_lock();
task_handle = osal_kthread_create((osal_kthread_handler)my_gpio_task, 0, "MyGpioTask", TASK_STACK_SIZE);
if (task_handle != NULL) {
osal_kthread_set_priority(task_handle, TASK_PRIO);
}
osal_kthread_unlock();
}
app_run(my_gpio_entry);
测试验证
完成一站式 CLI 环境配置后执行:
# 编译固件,编译生成的固件从 output/3322/fwpkg 中获取 diting-community.fwpkg
fbb set-target pack_diting_community
fbb build

说明
-
因为
app_run是在系统启动时运行应用,所以应用的运行日志会被夹在开机启动日志中。 -
为使该
gpio应用参与编译,还需在上层CMakeLists.txt文件中以宏MY_GPIO_DEMO_ENABLE为条件添加该my_gpio_demo文件。 - 宏
MY_GPIO_DEMO_ENABLE默认关闭。如需启用新建GPIO示例功能,需要在config.py中的diting-community配置项下将其打开。
app_run运行配置
app_run应用默认是关闭的,如需启用此应用,需用户手动在acore.prelds文件中添加 KEEP (*(SORT(.zinitcall.app_run*.init))) 具体参考示意图如下:

注意事项
引脚配置注意事项:
- GPIO 引脚号范围为 0-5,具体引脚对应的物理引脚请参考芯片手册。
- 使用前必须依次调用
uapi_pin_init()和uapi_gpio_init()完成初始化。 - 必须调用
uapi_pin_set_mode(pin, PIN_MODE_0)将引脚配置为 GPIO 模式。
输入模式注意事项:
- 读取输入电平前,必须调用
uapi_pin_set_ie(pin, PIN_IE_ENABLE)使能输入功能。 - 读取完成后,建议调用
uapi_pin_set_ie(pin, PIN_IE_DISABLE)关闭输入使能。
电平反转注意事项:
- 反转操作前必须将引脚设置为输出模式。
- 反转后的电平应与初始电平不同,否则操作失败。
AT 命令注意事项:
- 命令名称为大写字母,如
GPIOOUTPUT。 - 参数使用逗号分隔,如
AT+GPIOOUTPUT=0,1。 - 参数范围:pin 为 0-5,level 为 0/1。
常见错误
| 错误现象 | 原因 | 解决方法 |
|---|---|---|
undefined reference to 'uapi_gpio_init' |
未链接 GPIO 驱动库 | 检查 CMakeLists.txt 中是否正确添加了头文件路径 |
undefined reference to 'uapi_at_cmd_table_register' |
未链接 AT 命令库 | 检查 CMakeLists.txt 中是否正确添加了 AT 相关头文件路径 |
编译报 at_ret_t 未定义 |
未包含 at.h 头文件 |
添加 #include "at.h" |
| 串口无输出 | AT 命令未注册 | 确认调用了 at_diting_gpio_example_cmd_register() |
| 引脚无响应 | 引脚未正确初始化 | 确认依次调用了 uapi_pin_init()、uapi_gpio_init()、uapi_pin_set_mode() |
| 输入读取异常 | 输入使能未开启 | 确认调用了 uapi_pin_set_ie(pin, PIN_IE_ENABLE) |