当前位置: 首页 > news >正文

6、nRF52xx蓝牙学习(nrf_gpiote.c库函数学习)

续前一篇文章

2、nrfx_gpiote_in_init

程序代码如下:

nrfx_err_t nrfx_gpiote_in_init(nrfx_gpiote_pin_t               pin,
                               nrfx_gpiote_in_config_t const * p_config,
                               nrfx_gpiote_evt_handler_t       evt_handler)
{
    NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
    nrfx_err_t err_code = NRFX_SUCCESS;

    /* Only one GPIOTE channel can be assigned to one physical pin. */
    if (pin_in_use_by_gpiote(pin))
    {
        err_code = NRFX_ERROR_INVALID_STATE;
    }
    else
    {
        int8_t channel = channel_port_alloc(pin, evt_handler, p_config->hi_accuracy);
        if (channel != NO_CHANNELS)
        {
            if (!p_config->skip_gpio_setup)
            {
                if (p_config->is_watcher)
                {
                    nrf_gpio_cfg_watcher(pin);
                }
                else
                {
                    nrf_gpio_cfg_input(pin, p_config->pull);
                }
                pin_configured_set(pin);
            }

            if (p_config->hi_accuracy)
            {
                nrf_gpiote_event_configure((uint32_t)channel, pin, p_config->sense);
            }
            else
            {
                m_cb.port_handlers_pins[channel - GPIOTE_CH_NUM] |= (p_config->sense) <<
                                                                    POLARITY_FIELD_POS;
            }
        }
        else
        {
            err_code = NRFX_ERROR_NO_MEM;
        }
    }

    NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
    return err_code;
}

下面将详细解释 nrfx_gpiote_in_init 函数,

(1)   nrfx_err_t nrfx_gpiote_in_init(nrfx_gpiote_pin_t                          pin,
                                                               nrfx_gpiote_in_config_t const    * p_config,
                                                               nrfx_gpiote_evt_handler_t           evt_handler);

   • pin:要初始化的 GPIO 引脚编号,根据查询有如下信息:

         typedef uint32_t nrfx_gpiote_pin_t;

nrfx_gpiote_pin_t 其实就是uint32_t的意思,是为了便于理解,才这样取了一个别名。

• p_config:指向 nrfx_gpiote_in_config_t 结构体的指针,该结构体包含了引脚的配置信息。

结构体定义如下 :

typedef struct
{
    nrf_gpiote_polarity_t sense;               /**< Transition that triggers the interrupt. */
    nrf_gpio_pin_pull_t   pull;                /**< Pulling mode. */
    bool                  is_watcher      : 1; /**< True when the input pin is tracking an output pin. */
    bool                  hi_accuracy     : 1; /**< True when high accuracy (IN_EVENT) is used. */
    bool                  skip_gpio_setup : 1; /**< Do not change GPIO configuration */
} nrfx_gpiote_in_config_t;

其中nrf_gpiote_polarity_t类型是一个枚举类型,其定义如下:

typedef enum
{
  NRF_GPIOTE_POLARITY_LOTOHI = GPIOTE_CONFIG_POLARITY_LoToHi,       ///<  Low to high.
  NRF_GPIOTE_POLARITY_HITOLO = GPIOTE_CONFIG_POLARITY_HiToLo,       ///<  High to low.
  NRF_GPIOTE_POLARITY_TOGGLE = GPIOTE_CONFIG_POLARITY_Toggle        ///<  Toggle.
} nrf_gpiote_polarity_t;

其中nrf_gpio_pin_pull_t类型是一个枚举类型,其定义如下:

typedef enum
{
    NRF_GPIO_PIN_NOPULL   = GPIO_PIN_CNF_PULL_Disabled, ///<  Pin pull-up resistor disabled.
    NRF_GPIO_PIN_PULLDOWN = GPIO_PIN_CNF_PULL_Pulldown, ///<  Pin pull-down resistor enabled.
    NRF_GPIO_PIN_PULLUP   = GPIO_PIN_CNF_PULL_Pullup,   ///<  Pin pull-up resistor enabled.
} nrf_gpio_pin_pull_t;

• evt_handler:事件处理函数指针,当引脚状态发生变化时会调用此函数,该函数将单独作为一篇文章学习。

 (2)NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
nrfx_err_t err_code = NRFX_SUCCESS;

   • NRFX_ASSERT(nrf_gpio_pin_present_check(pin));:使用断言来确保指定的引脚 pin 是存在的。如果引脚不存在,程序会触发断言错误。

• nrfx_err_t err_code = NRFX_SUCCESS;

初始化错误码 err_code 为 NRFX_SUCCESS,表示初始状态下操作是成功的。

(3) /* Only one GPIOTE channel can be assigned to one physical pin. */
if (pin_in_use_by_gpiote(pin))
{
    err_code = NRFX_ERROR_INVALID_STATE;
}

   • 注释表明一个物理引脚只能分配一个 GPIOTE 通道。

• if (pin_in_use_by_gpiote(pin)):检查指定的引脚是否已经被 GPIOTE 使用。如果已经被使用,将错误码 err_code 设置为 NRFX_ERROR_INVALID_STATE。其中pin_in_use_by_gpiote函数定义如下 :

__STATIC_INLINE bool pin_in_use_by_gpiote(uint32_t pin)
{
    return (m_cb.pin_assignments[pin] >= 0);
}

(4) else
{
    int8_t channel = channel_port_alloc(pin, evt_handler, p_config->hi_accuracy);
    if (channel != NO_CHANNELS)
    {
   • int8_t channel = channel_port_alloc(pin, evt_handler, p_config->hi_accuracy);

尝试为指定的引脚分配一个 GPIOTE 通道。channel_port_alloc 函数会根据引脚编号、事件处理函数和高精度配置标志来分配通道,并返回分配的通道编号。

• if (channel != NO_CHANNELS):检查通道分配是否成功。如果成功,进入后续的配置步骤。

  (5)  if (!p_config->skip_gpio_setup)
        {
            if (p_config->is_watcher)
            {
                nrf_gpio_cfg_watcher(pin);
            }
            else
            {
                nrf_gpio_cfg_input(pin, p_config->pull);
            }
            pin_configured_set(pin);
        }

   • if (!p_config->skip_gpio_setup):检查是否跳过 GPIO 引脚的设置。如果不跳过,继续进行引脚配置。 

if (p_config->is_watcher):如果 is_watcher 标志为真,调用 nrf_gpio_cfg_watcher(pin) 函数将引脚配置为观察者模式。 ◦ else:否则,调用 nrf_gpio_cfg_input(pin, p_config->pull) 函数将引脚配置为输入模式,并设置上拉或下拉电阻。  

• pin_configured_set(pin);:标记该引脚已经被配置。

 (6)   if (p_config->hi_accuracy)
        {
            nrf_gpiote_event_configure((uint32_t)channel, pin, p_config->sense);
        }
        else
        {
            m_cb.port_handlers_pins[channel - GPIOTE_CH_NUM] |= (p_config->sense) <<
                                                                POLARITY_FIELD_POS;
        }
    }

   • if (p_config->hi_accuracy):检查是否启用高精度模式。 ◦ 如果启用,调用 nrf_gpiote_event_configure((uint32_t)channel, pin, p_config->sense) 函数配置 GPIOTE 事件,指定通道、引脚和触发条件。 ◦ 如果未启用,将触发条件 p_config->sense 左移 POLARITY_FIELD_POS 位,并与 m_cb.port_handlers_pins[channel - GPIOTE_CH_NUM] 进行按位或操作,更新端口处理引脚的状态。  

 (7) else
    {
        err_code = NRFX_ERROR_NO_MEM;
    }
}

   • 如果通道分配失败(channel == NO_CHANNELS),将错误码 err_code 设置为 NRFX_ERROR_NO_MEM,表示没有可用的通道资源。  

(8)NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
return err_code;

   • NRFX_LOG_INFO:记录日志信息,包含函数名和错误码的字符串表示。

• return err_code;:返回错误码,告知调用者初始化操作的结果。

 总结 nrfx_gpiote_in_init 函数的主要功能是为指定的 GPIO 引脚分配一个 GPIOTE 通道,并根据配置信息对引脚进行初始化。如果引脚已经被使用或没有可用的通道资源,会返回相应的错误码。

http://www.dtcms.com/a/122979.html

相关文章:

  • 基于 AI智能体、大模型、RAG、Agent 等技术构建公司内部闭环智能问答系统的详细方案,结合 Spring Boot + Vue 管理系统 的改造思路
  • Http代理服务器选型与搭建
  • Starrocks的Bitmap索引和Bloom filter索引以及全局字典
  • 基于微信小程序的志愿服务系统的设计与实现
  • 数字图像处理作业3
  • fuse-python使用fuse来挂载fs
  • 汽车软件开发常用的建模工具汇总
  • Joomla 常用模块 - 在线用户与Joomla 常用模块 - 自定义HTML模块
  • [leetcode]判断质数
  • 关于C++日志库spdlog
  • JS 函数提升
  • 蓝桥杯十一届C++B组真题题解
  • 革新电销流程,数企云外呼开启便捷 “直通车”
  • 各种场景的ARP攻击描述笔记(超详细)
  • stream流Collectors.toMap(),key值重复问题
  • Bootstrap Table动态修改列标题
  • C++中命名空间namespace|头文件h文件|源文件cpp文件详解
  • pyecharts常用图形
  • Mysql索引(二)
  • 8.第二阶段x64游戏实战-string类
  • UE学习记录part15
  • ffpyplayer+Qt,制作一个视频播放器
  • 玩转Docker | 使用Docker安装FileDrop文件共享工具
  • 如何解【决泛型作为运行时参数】时类型擦除问题
  • PowerBI数据建模2:计算选项、计算组
  • JavaScript实用API
  • 计算机视觉4——特征点及其描述子
  • LeetCode344反转字符串
  • 亮相2025全球分布式云大会,火山引擎边缘云落地AI新场景
  • 1. 两数之和 leetcode