您的位置:首页 > 汽车 > 时评 > 无锡网站托管_王烨然盈盈_自媒体发布平台有哪些_百度搜索引擎营销案例

无锡网站托管_王烨然盈盈_自媒体发布平台有哪些_百度搜索引擎营销案例

2025/4/19 17:18:54 来源:https://blog.csdn.net/strongwyy/article/details/147149716  浏览:    关键词:无锡网站托管_王烨然盈盈_自媒体发布平台有哪些_百度搜索引擎营销案例
无锡网站托管_王烨然盈盈_自媒体发布平台有哪些_百度搜索引擎营销案例
下面再来探讨下驱动库如何实现任务的配置,驱动库的实现步骤应该和寄存器方式对应,关
键点就是如何调用驱动库的函数。
本例里同样的对比寄存器方式编写两路的 GPOITE 任务输出,一路配置为输出翻转,一路设
置为输出低电平。和 GPIOTE 事件相反,初始化任务应该是输出,同时需要使能任务和触发任务的 驱动库函数。下面介绍下如下三个组件库函数:
(1)nrfx_gpiote_out_init 函数
nrfx_err_t nrfx_gpiote_out_init(nrfx_gpiote_pin_t                pin,nrfx_gpiote_out_config_t const * p_config)
{NRFX_ASSERT(nrf_gpio_pin_present_check(pin));NRFX_ASSERT(m_cb.state == NRFX_DRV_STATE_INITIALIZED);NRFX_ASSERT(p_config);nrfx_err_t err_code = NRFX_SUCCESS;if (pin_in_use(pin)){err_code = NRFX_ERROR_INVALID_STATE;}else{if (p_config->task_pin){int8_t channel = channel_port_alloc(pin, NULL, true);if (channel != NO_CHANNELS){nrf_gpiote_task_configure((uint32_t)channel,pin,p_config->action,p_config->init_state);}else{err_code = NRFX_ERROR_NO_MEM;}}else{pin_in_use_set(pin);}if (err_code == NRFX_SUCCESS){if (p_config->init_state == NRF_GPIOTE_INITIAL_VALUE_HIGH){nrf_gpio_pin_set(pin);}else{nrf_gpio_pin_clear(pin);}nrf_gpio_cfg_output(pin);pin_configured_set(pin);}}NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));return err_code;
}

nrfx_gpiote_out_init 函数的主要作用是初始化一个 GPIO 引脚作为 GPIOTE(通用外设中断和事件)的输出引脚。它接收一个引脚编号和一个配置结构体指针作为参数,根据配置对引脚进行相应的初始化设置,并返回初始化结果的错误码。

函数参数 • nrfx_gpiote_pin_t pin:要初始化的 GPIO 引脚编号。

• nrfx_gpiote_out_config_t const * p_config:指向 GPIO 输出配置结构体的指针,该结构体包含了引脚的各种配置信息,如是否作为任务引脚、引脚动作、初始状态等。

nrfx_gpiote_out_config_t 结构体定义如下 :

typedef struct
{nrf_gpiote_polarity_t action;     /**< Configuration of the pin task. */nrf_gpiote_outinit_t  init_state; /**< Initial state of the output pin. */bool                  task_pin;   /**< True if the pin is controlled by a GPIOTE task. */
} nrfx_gpiote_out_config_t;

其中nrf_gpiote_outinit_t是枚举类型,其定义如下 :

typedef enum
{NRF_GPIOTE_INITIAL_VALUE_LOW  = GPIOTE_CONFIG_OUTINIT_Low,       ///<  Low to high.NRF_GPIOTE_INITIAL_VALUE_HIGH = GPIOTE_CONFIG_OUTINIT_High       ///<  High to low.
} nrf_gpiote_outinit_t;

NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
    NRFX_ASSERT(m_cb.state == NRFX_DRV_STATE_INITIALIZED);
    NRFX_ASSERT(p_config);


NRFX_ASSERT 是一个断言宏,用于在开发和调试阶段检查某些条件是否满足。如果条件不满足,程序会触发断言失败,帮助开发者快速定位问题。

nrf_gpio_pin_present_check(pin) 检查指定的引脚是否存在

 m_cb.state == NRFX_DRV_STATE_INITIALIZED 检查 GPIOTE 驱动的状态是否已经初始化。

 p_config 检查配置结构体指针是否有效。


if (pin_in_use(pin))
    {
        err_code = NRFX_ERROR_INVALID_STATE;
    }


pin_in_use(pin) 函数检查指定的引脚是否已经被使用。如果该引脚已经被使用,则将错误码设置为 NRFX_ERROR_INVALID_STATE,表示状态无效。


else
    {
        if (p_config->task_pin)
        {
            int8_t channel = channel_port_alloc(pin, NULL, true);

            if (channel != NO_CHANNELS)
            {
                nrf_gpiote_task_configure((uint32_t)channel,
                                          pin,
                                          p_config->action,
                                          p_config->init_state);
            }
            else
            {
                err_code = NRFX_ERROR_NO_MEM;
            }
        }


如果引脚未被使用,检查配置结构体中的 task_pin 字段。

如果 task_pin 为真,表示该引脚要作为任务引脚使用。

channel_port_alloc(pin, NULL, true) 函数尝试为该引脚分配一个 GPIOTE 通道。如果分配成功,返回通道编号;如果没有可用通道,返回 NO_CHANNELS。

如果通道分配成功,调用 nrf_gpiote_task_configure 函数对该通道进行配置,传入通道编号、引脚编号、引脚动作和初始状态等参数。

如果通道分配失败,将错误码设置为 NRFX_ERROR_NO_MEM,表示内存不足(这里实际是没有可用的 GPIOTE 通道)。


channel_port_alloc函数代码如下:
static int8_t channel_port_alloc(uint32_t pin, nrfx_gpiote_evt_handler_t handler, bool channel)
{int8_t   channel_id = NO_CHANNELS;uint32_t i;uint32_t start_idx = channel ? 0 : GPIOTE_CH_NUM;uint32_t end_idx   =channel ? GPIOTE_CH_NUM : (GPIOTE_CH_NUM + NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS);// critical sectionfor (i = start_idx; i < end_idx; i++){if (m_cb.handlers[i] == FORBIDDEN_HANDLER_ADDRESS){pin_in_use_by_te_set(pin, i, handler, channel);channel_id = i;break;}}// critical sectionreturn channel_id;
}

代码解释如下 :

函数概述 channel_port_alloc 是一个静态函数,其作用是为指定的引脚分配一个通道。

该函数会在特定的通道范围内查找可用通道,若找到,就将该通道分配给指定引脚,并返回通道编号;若未找到,就返回 NO_CHANNELS。

函数参数

• pin:类型为 uint32_t,代表要分配通道的引脚编号。

• handler:类型为 nrfx_gpiote_evt_handler_t,是一个事件处理函数指针,当该引脚发生事件时会调用此函数。

• channel:类型为 bool,用于确定通道分配的范围。若为 true,就在普通通道范围内分配;若为 false,就在低功耗事件通道范围内分配。  

若成功分配通道,返回通道编号;若未找到可用通道,返回 NO_CHANNELS。

代码详细解释


static int8_t channel_port_alloc(uint32_t pin, nrfx_gpiote_evt_handler_t handler, bool channel)
{
    int8_t   channel_id = NO_CHANNELS;
    uint32_t i;

    


根据 channel 参数确定通道分配的起始和结束索引

uint32_t start_idx = channel ? 0 : GPIOTE_CH_NUM; 这行代码的作用是根据 channel 的值来确定通道分配范围的起始索引。

• 若 channel 为 true(非零),则 start_idx 被赋值为 0。这意味着通道分配从编号为 0 的通道开始。

• 若 channel 为 false(零),则 start_idx 被赋值为 GPIOTE_CH_NUM。这表明通道分配从编号为 GPIOTE_CH_NUM 的通道开始。

uint32_t end_idx = channel ? GPIOTE_CH_NUM : (GPIOTE_CH_NUM + NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS);

这行代码的作用是根据 channel 的值来确定通道分配范围的结束索引。

• 若 channel 为 true(非零),则 end_idx 被赋值为 GPIOTE_CH_NUM。这意味着通道分配的范围是从 0 到 GPIOTE_CH_NUM - 1。

• 若 channel 为 false(零),则 end_idx 被赋值为 GPIOTE_CH_NUM + NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS。这表明通道分配的范围是从 GPIOTE_CH_NUM 到 GPIOTE_CH_NUM + NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS - 1。

总结 这两行代码的目的是根据 channel 的值选择不同的通道分配范围:

• 当 channel 为 true 时,通道分配范围是从 0 到 GPIOTE_CH_NUM - 1,通常代表普通通道的范围。

• 当 channel 为 false 时,通道分配范围是从 GPIOTE_CH_NUM 到 GPIOTE_CH_NUM + NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS - 1,一般代表低功耗事件通道的范围。



    

    // 进入临界区,这里代码注释表示是临界区,但代码中未实际体现临界区的保护代码
    // 临界区用于确保在多线程或多任务环境下,对共享资源的操作是原子的

    // 遍历指定范围的通道
    for (i = start_idx; i < end_idx; i++)
    {
        // 检查当前通道的处理函数地址是否为禁止使用的地址
        if (m_cb.handlers[i] == FORBIDDEN_HANDLER_ADDRESS)
        {
            // 如果是,调用 pin_in_use_by_te_set 函数将该引脚标记为已使用,并关联处理函数
            pin_in_use_by_te_set(pin, i, handler, channel);
            // 将通道编号赋值给 channel_id
            channel_id = i;
            // 找到可用通道后,跳出循环
            break;
        }
    }
    // 退出临界区,同样这里代码注释表示是临界区,但未实际体现临界区的保护代码

    // 返回通道编号,如果未找到可用通道,返回 NO_CHANNELS
    return channel_id;
}
   代码逻辑总结

1. 把 channel_id 初始化为 NO_CHANNELS,这意味着默认情况下未找到可用通道。

2. 依据 channel 参数确定通道分配的起始和结束索引。

3. 进入临界区(代码注释表明是临界区,但未实际实现临界区保护),以此保证在多线程或多任务环境下对共享资源的操作是原子的。

4. 遍历指定范围的通道,检查每个通道的处理函数地址是否为禁止使用的地址。

5. 若找到可用通道,调用 pin_in_use_by_te_set 函数将该引脚标记为已使用,并关联处理函数,然后将通道编号赋值给 channel_id,接着跳出循环。

6. 退出临界区(代码注释表明是临界区,但未实际实现临界区保护)。

7. 返回通道编号,若未找到可用通道,返回 NO_CHANNELS。        


nrf_gpiote_task_configure函数代码如下

__STATIC_INLINE void nrf_gpiote_task_configure(uint32_t idx, uint32_t pin,nrf_gpiote_polarity_t polarity,nrf_gpiote_outinit_t  init_val)
{NRF_GPIOTE->CONFIG[idx] &= ~(GPIOTE_CONFIG_PORT_PIN_Msk |GPIOTE_CONFIG_POLARITY_Msk |GPIOTE_CONFIG_OUTINIT_Msk);NRF_GPIOTE->CONFIG[idx] |= ((pin << GPIOTE_CONFIG_PSEL_Pos) & GPIOTE_CONFIG_PORT_PIN_Msk) |((polarity << GPIOTE_CONFIG_POLARITY_Pos) & GPIOTE_CONFIG_POLARITY_Msk) |((init_val << GPIOTE_CONFIG_OUTINIT_Pos) & GPIOTE_CONFIG_OUTINIT_Msk);
}

 nrf_gpiote_task_configure 是一个静态内联函数,其用途是对 nRF GPIOTE(通用引脚输入 / 输出任务和事件)模块的特定通道配置寄存器进行设置。借助该函数,你能够指定特定通道所关联的引脚、引脚极性以及初始输出值。

函数参数

• idx:uint32_t 类型,代表要配置的 GPIOTE 通道的索引。

• pin:uint32_t 类型,代表要关联到该通道的引脚编号。

• polarity:nrf_gpiote_polarity_t 类型,用于指定引脚的极性,例如高电平触发、低电平触发等。 • init_val:nrf_gpiote_outinit_t 类型,用于指定引脚的初始输出值。  


   
   代码逻辑步骤

1.  清除相关位:

 NRF_GPIOTE->CONFIG[idx] &= ~(GPIOTE_CONFIG_PORT_PIN_Msk |
                             GPIOTE_CONFIG_POLARITY_Msk |
                             GPIOTE_CONFIG_OUTINIT_Msk);
   
  NRF_GPIOTE->CONFIG[idx] 表示 GPIOTE 模块中第 idx 个通道的配置寄存器。  GPIOTE_CONFIG_PORT_PIN_Msk、GPIOTE_CONFIG_POLARITY_Msk 和 GPIOTE_CONFIG_OUTINIT_Msk 分别是用于选择引脚、极性和初始输出值的位掩码。

 ~ 是按位取反运算符,&= 是按位与赋值运算符。这行代码的作用是把配置寄存器中与引脚、极性和初始输出值相关的位清零,为后续设置新值做准备。  

2.  设置新值:

NRF_GPIOTE->CONFIG[idx] |= ((pin << GPIOTE_CONFIG_PSEL_Pos) & GPIOTE_CONFIG_PORT_PIN_Msk) |
                           ((polarity << GPIOTE_CONFIG_POLARITY_Pos) & GPIOTE_CONFIG_POLARITY_Msk) |
                           ((init_val << GPIOTE_CONFIG_OUTINIT_Pos) & GPIOTE_CONFIG_OUTINIT_Msk);
   
  << 是左移运算符,用于把 pin、polarity 和 init_val 移动到配置寄存器中对应的位置。

& 是按位与运算符,用于确保只有对应位掩码覆盖的位被设置。

| 是按位或运算符,|= 是按位或赋值运算符。这行代码的作用是将移动并掩码处理后的 pin、polarity 和 init_val 值设置到配置寄存器中。    

总结 此函数的主要功能是先清除 GPIOTE 通道配置寄存器中与引脚、极性和初始输出值相关的位,然后将新的引脚编号、极性和初始输出值设置到这些位上,从而完成对指定通道的配置。   

     


(2)nrfx_gpiote_out_task_enable函数

void nrfx_gpiote_out_task_enable(nrfx_gpiote_pin_t pin)
{NRFX_ASSERT(nrf_gpio_pin_present_check(pin));NRFX_ASSERT(pin_in_use(pin));NRFX_ASSERT(pin_in_use_by_te(pin));nrf_gpiote_task_enable((uint32_t)m_cb.pin_assignments[pin]);
}

整体功能概述 nrfx_gpiote_out_task_enable

函数的作用是启用指定引脚的 GPIO 任务(GPIOTE,General Purpose Input Output Task and Event)。

在 Nordic Semiconductor 的 nRF 系列微控制器里,GPIOTE 模块可让 GPIO 引脚与任务和事件系统相互配合,进而实现高效的硬件级控制。

代码详细解释

void nrfx_gpiote_out_task_enable(nrfx_gpiote_pin_t pin)
   • 函数定义:这是一个无返回值(void)的函数,其参数为 nrfx_gpiote_pin_t 类型的 pin,此参数代表要启用任务的 GPIO 引脚编号。

 NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
   • 断言检查:NRFX_ASSERT 属于一个断言宏,当条件不满足时,程序会停止执行。nrf_gpio_pin_present_check(pin) 函数用于检查指定的引脚是否存在于硬件中。若该引脚不存在,程序会触发断言失败,进而停止执行。

 NRFX_ASSERT(pin_in_use(pin));
   • 断言检查:pin_in_use(pin) 函数用来检查指定的引脚是否已被使用。要是该引脚未被使用,程序会触发断言失败并停止执行。

  NRFX_ASSERT(pin_in_use_by_te(pin));
   • 断言检查:pin_in_use_by_te(pin) 函数用于检查指定的引脚是否被 GPIOTE 模块使用。若该引脚未被 GPIOTE 模块使用,程序会触发断言失败并停止执行。

  nrf_gpiote_task_enable((uint32_t)m_cb.pin_assignments[pin]);
   • 启用任务:nrf_gpiote_task_enable 函数用于启用指定的 GPIOTE 任务。m_cb.pin_assignments[pin] 是一个数组,它将 GPIO 引脚编号映射到对应的 GPIOTE 任务编号。通过将 m_cb.pin_assignments[pin] 强制转换为 uint32_t 类型,将其作为参数传递给 nrf_gpiote_task_enable 函数,从而启用该引脚对应的 GPIOTE 任务。  

总结 此函数先对指定的 GPIO 引脚进行多项检查,以确保其存在且已被 GPIOTE 模块使用,然后启用该引脚对应的 GPIOTE 任务。这样做能够避免在不合法的引脚上执行任务,增强程序的健壮性。


__STATIC_INLINE void nrf_gpiote_task_enable函代码如下:
__STATIC_INLINE void nrf_gpiote_task_enable(uint32_t idx)
{uint32_t final_config = NRF_GPIOTE->CONFIG[idx] | GPIOTE_CONFIG_MODE_Task;
#ifdef NRF51/* Workaround for the OUTINIT PAN. When nrf_gpiote_task_config() is called a glitch happenson the GPIO if the GPIO in question is already assigned to GPIOTE and the pin is in thecorrect state in GPIOTE, but not in the OUT register. *//* Configure channel to not existing, not connected to the pin, and configure as a tasks that will set it to proper level */NRF_GPIOTE->CONFIG[idx] = final_config | (((31) << GPIOTE_CONFIG_PSEL_Pos) & GPIOTE_CONFIG_PORT_PIN_Msk);__NOP();__NOP();__NOP();
#endifNRF_GPIOTE->CONFIG[idx] = final_config;
}

整体功能概述

nrf_gpiote_task_enable 是一个静态内联函数,其主要功能是启用指定索引 idx 的 GPIO 任务(GPIOTE,General Purpose Input Output Task and Event)。在 Nordic Semiconductor 的 nRF 系列微控制器中,GPIOTE 模块允许 GPIO 引脚与任务和事件系统进行交互,从而实现高效的硬件级控制。

代码详细解释

__STATIC_INLINE void nrf_gpiote_task_enable(uint32_t idx)
   • 函数定义:__STATIC_INLINE 表明这是一个静态内联函数,它会在调用处直接展开代码,从而避免函数调用的开销。函数返回值类型为 void,接收一个 uint32_t 类型的参数 idx,该参数代表要启用任务的 GPIOTE 通道索引。

  uint32_t final_config = NRF_GPIOTE->CONFIG[idx] | GPIOTE_CONFIG_MODE_Task;
   • 配置计算:NRF_GPIOTE->CONFIG[idx] 用于访问 GPIOTE 模块中指定通道 idx 的配置寄存器。GPIOTE_CONFIG_MODE_Task 是一个宏,代表将通道配置为任务模式。通过按位或操作(|),把当前通道的配置与任务模式标志组合,得到最终的配置值 final_config。

 #ifdef NRF51
    /* Workaround for the OUTINIT PAN. When nrf_gpiote_task_config() is called a glitch happens
    on the GPIO if the GPIO in question is already assigned to GPIOTE and the pin is in the
    correct state in GPIOTE, but not in the OUT register. */
    /* Configure channel to not existing, not connected to the pin, and configure as a tasks that will set it to proper level */
    NRF_GPIOTE->CONFIG[idx] = final_config | (((31) << GPIOTE_CONFIG_PSEL_Pos) & GPIOTE_CONFIG_PORT_PIN_Msk);
    __NOP();
    __NOP();
    __NOP();
#endif
    • 特定芯片的处理:#ifdef NRF51 是一个条件编译指令,意味着这段代码仅在 NRF51 芯片上编译执行。在 NRF51 芯片中,当调用 nrf_gpiote_task_config() 函数时,若 GPIO 引脚已分配给 GPIOTE 模块,且该引脚在 GPIOTE 模块中的状态与 OUT 寄存器中的状态不一致,就会出现信号毛刺问题。为解决此问题,代码先将通道配置为不与任何引脚相连,同时将其配置为任务模式,以确保引脚状态能正确设置。__NOP() 是空操作指令,用于插入短暂的延迟,保证硬件有足够时间响应配置更改。

NRF_GPIOTE->CONFIG[idx] = final_config;
   • 应用最终配置:将计算得到的最终配置值 final_config 写入 GPIOTE 模块中指定通道 idx 的配置寄存器,从而启用该通道的任务模式。  总结 该函数的主要目的是启用指定 GPIOTE 通道的任务模式。在 NRF51 芯片上,还会执行额外的配置步骤,以避免信号毛刺问题。通过这种方式,确保了 GPIO 任务的稳定和可靠执行。


本节主程序如下:

nrf_drv_gpiote_init:对 GPIOTE 驱动模块进行初始化操作。

err_code 用于存储初始化的返回状态,APP_ERROR_CHECK 宏会对返回状态进行检查,若出现错误就会触发相应的错误处理机制。

• GPIOTE_CONFIG_OUT_TASK_TOGGLE:创建一个 nrf_drv_gpiote_out_config_t 类型的结构体 config1,把 GPIOTE 通道配置为翻转模式。也就是说,每次触发该通道的任务时,对应的引脚电平就会翻转。

• nrf_drv_gpiote_out_init:将 config1 配置应用到 GPIOTE0 通道,并且进行初始化。若初始化失败,APP_ERROR_CHECK 会处理错误。

• nrf_drv_gpiote_out_task_enable:启用 GPIOTE0 通道的任务模式,这样该通道就能响应任务触发了。

• GPIOTE_CONFIG_OUT_TASK_LOW:创建另一个 nrf_drv_gpiote_out_config_t 类型的结构体 config2,把 GPIOTE 通道配置为低电平模式。即每次触发该通道的任务时,对应的引脚电平会被拉低。

• 再次使用 nrf_drv_gpiote_out_init 和 nrf_drv_gpiote_out_task_enable 对 GPIOTE1 通道进行初始化和任务启用操作。

nrf_drv_gpiote_out_task_trigger:分别触发 GPIOTE0 和 GPIOTE1 通道的任务。依据之前的配置,GPIOTE0 通道会使对应的引脚电平翻转,而 GPIOTE1 通道会将对应的引脚电平拉低。

#include <stdbool.h>
#include "nrf.h"
#include "nrf_drv_gpiote.h"
#include "app_error.h"
#include "nrf_delay.h"#define GPIOTE0       13
#define GPIOTE1       14void GPIOTE_TASK_Init(void){ret_code_t err_code;	//初始化GPIOTE程序模块err_code = nrf_drv_gpiote_init();APP_ERROR_CHECK(err_code);//定义GPIOTE输出初始化结构体,主要是配置为翻转模式nrf_drv_gpiote_out_config_t config1 = GPIOTE_CONFIG_OUT_TASK_TOGGLE(true);//绑定GPIOTE输出引脚err_code = nrf_drv_gpiote_out_init(GPIOTE0, &config1);APP_ERROR_CHECK(err_code);//配置为引脚LED_3所在GPIOTE通道的任务模式nrf_drv_gpiote_out_task_enable(GPIOTE0);  //定义GPIOTE输出初始化结构体,主要是配置为低电平模式nrf_drv_gpiote_out_config_t config2 = GPIOTE_CONFIG_OUT_TASK_LOW;//绑定GPIOTE输出引脚err_code = nrf_drv_gpiote_out_init(GPIOTE1, &config2);APP_ERROR_CHECK(err_code);//配置为引脚LED_4所在GPIOTE通道的任务模式nrf_drv_gpiote_out_task_enable(GPIOTE1); 	}int main(void)
{GPIOTE_TASK_Init();   while(true){ //触发输出,即指示灯D3,D4翻转状态nrf_drv_gpiote_out_task_trigger(GPIOTE0);     nrf_drv_gpiote_out_task_trigger(GPIOTE1);nrf_delay_ms(500);}
}     

解析代码:

(1)相当宏NRFX_GPIOTE_CONFIG_OUT_TASK_LOW

#define NRFX_GPIOTE_CONFIG_OUT_TASK_LOW              \{                                                \.init_state = NRF_GPIOTE_INITIAL_VALUE_HIGH, \.task_pin   = true,                          \.action     = NRF_GPIOTE_POLARITY_HITOLO,    \}

整体功能概述 这段代码定义了一个宏 NRFX_GPIOTE_CONFIG_OUT_TASK_LOW,其用途是生成一个用于配置通用输入输出任务和事件(GPIOTE)模块输出引脚的结构体初始化器。在 Nordic nRF 系列微控制器里,GPIOTE 模块可让 GPIO 引脚与任务和事件系统相互配合,实现高效的硬件级控制。

代码详细解释

 #define NRFX_GPIOTE_CONFIG_OUT_TASK_LOW              \
   • 宏定义:借助 #define 指令定义一个名为 NRFX_GPIOTE_CONFIG_OUT_TASK_LOW 的宏,该宏会生成一个结构体初始化器,用于把 GPIOTE 输出引脚配置为低电平任务模式。
   • 结构体初始化开始

  .init_state = NRF_GPIOTE_INITIAL_VALUE_HIGH, \
   • 初始状态配置:.init_state 是结构体中的一个成员,用于设定引脚的初始状态。NRF_GPIOTE_INITIAL_VALUE_HIGH 表示引脚的初始电平为高电平。

     .task_pin   = true,                          \
   • 任务引脚配置:.task_pin 是结构体nrfx_gpiote_out_config_t中的一个成员,用于指明该引脚是否作为任务引脚。true 表明该引脚被配置为任务引脚,意味着可以通过 GPIOTE 任务来控制该引脚的电平。

    .action     = NRF_GPIOTE_POLARITY_HITOLO,    \
   • 动作配置:.action 是结构体中的一个成员,用于设定引脚的动作模式。NRF_GPIOTE_POLARITY_HITOLO 表示当任务触发时,引脚的电平会从高电平变为低电平。

  总结 NRFX_GPIOTE_CONFIG_OUT_TASK_LOW 宏生成的结构体初始化器能够将 GPIOTE 输出引脚配置为低电平任务模式。具体而言,引脚的初始电平为高电平,被配置为任务引脚,且当任务触发时,引脚电平会从高电平变为低电平。这样的配置可用于控制外部设备,例如通过任务触发来关闭某个设备。


(2)相关宏NRFX_GPIOTE_CONFIG_OUT_TASK_HIGH

#define NRFX_GPIOTE_CONFIG_OUT_TASK_HIGH            \{                                               \.action     = NRF_GPIOTE_POLARITY_LOTOHI,   \.init_state = NRF_GPIOTE_INITIAL_VALUE_LOW, \.task_pin   = true,                         \}

解析:整体功能概述 这段代码定义了一个宏 NRFX_GPIOTE_CONFIG_OUT_TASK_HIGH,其作用是生成一个用于配置通用输入输出任务和事件(GPIOTE,General Purpose Input Output Task and Event)模块输出引脚的结构体初始化器。在 Nordic 的 nRF 系列微控制器中,GPIOTE 模块可以让 GPIO 引脚与任务和事件系统协同工作,实现高效的硬件级控制。这个宏所生成的配置会将引脚配置为高电平任务模式。

代码详细解释

#define NRFX_GPIOTE_CONFIG_OUT_TASK_HIGH            \
   • 宏定义:使用 #define 指令定义了一个名为 NRFX_GPIOTE_CONFIG_OUT_TASK_HIGH 的宏。该宏会生成一个结构体初始化代码块,用于把 GPIOTE 输出引脚配置为高电平任务模式。                         \
   • 结构体初始化起始:

  .action     = NRF_GPIOTE_POLARITY_LOTOHI,   \
   • 动作模式配置:.action 是结构体中的一个成员,用于指定引脚的动作模式。NRF_GPIOTE_POLARITY_LOTOHI 意味着当对应的 GPIOTE 任务被触发时,引脚的电平会从低电平转变为高电平。

   .init_state = NRF_GPIOTE_INITIAL_VALUE_LOW, \
   • 初始状态配置:.init_state 也是结构体的成员,用于设置引脚的初始电平状态。NRF_GPIOTE_INITIAL_VALUE_LOW 表示引脚在初始化时的电平为低电平。

   .task_pin   = true,                         \
   • 任务引脚标志:.task_pin 是一个布尔类型的结构体成员,true 表明该引脚被配置为任务引脚。这意味着可以通过 GPIOTE 任务来控制这个引脚的电平状态。

   总结 NRFX_GPIOTE_CONFIG_OUT_TASK_HIGH 宏创建了一个用于配置 GPIOTE 输出引脚的结构体初始化器。该配置将引脚初始化为低电平,设定为任务引脚,并且当触发相应的 GPIOTE 任务时,引脚的电平会从低电平变为高电平。这种配置通常用于控制外部设备,例如通过任务触发来开启某个设备。


(3) 使用的宏 NRFX_GPIOTE_CONFIG_OUT_TASK_TOGGLE(init_high)
#define NRFX_GPIOTE_CONFIG_OUT_TASK_TOGGLE(init_high)                                           \{                                                                                           \.action     = NRF_GPIOTE_POLARITY_TOGGLE,                                               \.init_state = init_high ? NRF_GPIOTE_INITIAL_VALUE_HIGH : NRF_GPIOTE_INITIAL_VALUE_LOW, \.task_pin   = true,                                                                     \}

代码解析:

此代码定义了一个宏 NRFX_GPIOTE_CONFIG_OUT_TASK_TOGGLE,

其用途是生成用于配置通用输入输出任务和事件(GPIOTE)模块输出引脚的结构体初始化器。该配置会将引脚设定为翻转任务模式,也就是每次触发任务时引脚电平会翻转。 代码详细解释 宏定义部分

#define NRFX_GPIOTE_CONFIG_OUT_TASK_TOGGLE(init_high)
   • 这行代码定义了一个名为 NRFX_GPIOTE_CONFIG_OUT_TASK_TOGGLE 的宏,它接收一个参数 init_high。这个参数是一个布尔值,用于指定引脚的初始电平状态。

  
   • 表示结构体初始化的开始。

   .action     = NRF_GPIOTE_POLARITY_TOGGLE,
   • .action 是结构体中的一个成员,用于设定引脚的动作模式。NRF_GPIOTE_POLARITY_TOGGLE 意味着当对应的 GPIOTE 任务被触发时,引脚的电平会进行翻转(高变低或者低变高)。

  .init_state = init_high ? NRF_GPIOTE_INITIAL_VALUE_HIGH : NRF_GPIOTE_INITIAL_VALUE_LOW,
   • .init_state 同样是结构体的成员,用于设置引脚的初始电平状态。这里使用了三元运算符 ? : 来根据 init_high 的值进行判断:

若 init_high 为真(非零值),则初始电平设为高电平(NRF_GPIOTE_INITIAL_VALUE_HIGH)。

若 init_high 为假(零值),则初始电平设为低电平(NRF_GPIOTE_INITIAL_VALUE_LOW)。    .task_pin   = true,
   • .task_pin 是一个布尔类型的结构体成员,true 表明该引脚被配置为任务引脚,意味着可以通过 GPIOTE 任务来控制这个引脚的电平状态。
   • 表示结构体初始化的结束。  

总结 NRFX_GPIOTE_CONFIG_OUT_TASK_TOGGLE 宏为 GPIOTE 输出引脚生成了一个可灵活配置初始电平的翻转任务模式配置。借助传入不同的 init_high 值,能够控制引脚的初始电平,而每次触发任务时,引脚电平都会进行翻转。这种配置常用于需要周期性改变引脚电平状态的场景,例如控制闪烁的 LED 灯。


(4)nrfx_gpiote_out_task_trigger(nrfx_gpiote_pin_t pin)函数

void nrfx_gpiote_out_task_trigger(nrfx_gpiote_pin_t pin)
{NRFX_ASSERT(nrf_gpio_pin_present_check(pin));NRFX_ASSERT(pin_in_use(pin));NRFX_ASSERT(pin_in_use_by_te(pin));nrf_gpiote_tasks_t task = TE_OUT_IDX_TO_TASK_ADDR((uint32_t)channel_port_get(pin));nrf_gpiote_task_set(task);
}

代码解析:

整体功能概述 nrfx_gpiote_out_task_trigger 函数的主要功能是触发指定 GPIO 引脚对应的 GPIOTE(General Purpose Input Output Task and Event)输出任务。在 Nordic nRF 系列微控制器中,GPIOTE 模块允许用户通过硬件任务和事件机制来控制 GPIO 引脚,从而实现高效的硬件操作。

代码详细解释

函数定义与参数

 void nrfx_gpiote_out_task_trigger(nrfx_gpiote_pin_t pin)
   • 这是一个无返回值(void)的函数,它接受一个 nrfx_gpiote_pin_t 类型的参数 pin,该参数代表要触发任务的 GPIO 引脚编号。

 断言检查部分

NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
NRFX_ASSERT(pin_in_use(pin));
NRFX_ASSERT(pin_in_use_by_te(pin));
   • NRFX_ASSERT 是一个断言宏,用于在调试阶段检查条件是否为真。如果条件为假,程序会触发断言失败,通常会导致程序停止执行,便于开发者定位问题。 ◦ nrf_gpio_pin_present_check(pin):检查指定的 GPIO 引脚是否在硬件上存在。如果引脚不存在,断言会失败。

pin_in_use(pin):检查该引脚是否已经被使用。若引脚未被使用,断言会失败。

pin_in_use_by_te(pin):检查该引脚是否已经被 GPIOTE 模块使用。若引脚未被 GPIOTE 模块使用,断言会失败。    

任务地址获取部分

nrf_gpiote_tasks_t task = TE_OUT_IDX_TO_TASK_ADDR((uint32_t)channel_port_get(pin));
   • channel_port_get(pin):该函数的作用是根据传入的 GPIO 引脚编号 pin,获取对应的 GPIOTE 通道和端口信息。

• (uint32_t):将 channel_port_get(pin) 的返回值强制转换为 uint32_t 类型。 • TE_OUT_IDX_TO_TASK_ADDR:这是一个宏或者函数,它将 GPIOTE 通道和端口信息转换为对应的 GPIOTE 任务地址。最终,将得到的任务地址赋值给 nrf_gpiote_tasks_t 类型的变量 task。  任务触发部分

nrf_gpiote_task_set(task);
   • 调用 nrf_gpiote_task_set 函数,传入之前获取的任务地址 task,从而触发该任务。这会导致对应的 GPIO 引脚按照预先配置的 GPIOTE 任务动作进行操作,例如改变引脚电平。  

总结 该函数通过一系列的断言检查确保传入的 GPIO 引脚是有效的且已被 GPIOTE 模块使用,然后根据引脚信息获取对应的 GPIOTE 任务地址,最后触发该任务,实现对 GPIO 引脚的硬件级操作。这种设计有助于提高代码的健壮性和可靠性,避免在不合法的情况下触发任务。

主函数中,只需要每隔 500ms 的使能一次任务输出,
实验下载到青云 nrf52840 开发板后的实验现象如下: LED3 灯会对应 500ms 时间翻转闪烁,
LED4 会保持常亮。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com