获取GPIO管脚方向

可以通过如下函数获取GPIO管脚方向:

int32_t GpioGetDir(uint16_t gpio, uint16_t *dir);
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

表 3 GpioGetDir参数和返回值描述

class="table-box">
参数参数描述
gpiouint16_t类型,GPIO管脚号
diruint16_t类型指针,获取到的方向值
返回值返回值描述
HDF_SUCCESS获取GPIO管脚方向成功
负数获取GPIO管脚方向失败

假设需要获取GPIO管脚3的方向,其使用示例如下:

int32_t ret;
uin16_t dir;

ret = GpioGetDir(3, &dir);    // 获取3号GPIO管脚方向
if (ret != HDF_SUCCESS) {
    HDF_LOGE("GpioGetDir: gpio get dir fail, ret:%d\n", ret);
    return ret;
}
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
读取GPIO管脚电平值

如果要读取一个GPIO管脚电平,通过以下函数完成:

int32_t GpioRead(uint16_t gpio, uint16_t *val);
c
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

表 4 GpioRead参数和返回值描述

class="table-box">
参数参数描述
gpiouint16_t类型,GPIO管脚号
valuint16_t类型指针,接收读取电平值
返回值返回值描述
HDF_SUCCESS读取GPIO管脚电平值成功
负数读取GPIO管脚电平值失败

假设需要读取GPIO管脚3的电平值,其使用示例如下:

int32_t ret;
uint16_t val;

ret = GpioRead(3, &val);    // 读取3号GPIO管脚电平值
if (ret != HDF_SUCCESS) {
    HDF_LOGE("GpioRead: gpio read fail, ret:%d\n", ret);
    return ret;
}
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
写入GPIO管脚电平值

如果要向GPIO管脚写入电平值,通过以下函数完成:

int32_t GpioWrite(uint16_t gpio, uint16_t val);
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

表 5 GpioWrite参数和返回值描述

class="table-box">
参数参数描述
gpiouint16_t类型,GPIO管脚号
valuint16_t类型,待写入的电平值
返回值返回值描述
HDF_SUCCESS写入GPIO管脚电平值成功
负数写入GPIO管脚电平值失败

假设需要给GPIO管脚3写入低电平值,其使用示例如下:

int32_t ret;

ret = GpioWrite(3, GPIO_VAL_LOW);    // 给3号GPIO管脚写入低电平值
if (ret != HDF_SUCCESS) {
    HDF_LOGE("GpioWrite: gpio write fail, ret:%d\n", ret);
    return ret;
}
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
设置GPIO管脚中断

如果要为一个GPIO管脚设置中断响应程序,使用如下函数:

int32_t GpioSetIrq(uint16_t gpio, uint16_t mode, GpioIrqFunc func, void *arg);
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

表 6 GpioSetIrq参数和返回值描述

class="table-box">
参数参数描述
gpiouint16_t类型,GPIO管脚号
modeuint16_t类型,中断触发模式
func函数指针,中断服务程序
arg无类型指针,传递给中断服务程序的入参
返回值返回值描述
HDF_SUCCESS设置GPIO管脚中断成功
负数设置GPIO管脚中断失败

注意:
同一时间,只能为某个GPIO管脚设置一个中断服务函数,如果重复调用GpioSetIrq函数,则之前设置的中断服务函数会被取代。

取消GPIO管脚中断

当不再需要响应中断服务函数时,使用如下函数取消中断设置:

int32_t GpioUnsetIrq(uint16_t gpio, void *arg);
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

表 7 GpioUnsetIrq参数和返回值描述

class="table-box">
参数参数描述
gpiouint16_t类型,GPIO管脚号
arg无类型指针,GPIO中断数据
返回值返回值描述
HDF_SUCCESS取消GPIO管脚中断成功
负数取消GPIO管脚中断失败
使能GPIO管脚中断

在中断服务程序设置完成后,还需要先通过如下函数使能GPIO管脚的中断:

int32_t GpioEnableIrq(uint16_t gpio);
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

表 8 GpioEnableIrq参数和返回值描述

class="table-box">
参数参数描述
gpiouint16_t类型,GPIO管脚号
返回值返回值描述
HDF_SUCCESS使能GPIO管脚中断成功
负数使能GPIO管脚中断失败

注意:
必须通过此函数使能管脚中断,之前设置的中断服务函数才能被正确响应。

禁止GPIO管脚中断

如果要临时屏蔽此中断,可以通过如下函数禁止GPIO管脚中断:

int32_t GpioDisableIrq(uint16_t gpio);
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

表 9 GpioDisableIrq参数和返回值描述

class="table-box">
参数参数描述
gpiouint16_t类型,GPIO管脚号
返回值返回值描述
HDF_SUCCESS禁止GPIO管脚中断成功
负数禁止GPIO管脚中断失败

中断相关操作示例:

// 中断服务函数
int32_t MyCallBackFunc(uint16_t gpio, void *data)
{
    HDF_LOGI("MyCallBackFunc: gpio:%u interrupt service in data.\n", gpio);
    return HDF_SUCCESS;
}

int32_t ret;
// 设置中断服务程序为MyCallBackFunc,入参为NULL,中断触发模式为上升沿触发
ret = GpioSetIrq(3, OSAL_IRQF_TRIGGER_RISING, MyCallBackFunc, NULL);
if (ret != HDF_SUCCESS) {
    HDF_LOGE("GpioSetIrq: gpio set irq fail, ret:%d\n", ret);
    return ret;
}

// 使能3号GPIO管脚中断
ret = GpioEnableIrq(3);
if (ret != HDF_SUCCESS) {
    HDF_LOGE("GpioEnableIrq: gpio enable irq fail, ret:%d\n", ret);
    return ret;
}

// 禁止3号GPIO管脚中断
ret = GpioDisableIrq(3);
if (ret != HDF_SUCCESS) {
    HDF_LOGE("GpioDisableIrq: gpio disable irqfail, ret:%d\n", ret);
    return ret;
}

// 取消3号GPIO管脚中断服务程序
ret = GpioUnsetIrq(3, NULL);
if (ret != HDF_SUCCESS) {
    HDF_LOGE("GpioUnSetIrq: gpio unset irq fail, ret:%d\n", ret);
    return ret;
}
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"> class="hide-preCode-box">

使用实例

本实例程序中,我们将测试一个GPIO管脚的中断触发:为管脚设置中断服务函数,触发方式为边沿触发,然后通过交替写高低电平到管脚,产生电平波动,制造触发条件,观察中断服务函数的执行。

首先需要选取一个空闲的GPIO管脚,本例程基于Hi3516DV300开发板,GPIO管脚选择GPIO10_3,换算成GPIO号为83。

读者可以根据自己使用的开发板,参考其原理图,选择一个空闲的GPIO管脚即可。

#include "gpio_if.h"
#include "hdf_log.h"
#include "osal_irq.h"
#include "osal_time.h"

static uint32_t g_irqCnt;

// 中断服务函数
static int32_t TestCaseGpioIrqHandler(uint16_t gpio, void *data)
{
    HDF_LOGE("TestCaseGpioIrqHandler: irq triggered! on gpio:%u, in data", gpio);
    g_irqCnt++;          // 如果中断服务函数触发执行,则将全局中断计数加1
    return GpioDisableIrq(gpio);
}

// 测试用例函数
static int32_t TestCaseGpioIrqEdge(void)
{
    int32_t ret;
    uint16_t valRead;
    uint16_t mode;
    uint16_t gpio = 84;  // 待测试的GPIO管脚号
    uint32_t timeout;

    // 将管脚方向设置为输出
    ret = GpioSetDir(gpio, GPIO_DIR_OUT);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("TestCaseGpioIrqEdge: set dir fail! ret:%d\n", ret);
        return ret;
    }

    // 先禁止该管脚中断
    ret = GpioDisableIrq(gpio);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("TestCaseGpioIrqEdge: disable irq fail! ret:%d\n", ret);
        return ret;
    }

    // 为管脚设置中断服务函数,触发模式为上升沿和下降沿共同触发
    mode = OSAL_IRQF_TRIGGER_RISING | OSAL_IRQF_TRIGGER_FALLING;
    HDF_LOGE("TestCaseGpioIrqEdge: mode:%0x\n", mode);
    ret = GpioSetIrq(gpio, mode, TestCaseGpioIrqHandler, NULL);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("TestCaseGpioIrqEdge: set irq fail! ret:%d\n", ret);
        return ret;
    }

    // 使能此管脚中断
    ret = GpioEnableIrq(gpio);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("TestCaseGpioIrqEdge: enable irq fail! ret:%d\n", ret);
        (void)GpioUnsetIrq(gpio, NULL);
        return ret;
    }

    g_irqCnt = 0;        // 清除全局计数器
    timeout = 0;         // 等待时间清零
    // 等待此管脚中断服务函数触发,等待超时时间为1000毫秒
    while (g_irqCnt <= 0 && timeout < 1000) {
        (void)GpioRead(gpio, &valRead);
        (void)GpioWrite(gpio, (valRead == GPIO_VAL_LOW) ? GPIO_VAL_HIGH : GPIO_VAL_LOW);
        HDF_LOGE("TestCaseGpioIrqEdge: wait irq timeout:%u\n", timeout);
        OsalMDelay(200); // 等待中断触发
        timeout += 200;
    }
    (void)GpioUnsetIrq(gpio, NULL);
    HDF_LOGI("TestCaseGpioIrqEdge: function tests end, g_irqCnt:%u", g_irqCnt);
    return (g_irqCnt > 0) ? HDF_SUCCESS : HDF_FAILURE;
}
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"> class="hide-preCode-box">

如果大家想更加深入的学习 OpenHarmony(鸿蒙南向) 开发的全栈内容,不妨可以参考以下相关学习文档进行学习,助你快速提升自己:

OpenHarmony 开发环境搭建:https://qr18.cn/CgxrRy

《OpenHarmony源码解析》:https://qr18.cn/CgxrRy

系统架构分析:https://qr18.cn/CgxrRy

OpenHarmony 设备开发学习手册:https://qr18.cn/CgxrRy

在这里插入图片描述

OpenHarmony面试题(内含参考答案):https://qr18.cn/CgxrRy

写在最后

data-report-view="{"mod":"1585297308_001","spm":"1001.2101.3001.6548","dest":"https://blog.csdn.net/maniuT/article/details/141071811","extend1":"pc","ab":"new"}">> id="blogExtensionBox" style="width:400px;margin:auto;margin-top:12px" class="blog-extension-box"> class="blog_extension blog_extension_type2" id="blog_extension"> class="extension_official" data-report-click="{"spm":"1001.2101.3001.6471"}" data-report-view="{"spm":"1001.2101.3001.6471"}"> class="blog_extension_card_left"> class="blog_extension_card_cont"> 鸿蒙开发学习资料领取!!! class="blog_extension_card_cont_r"> 微信名片
注:本文转载自blog.csdn.net的沧海一笑-dj的文章"https://blog.csdn.net/dengjin20104042056/article/details/99698903"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接

评论记录:

未查询到任何数据!