12、nRF52XX蓝牙学习(GPIOTE任务触发LED)
void GPIOTE_TASK_Init(void)
{
NVIC_EnableIRQ(GPIOTE_IRQn);//中断嵌套设置
NRF_GPIOTE->CONFIG[0] = (GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos)
| (GPIOTE0 << GPIOTE_CONFIG_PSEL_Pos)
| (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos);
NRF_GPIOTE->CONFIG[1] = (GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos)
| (GPIOTE1<< GPIOTE_CONFIG_PSEL_Pos)
| (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos);
}
包含头文件为:
#ifndef __GPIOTE_H
#define __GPIOTE_H
#include "nrf52840.h"
#define GPIOTE0 13
#define GPIOTE1 14
void GPIOTE_TASK_Init(void);
#endif /* __EXIT_H */
主函数
#include "nrf52840.h"
#include "nrf_gpio.h"
#include "GPIOTE.h"
#include "led.h"
#include "nrf_delay.h"
int main(void)
{
/*配置按键中断*/
GPIOTE_TASK_Init();
while(1)
{
//触发输出任务模式
NRF_GPIOTE->TASKS_OUT[0]=1;
NRF_GPIOTE->TASKS_OUT[1]=1;
nrf_delay_ms(500);
}
}
以下是对GPIOTE_TASK_Init 函数解释:
整体功能概述
GPIOTE_TASK_Init 函数的主要作用是对通用外设中断和事件(GPIOTE)模块进行初始化配置。具体来说,它会使能 GPIOTE 中断,并且对 GPIOTE 的两个通道(CONFIG[0] 和 CONFIG[1])进行配置,设置它们的极性、选择的引脚以及工作模式。
NVIC_EnableIRQ(GPIOTE_IRQn);
• NVIC 是嵌套向量中断控制器(Nested Vectored Interrupt Controller)的缩写,它负责管理和控制微控制器中的中断。
• NVIC_EnableIRQ(GPIOTE_IRQn) 这行代码的作用是使能 GPIOTE 模块的中断。当 GPIOTE 模块检测到符合配置条件的事件时,就会触发中断,从而执行相应的中断服务程序。GPIOTE_IRQn 是 GPIOTE 中断的中断号。
NRF_GPIOTE->CONFIG[0] = (GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos)
| (GPIOTE0 << GPIOTE_CONFIG_PSEL_Pos)
| (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos);
• NRF_GPIOTE 是一个指向 GPIOTE 模块寄存器结构体的指针,通过它可以访问和配置 GPIOTE 模块的各个寄存器。此结构体定义如下 :
#define NRF_GPIOTE ((NRF_GPIOTE_Type*) NRF_GPIOTE_BASE)
typedef struct { //!< (@ 0x40006000) GPIOTE Structure
__OM uint32_t TASKS_OUT[8]; //< (@ 0x00000000) Description collection: Task for writing to pin
// specified in CONFIG[n].PSEL. Action on pin
// is configured in CONFIG[n].POLARITY.
__IM uint32_t RESERVED[4];
__OM uint32_t TASKS_SET[8]; //< (@ 0x00000030) Description collection: Task for writing to pin
// specified in CONFIG[n].PSEL. Action on pin
// is to set it high.
__IM uint32_t RESERVED1[4];
__OM uint32_t TASKS_CLR[8]; //< (@ 0x00000060) Description collection: Task for writing to pin
// specified in CONFIG[n].PSEL. Action on pin
// is to set it low.
__IM uint32_t RESERVED2[32];
__IOM uint32_t EVENTS_IN[8]; //< (@ 0x00000100) Description collection: Event generated from
// pin specified in CONFIG[n].PSEL
__IM uint32_t RESERVED3[23];
__IOM uint32_t EVENTS_PORT; //< (@ 0x0000017C) Event generated from multiple input GPIO pins
// with SENSE mechanism enabled
__IM uint32_t RESERVED4[97];
__IOM uint32_t INTENSET; //< (@ 0x00000304) Enable interrupt
__IOM uint32_t INTENCLR; //< (@ 0x00000308) Disable interrupt
__IM uint32_t RESERVED5[129];
__IOM uint32_t CONFIG[8]; //< (@ 0x00000510) Description collection: Configuration for OUT[n],
// SET[n], and CLR[n] tasks and IN[n] event
} NRF_GPIOTE_Type; //< Size = 1328 (0x530)
• CONFIG 是一个数组,用于配置 GPIOTE 的不同通道。这里配置的是通道 0(CONFIG[0])。 ◦ GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos:
将 GPIOTE_CONFIG_POLARITY_Toggle 这个表示极性设置的常量左移 GPIOTE_CONFIG_POLARITY_Pos 位,目的是将其放置到 CONFIG 寄存器中极性配置的正确位置。GPIOTE_CONFIG_POLARITY_Toggle 表示引脚电平翻转时触发事件,即从高电平到低电平或从低电平到高电平的变化都会触发。
GPIOTE0 << GPIOTE_CONFIG_PSEL_Pos:将 GPIOTE0 这个表示引脚选择的常量左移 GPIOTE_CONFIG_PSEL_Pos 位,将其放置到 CONFIG 寄存器中引脚选择的正确位置。GPIOTE0 代表要配置的具体 GPIO 引脚。
GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos:将 GPIOTE_CONFIG_MODE_Task 这个表示工作模式的常量左移 GPIOTE_CONFIG_MODE_Pos 位,将其放置到 CONFIG 寄存器中工作模式配置的正确位置。GPIOTE_CONFIG_MODE_Task 表示该通道工作在任务模式下。
最后使用按位或运算符 | 将这三个配置项组合起来,并赋值给 NRF_GPIOTE->CONFIG[0],完成通道 0 的配置。
NRF_GPIOTE->CONFIG[1] = (GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos)
| (GPIOTE1<< GPIOTE_CONFIG_PSEL_Pos)
| (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos);
• 这行代码与前面配置通道 0 的逻辑类似,只不过这里配置的是通道 1(CONFIG[1])。 ◦ GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos:表示将引脚电平从高电平变为低电平时触发事件。
GPIOTE1 << GPIOTE_CONFIG_PSEL_Pos:选择 GPIOTE1 引脚进行配置。 GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos:同样将该通道设置为任务模式。
总结 这段代码通过使能 GPIOTE 中断,并对 GPIOTE 的两个通道进行配置,实现了对不同 GPIO 引脚的事件触发极性和工作模式的设置。通道 0 配置为引脚电平翻转时触发事件,通道 1 配置为引脚电平从高到低变化时触发事件,且两个通道都工作在任务模式下。
主函数代码解析:
int main(void)
{
/*配置按键中断*/
GPIOTE_TASK_Init();
while(1)
{
//触发输出任务模式
NRF_GPIOTE->TASKS_OUT[0]=1;
NRF_GPIOTE->TASKS_OUT[1]=1;
nrf_delay_ms(500);
}
}
TASKS_OUT 是一个数组,用于触发 GPIOTE 模块的输出任务。NRF_GPIOTE->TASKS_OUT[0]=1; 这行代码将 TASKS_OUT[0] 寄存器的值设置为 1,从而触发 GPIOTE 通道 0 的输出任务。同理,NRF_GPIOTE->TASKS_OUT[1]=1; 触发 GPIOTE 通道 1 的输出任务。当这些任务被触发时,会根据之前在 GPIOTE_TASK_Init 函数中对通道的配置来执行相应的操作,比如改变引脚的电平状态等。
