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

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

续前一篇文章。

3、nrfx_gpiote_in_event_enable

void nrfx_gpiote_in_event_enable(nrfx_gpiote_pin_t pin, bool int_enable)
{
    NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
    NRFX_ASSERT(pin_in_use_by_gpiote(pin));
    if (pin_in_use_by_port(pin))
    {
        nrf_gpiote_polarity_t polarity =
            port_handler_polarity_get(channel_port_get(pin) - GPIOTE_CH_NUM);
        nrf_gpio_pin_sense_t sense;
        if (polarity == NRF_GPIOTE_POLARITY_TOGGLE)
        {
            /* read current pin state and set for next sense to oposit */
            sense = (nrf_gpio_pin_read(pin)) ?
                    NRF_GPIO_PIN_SENSE_LOW : NRF_GPIO_PIN_SENSE_HIGH;
        }
        else
        {
            sense = (polarity == NRF_GPIOTE_POLARITY_LOTOHI) ?
                    NRF_GPIO_PIN_SENSE_HIGH : NRF_GPIO_PIN_SENSE_LOW;
        }
        nrf_gpio_cfg_sense_set(pin, sense);
    }
    else if (pin_in_use_by_te(pin))
    {
        int32_t             channel = (int32_t)channel_port_get(pin);
        nrf_gpiote_events_t event   = TE_IDX_TO_EVENT_ADDR((uint32_t)channel);

        nrf_gpiote_event_enable((uint32_t)channel);

        nrf_gpiote_event_clear(event);
        if (int_enable)
        {
            nrfx_gpiote_evt_handler_t handler = channel_handler_get((uint32_t)channel_port_get(pin));
            // Enable the interrupt only if event handler was provided.
            if (handler)
            {
                nrf_gpiote_int_enable(1 << channel);
            }
        }
    }
}

一、函数概述
nrfx_gpiote_in_event_enable 函数的主要功能是为指定的 GPIO 引脚启用 GPIOTE(通用外设中断和事件)输入事件。
该函数会根据引脚的使用情况(是由端口处理还是由定时器事件处理)来配置相应的引脚感应和事件中断。 
函数参数
pin:类型为 nrfx_gpiote_pin_t,表示要启用事件的 GPIO 引脚编号。 
int_enable:布尔类型,用于决定是否启用该引脚的中断功能。  
二、函数实现步骤
1. 断言检查


NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
NRFX_ASSERT(pin_in_use_by_gpiote(pin));


 NRFX_ASSERT(nrf_gpio_pin_present_check(pin)):使用断言确保传入的引脚 pin 是有效的,nrf_gpio_pin_present_check 函数用于检查该引脚是否存在于硬件中。如果检查失败,程序会触发断言错误。
NRFX_ASSERT(pin_in_use_by_gpiote(pin)):确保该引脚已经被 GPIOTE 使用,如果未被使用,程序会触发断言错误。  
2. 处理引脚由端口使用的情况


 if (pin_in_use_by_port(pin))
{
    nrf_gpiote_polarity_t polarity =
        port_handler_polarity_get(channel_port_get(pin) - GPIOTE_CH_NUM);
    nrf_gpio_pin_sense_t sense;
    if (polarity == NRF_GPIOTE_POLARITY_TOGGLE)
    {
        sense = (nrf_gpio_pin_read(pin)) ?
                NRF_GPIO_PIN_SENSE_LOW : NRF_GPIO_PIN_SENSE_HIGH;
    }
    else
    {
        sense = (polarity == NRF_GPIOTE_POLARITY_LOTOHI) ?
                NRF_GPIO_PIN_SENSE_HIGH : NRF_GPIO_PIN_SENSE_LOW;
    }
    nrf_gpio_cfg_sense_set(pin, sense);
}

(1)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;

(2)port_handler_polarity_get函数定义如下 :

static nrf_gpiote_polarity_t port_handler_polarity_get(uint32_t handler_idx)
{
    uint8_t pin_and_polarity = (uint8_t)m_cb.port_handlers_pins[handler_idx];
    return (nrf_gpiote_polarity_t)((pin_and_polarity & POLARITY_FIELD_MASK) >> POLARITY_FIELD_POS);
}

(3)m_cb是一个静态变量,定义如下 :

static gpiote_control_block_t m_cb;

其类型为结构体类型gpiote_control_block_t,该类型是在nrfx_gpiote.c中定义的:

typedef struct
{
    nrfx_gpiote_evt_handler_t handlers[GPIOTE_CH_NUM + NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS];
    int8_t                    pin_assignments[MAX_PIN_NUMBER];
    int8_t                    port_handlers_pins[NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS];
    uint8_t                   configured_pins[((MAX_PIN_NUMBER)+7) / 8];
    nrfx_drv_state_t          state;
} gpiote_control_block_t;

此结构体的解释如下:

,它用于管理和控制通用外设中断和事件(GPIOTE)模块。

下面详细解释结构体中的每个成员:

整体用途 gpiote_control_block_t 结构体作为 GPIOTE 模块的控制块,负责存储和管理与 GPIOTE 操作相关的各种信息,包括事件处理函数、引脚分配、端口处理状态、引脚配置状态以及驱动程序的整体状态。

结构体成员解释

1. nrfx_gpiote_evt_handler_t handlers[GPIOTE_CH_NUM + NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS];

• 类型:nrfx_gpiote_evt_handler_t 是一个函数指针类型,它指向处理 GPIOTE 事件的函数。该数组存储了所有 GPIOTE 通道(包括普通通道和低功耗事件通道)对应的事件处理函数。

• 用途:当特定的 GPIOTE 通道发生事件时,系统会调用该通道对应的事件处理函数来处理事件。GPIOTE_CH_NUM 代表普通 GPIOTE 通道的数量,NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS 表示低功耗事件通道的数量。  

2. int8_t pin_assignments[MAX_PIN_NUMBER];

• 类型:int8_t 类型的数组,每个元素存储一个 8 位有符号整数。

• 用途:该数组用于记录每个 GPIO 引脚所分配的 GPIOTE 通道编号。MAX_PIN_NUMBER 是系统中可用的最大 GPIO 引脚数量。数组的索引对应引脚编号,数组元素的值为该引脚分配的 GPIOTE 通道编号。如果某个引脚未分配通道,通常用一个特殊值(如 -1)表示。  

3. int8_t port_handlers_pins[NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS];

• 类型:int8_t 类型的数组。

• 用途:此数组用于存储与低功耗事件通道相关的引脚信息。每个元素对应一个低功耗事件通道,可能存储该通道所关联的引脚编号或其他相关信息。  

4. uint8_t configured_pins[((MAX_PIN_NUMBER)+7) / 8];

• 类型:uint8_t 类型的数组,即无符号 8 位整数数组。

• 用途:这是一个位图数组,用于记录哪些 GPIO 引脚已经被配置为 GPIOTE 功能。通过使用位图,每个字节可以表示 8 个引脚的配置状态。((MAX_PIN_NUMBER)+7) / 8 确保数组大小足够存储所有引脚的状态。例如,如果某个引脚已配置,则对应位图中的相应位被设置为 1;否则为 0。  5. nrfx_drv_state_t state;

• 类型:nrfx_drv_state_t 是一个自定义的枚举类型,用于表示 GPIOTE 驱动程序的状态。

• 用途:该成员变量记录了 GPIOTE 驱动程序的当前状态,如初始化、运行、停止等。通过检查这个状态变量,系统可以了解 GPIOTE 模块的工作状态,并根据需要进行相应的操作。  总结 gpiote_control_block_t 结构体整合了管理 GPIOTE 模块所需的关键信息,通过这些成员变量,系统可以有效地分配通道、处理事件、跟踪引脚配置状态以及管理驱动程序的整体状态。

(4) pin_in_use_by_port(pin):

检查该引脚是否由端口处理。
 port_handler_polarity_get(channel_port_get(pin) - GPIOTE_CH_NUM):获取该引脚对应的端口处理极性。 
 极性判断: 
 如果极性为 NRF_GPIOTE_POLARITY_TOGGLE,则读取当前引脚的状态,根据状态设置感应为相反的电平(如果当前引脚为高电平,则感应设置为低电平;反之亦然)。 
 如果极性为 NRF_GPIOTE_POLARITY_LOTOHI,则感应设置为高电平;如果极性为其他值(可理解为 NRF_GPIOTE_POLARITY_HITOLO),则感应设置为低电平。   
 nrf_gpio_cfg_sense_set(pin, sense):将计算得到的感应设置应用到该引脚上。

 
(5). 处理引脚由定时器事件使用的情况
  else if (pin_in_use_by_te(pin))
{
    int32_t             channel = (int32_t)channel_port_get(pin);
    nrf_gpiote_events_t event   = TE_IDX_TO_EVENT_ADDR((uint32_t)channel);

    nrf_gpiote_event_enable((uint32_t)channel);

    nrf_gpiote_event_clear(event);
    if (int_enable)
    {
        nrfx_gpiote_evt_handler_t handler = channel_handler_get((uint32_t)channel_port_get(pin));
        // Enable the interrupt only if event handler was provided.
        if (handler)
        {
            nrf_gpiote_int_enable(1 << channel);
        }
    }
}


 pin_in_use_by_te(pin):检查该引脚是否由定时器事件处理。 
 channel_port_get(pin):获取该引脚对应的通道编号。
 TE_IDX_TO_EVENT_ADDR((uint32_t)channel):将通道编号转换为对应的 GPIOTE 事件地址。 
 nrf_gpiote_event_enable((uint32_t)channel):启用该通道的 GPIOTE 事件。 
 nrf_gpiote_event_clear(event):清除该事件的状态标志。 
 中断启用判断: 
 如果 int_enable 为 true,则获取该通道对应的事件处理函数 handler。 
 只有当事件处理函数存在时,才调用 nrf_gpiote_int_enable(1 << channel) 启用该通道的中断。    
 总结 该函数的核心是根据引脚的使用情况(端口处理或定时器事件处理)来配置引脚的感应和事件中断。
 对于端口处理的引脚,根据极性设置感应;对于定时器事件处理的引脚,启用事件、清除事件标志,并根据需要启用中断。通过这些步骤,确保指定引脚的 GPIOTE 输入事件能够正常工作。

void nrfx_gpiote_in_event_enablevoid nrfx_gpiote_in_event_enable

相关文章:

  • Spring 服务调用接口时,提示You should be redirected automatically to target URL:
  • 7.第二阶段x64游戏实战-分析人物属性
  • 软件需求分析习题汇编
  • PostGreSQL/openGauss表膨胀处理
  • Postman测试
  • [创业之路-364]:穿透表象:企业投资的深层逻辑与误区规避
  • 程序化广告行业(69/89):电商素材制作与展示策略解析
  • 程序化广告行业(71/89):ABTester与Tag Manager系统深度解析
  • Android学习总结之数据结构篇
  • <tauri><rust><GUI>基于rust和tauri,将tauri程序打包为window系统可安装的安装包(exe、msi)
  • TRUMPF PFG-RF RF Generators Operating instructions 操作使用说明
  • 【android bluetooth 框架分析 01】【关键线程 1】【关键线程介绍】
  • 2025 年江苏交安安全员考试:借助本地培训资源提升能力​
  • 集合计算高级函数
  • 图库项目开发 阶段二-图片优化
  • 数据结构与算法——链表OJ题详解(1)
  • 基于YOLO的半自动化标注方法:提升铁路视频缺陷检测效率
  • 如何避免“过度承诺”导致的验收失败
  • 大模型论文:BART
  • 使用 Spring Boot 快速构建企业微信 JS-SDK 权限签名后端服务
  • 做网站会用到的色彩代码单词/谷歌查询关键词的工具叫什么
  • 公司网站一般去哪里做/如何创建自己的卡网
  • 网站如何做传输网盘/网站开通
  • 大连比较好的的网站建设公司/seo优化易下拉排名
  • 动态网站开发与全程实例pdf/近三天新闻50字左右
  • 简洁网站倒计时代码/比较好用的搜索引擎