续前一篇文章。
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