GPIO使用指导
使用流程
GPIO标准API通过GPIO管脚号来操作指定管脚,使用GPIO的一般流程如图1所示。
图 1 GPIO使用流程图

确定GPIO管脚号
不同SOC芯片由于其GPIO控制器型号、参数、以及控制器驱动的不同,GPIO管脚号的换算方式不一样。
- Hi3516DV300
控制器管理12组GPIO管脚,每组8个。
GPIO号 = GPIO组索引 (0~11) * 每组GPIO管脚数(8) + 组内偏移
举例:GPIO10_3的GPIO号 = 10 * 8 + 3 = 83 - Hi3518EV300
控制器管理10组GPIO管脚,每组10个。
GPIO号 = GPIO组索引 (0~9) * 每组GPIO管脚数(10) + 组内偏移
举例:GPIO7_3的GPIO管脚号 = 7 * 10 + 3 = 73
使用API操作GPIO管脚
- 设置GPIO管脚方向
在进行GPIO管脚读写前,需要先通过如下函数设置GPIO管脚方向:
int32_t GpioSetDir(uint16_t gpio, uint16_t dir);
表 1 GpioSetDir参数和返回值描述
| 参数 | 参数描述 |
| gpio | 待设置的GPIO管脚号 |
| dir | 待设置的方向值 |
| 返回值 | 返回值描述 |
| 0 | 设置成功 |
| 负数 | 设置失败 |
| - 读写GPIO管脚 |
如果要读取一个GPIO管脚电平,通过以下函数完成:
int32_t GpioRead(uint16_t gpio, uint16_t *val);
表 2 GpioRead参数和返回值描述
| 参数 | 参数描述 |
| gpio | 待读取的GPIO管脚号 |
| val | 接收读取电平值的指针 |
| 返回值 | 返回值描述 |
| 0 | 读取成功 |
| 负数 | 读取失败 |
如果要向GPIO管脚写入电平值,通过以下函数完成:
int32_t GpioWrite(uint16_t gpio, uint16_t val);
表 3 GpioWrite参数和返回值描述
| 参数 | 参数描述 |
| gpio | 待写入的GPIO管脚号 |
| val | 待写入的电平值 |
| 返回值 | 返回值描述 |
| 0 | 写入成功 |
| 负数 | 写入失败 |
示例代码:
```
- int32_t ret;
- uint16_t val;
- / 将3号GPIO管脚配置为输出 /
- ret = GpioSetDir(3, GPIO_DIR_OUT);
- if (ret != 0) {
- HDF_LOGE("GpioSerDir: failed, ret %d\n", ret);
- return;
- }
- / 向3号GPIO管脚写入低电平GPIO_VAL_LOW /
- ret = GpioWrite(3, GPIO_VAL_LOW);
- if (ret != 0) {
- HDF_LOGE("GpioWrite: failed, ret %d\n", ret);
- return;
- }
- / 将6号GPIO管脚配置为输入 /
- ret = GpioSetDir(6, GPIO_DIR_IN);
- if (ret != 0) {
- HDF_LOGE("GpioSetDir: failed, ret %d\n", ret);
- return;
- }
- / 读取6号GPIO管脚的电平值 /
- ret = GpioRead(6, &val); ```
- 设置GPIO中断
如果要为一个GPIO管脚设置中断响程序,使用如下函数:
int32_t GpioSetIrq(uint16_t gpio, uint16_t mode, GpioIrqFunc func, void *arg);
表 4 GpioSetIrq参数和返回值描述
| 参数 | 参数描述 |
| gpio | GPIO管脚号 |
| mode | 中断触发模式 |
| func | 中断服务程序 |
| arg | 传递给中断服务程序的入参 |
| 返回值 | 返回值描述 |
| 0 | 设置成功 |
| 负数 | 设置失败 |
注意: 同一时间,只能为某个GPIO管脚设置一个中断服务函数,如果重复调用GpioSetIrq函数,则之前设置的中断服务函数会被取代。
当不再需要响应中断服务函数时,使用如下函数取消中断设置:
int32_t GpioUnSetIrq(uint16_t gpio);
表 5 GpioUnSetIrq参数和返回值描述
| 参数 | 参数描述 |
| gpio | GPIO管脚号 |
| 返回值 | 返回值描述 |
| 0 | 取消成功 |
| 负数 | 取消失败 |
在中断服务程序设置完成后,还需要先通过如下函数使能GPIO管脚的中断:
int32_t GpioEnableIrq(uint16_t gpio);
表 6 GpioEnableIrq参数和返回值描述
| 参数 | 参数描述 |
| gpio | GPIO管脚号 |
| 返回值 | 返回值描述 |
| 0 | 使能成功 |
| 负数 | 使能失败 |
注意: 必须通过此函数使能管脚中断,之前设置的中断服务函数才能被正确响应。
如果要临时屏蔽此中断,可以通过如下函数禁止GPIO管脚中断:
int32_t GpioDisableIrq(uint16_t gpio);
表 7 GpioDisableIrq参数和返回值描述
| 参数 | 参数描述 |
| gpio | GPIO管脚号 |
| 返回值 | 返回值描述 |
| 0 | 禁止成功 |
| 负数 | 禁止失败 |
示例代码:
```
- /* 中断服务函数
- */
- int32_t MyCallBackFunc(uint16_t gpio, void *data)
- {
- HDF_LOGI("%s: gpio:%u interrupt service in! data=%p\n", func, gpio, data);
- return 0;
-
}
-
int32_t ret;
- / 设置中断服务程序为MyCallBackFunc,入参为NULL,中断触发模式为上升沿触发 /
- ret = GpioSetIrq(3, OSAL_IRQF_TRIGGER_RISING, MyCallBackFunc, NULL);
- if (ret != 0) {
- HDF_LOGE("GpioSetIrq: failed, ret %d\n", ret);
- return;
-
}
-
/ 使能3号GPIO管脚中断 /
- ret = GpioEnableIrq(3);
- if (ret != 0) {
- HDF_LOGE("GpioEnableIrq: failed, ret %d\n", ret);
- return;
-
}
-
/ 禁止3号GPIO管脚中断 /
- ret = GpioDisableIrq(3);
- if (ret != 0) {
- HDF_LOGE("GpioDisableIrq: failed, ret %d\n", ret);
- return;
-
}
-
/ 取消3号GPIO管脚中断服务程序 /
- ret = GpioUnSetIrq(3);
- if (ret != 0) {
- HDF_LOGE("GpioUnSetIrq: failed, ret %d\n", ret);
- return;
- } ```
