nRF52832开发之GPIOTE浅析

一、GPIOTE原理

1.概念
1)nRF52832的GPIO只能作为通用的输入输出使能,它作为输入时无法产生中断的,这时候就需要通过GPIOTE实现这种效果了;
2)GPIOTE(GPIO任务和事件),是在GPIO的基础上引入任务和事件;
3)通过任务和事件来操作IO,任务是针对输出的,它可以让IO输出不同的动作,而事件针对输入,IO的状态变化会置位事件寄存器,从而产生事件中断。

2.原理
1)nRF52832的GPIOTE共有8个通道,每个通道都可以分配给一个引脚,分配的引脚可以配置为任务模式或事件模式;
2)GPIOTE每个通道都有SET、CLR和OUT任务,其中SET任务让引脚输出高电平,CLR任务让引脚输出低电平,OUT任务可以通过配置对引脚执行置位、清零和翻转操作;
3)GPIOTE每个通道的事件都可以配置为三种输入状态:上升沿、下降沿和任意电平跳变;
4)任务和事件通过CONFIG[n](n=0~7)寄存器配置,每个CONFIG[n]寄存器可配置一个对应编号OUT[n](n=0~7)任务寄存器和IN[n]事件寄存器;
5)当通过CONFIG寄存器配置某个引脚由SET、CLR和OUT任务寄存器或IN事件寄存器控制后,该引脚只能被GPIOTE模块写操作,正常的GPIO写入无效;
6)当在同一个GPIOTE通道中同时触发了有冲突的任务,这些任务的执行级别由高到低依次为:OUT-->CLR-->SET;
7)GPIOTE除了8个通道外,还包含一个PORT事件,PORT事件是多个引脚通过GPIO DETECT信号产生的事件。

二、GPIOTE寄存器(n=0~7)

1.OUT任务寄存器
OUT[n]:对CONFIG[n].PSEL指定的引脚进行写操作,引脚动作由CONFIG[n].POLARITY中的配置决定

2.TASKS_SET任务寄存器
TASKS_SET[n]:对CONFIG[n].PSEL指定的引脚进行写操作,引脚动作为输出高电平

3.TASKS_CLR任务寄存器
TASKS_CLR[n]:对CONFIG[n].PSEL指定的引脚进行写操作,引脚动作为输出低电平

4.EVENT_IN事件寄存器
EVENT_IN[n]:CONFIG[n].PSEL指定的引脚产生的事件

5.通用寄存器
1)INTENSET:使能中断
2)INTENCLR:禁止中断
3)CONFIG[n]:OUT[n],SET[n],CLR[n]和IN[n]的配置

三、编程分析

sdk版本:nRF5_SDK_15.2.0_9412b96

1.GPIOTE输出流程
1)初始化GPIOTE模块
2)初始化GPIOTE输出引脚
3)是否使能任务模式

2.GPIOTE输入流程
1)初始化GPIOTE模块
2)配置引脚为GPIOTE输入
3)使能事件模式

3.相关库函数使用
//头文件:nrf_drv_gpiote.h
1)ret_code_t nrf_drv_gpiote_init(void)
功能:初始化GPIOTE模块
2)ret_code_t nrf_drv_gpiote_out_init(nrf_drv_gpiote_pin_t pin,nrf_drv_gpiote_out_config_t const *p_config)
功能:初始化GPIOTE输出引脚,输出引脚初始化设置中会设定引脚的动作(低电平到高电平、高电平到低电平或者翻转状态)和初始化状态(高电平或低电平)
3)void nrf_drv_gpiote_out_uninit(nrf_drv_gpiote_pin_t pin)
功能:释放GPIOTE输出引脚
4)void nrfx_gpiote_out_task_enable(nrfx_drv_gpiote_pin_t pin)
功能:使能GPIOTE输出引脚的任务模式
5)void nrfx_gpiote_out_task_disable(nrfx_drv_gpiote_pin_t pin)
功能:禁止GPIOTE输出引脚的任务模式
6)触发任务驱动引脚函数
1>nrf_drv_gpiote_set_task_trigger(nrf_drv_gpiote_pin_t pin)
功能:收到触发GPIOTE SET任务,触发后,对应的引脚输出高电平
2>nrf_drv_gpiote_clr_task_trigger(nrf_drv_gpiote_pin_t pin)
功能:收到触发GPIOTE CLR任务,触发后,对应的引脚输出低电平
3>nrf_drv_gpiote_out_task_trigger(nrf_drv_gpiote_pin_t pin)
功能:收到触发GPIOTE OUT任务,触发后,对应的引脚输出状态翻转

7)ret_code_t nrf_drv_gpiote_in_init(nrf_drv_gpiote_pin_t pin,nrf_drv_gpiote_in_config_t const *p_config,nrf_drv_gpiote_evt_handler_t evt_handler)
功能:初始化GPIOTE输入引脚,
8)void nrfx_gpiote_in_event_enable(nrfx_drv_gpiote_pin_t pin,bool int_enable)
功能:使能GPIOTE输入引脚

4.代码编写
1)GPIOTE输出流程实例

#include "boards.h"
#include "nrf_delay.h"
#include "nrf_drv_gpiote.h"

int main(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 config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(true);
	//初始化GPIOTE输出引脚
	err_code = nrf_drv_gpiote_out_init(LED_1,&config);
	APP_ERROR_CHECK(err_code);
	//使能任务模式
	nrf_drv_gpiote_out_task_enable(LED_1);
	
	while(true)
	{	//触发任务
		nrf_drv_gpiote_out_task_trigger(LED_1);
		nrf_delay_ms(150);
	}
	return 0;
}

2)GPIOTE输入流程实例

#include "boards.h"
#include "nrf_drv_gpiote.h"

//事件回调函数
void in_pin_handler(nrf_drv_gpiote_pin_t pin,nrf_gpiote_polarity_t action)
{
	if (pin == BUTTON_1)
		nrf_gpio_pin_toggle(LED_1);
	
	if (action == NRF_GPIOTE_POLARITY_HITOLO)
		nrf_gpio_pin_toggle(LED_2);
	else if (action == NRF_GPIOTE_POLARITY_LOTOHI)
		nrf_gpio_pin_toggle(LED_3);
	else if (action == NRF_GPIOTE_POLARITY_TOGGLE)
		nrf_gpio_pin_toggle(LED_4);
}

int main(void)
{
	ret_code_t err_code;
	//初始化开发板上的LED灯
	bsp_board_init(BSP_INIT_LEDS);
	//初始化GPIOTE模块
	err_code = nrf_drv_gpiote_init();
	APP_ERROR_CHECK(err_code);
	//配置下降沿产生事件
	//nrf_drv_gpiote_in_config_t config = GPIOTE_CONFIG_IN_SENSE_HITOLO(true);
	//配置上升沿产生事件,false表示
	nrf_drv_gpiote_in_config_t config = GPIOTE_CONFIG_IN_SENSE_LOTOHI(false);//true表示高精度,false表示低精度
	//配置任意电平变化产生事件
	//nrf_drv_gpiote_in_config_t config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(true);
	//配置引脚为内部上拉
	config.pull = NRF_GPIO_PIN_PULLUP;
	//配置引脚为GPIOTE输入
	err_code = nrf_drv_gpiote_in_init(BUTTON_1,&config,in_pin_handler);
	APP_ERROR_CHECK(err_code);
	//使能事件模式
	nrf_drv_gpiote_in_event_enable(BUTTON_1,true);
	while(true)
	{
	
	}
	return 0;
}
发布了81 篇原创文章 · 获赞 21 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_33575901/article/details/90041554