文章目录
GPIO的基本操作
首先包含头文件,该头文件定了GPIO的相关定义
#include "nrf_gpio.h"
函数采用内联函数的形式定义
常用的函数如下:
//配置为输出模式
__STATIC_INLINE void nrf_gpio_cfg_output(uint32_t pin_number);
//配饰为输入模式
__STATIC_INLINE void nrf_gpio_cfg_input(uint32_t pin_number, nrf_gpio_pin_pull_t pull_config);
//复位引脚
__STATIC_INLINE void nrf_gpio_cfg_default(uint32_t pin_number);
//引脚置高
__STATIC_INLINE void nrf_gpio_pin_set(uint32_t pin_number);
//引脚置低
__STATIC_INLINE void nrf_gpio_pin_clear(uint32_t pin_number);
//翻转引脚
__STATIC_INLINE void nrf_gpio_pin_toggle(uint32_t pin_number);
//读取引脚电平
__STATIC_INLINE uint32_t nrf_gpio_pin_read(uint32_t pin_number);
延时函数
随便添加一下延时函数吧
#include "nrf_delay.h"
//延时函数包含了微妙延时和毫秒延时
#define nrf_delay_us(us_time) NRFX_DELAY_US(us_time);
__STATIC_INLINE void nrf_delay_ms(uint32_t ms_time);
GPIOTE,操作寄存器
事件模式就是配置中断下面代码配置了GPIO引脚按键的中断模式
void EXIT_KEY_Init(void)
{
nrf_gpio_cfg_input(KEY_0,NRF_GPIO_PIN_PULLUP);//设置管脚位上拉输入
nrf_gpio_cfg_input(KEY_1,NRF_GPIO_PIN_PULLUP);//设置管脚位上拉输入
NVIC_EnableIRQ(GPIOTE_IRQn);//中断嵌套设置
NRF_GPIOTE->CONFIG[0] = (GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos)//下降沿触发
| (11 << GPIOTE_CONFIG_PSEL_Pos) //引脚11
| (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos);//事件模式
NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_IN0_Set << GPIOTE_INTENSET_IN0_Pos;// 使能中断类型:
NRF_GPIOTE->CONFIG[1] = (GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos)//下降沿触发
| (12<< GPIOTE_CONFIG_PSEL_Pos) //引脚12
| (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos);//事件模式
NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_IN1_Set << GPIOTE_INTENSET_IN1_Pos;// 使能中断类型:
}
void GPIOTE_IRQHandler(void)
{
if(nrf_gpio_pin_read(KEY_0)== 0)
{
if ((NRF_GPIOTE->EVENTS_IN[0] == 1) &&
(NRF_GPIOTE->INTENSET & GPIOTE_INTENSET_IN0_Msk))
{
NRF_GPIOTE->EVENTS_IN[0] = 0; //中断事件清零.
Delay(10000);
if(nrf_gpio_pin_read(KEY_0)== 0)
{
LED1_Toggle();//led灯翻转
}
}
}
if(nrf_gpio_pin_read(KEY_1)== 0)
{
if ((NRF_GPIOTE->EVENTS_IN[1] == 1) &&
(NRF_GPIOTE->INTENSET & GPIOTE_INTENSET_IN1_Msk))
{
NRF_GPIOTE->EVENTS_IN[1] = 0; //中断事件清零.
LED2_Toggle();//led灯翻转
}
}
}
GPIO 操作驱动库
//GPIOTE 初始化函数
#define nrf_drv_gpiote_init nrfx_gpiote_init
//输出配置为任务
#define nrf_drv_gpiote_out_init nrfx_gpiote_out_init
#define nrf_drv_gpiote_out_task_enable nrfx_gpiote_out_task_enable
//输入配置为 事件模式
#define nrf_drv_gpiote_in_init nrfx_gpiote_in_init
#define nrf_drv_gpiote_in_event_enable nrfx_gpiote_in_event_enable
//配置
ret_code_t err_code;
err_code = nrf_drv_gpiote_init();
APP_ERROR_CHECK(err_code);
nrf_drv_gpiote_out_config_t out_config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(true);
err_code = nrf_drv_gpiote_out_init(PIN_OUT, &out_config);
APP_ERROR_CHECK(err_code);
nrf_drv_gpiote_out_task_enable(PIN_OUT);
nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(true);
in_config.pull = NRF_GPIO_PIN_PULLUP;
err_code = nrf_drv_gpiote_in_init(PIN_IN, &in_config, in_pin_handler);
APP_ERROR_CHECK(err_code);
nrf_drv_gpiote_in_event_enable(PIN_IN, true);
下面我们对以上函数逐个说明
函数定义在 #include <nrfx_gpiote.h>
1. nrf_drv_gpiote_init
nrfx_err_t nrfx_gpiote_init(void)
{
nrfx_err_t err_code;
if (m_cb.state != NRFX_DRV_STATE_UNINITIALIZED)
{
err_code = NRFX_ERROR_INVALID_STATE;
NRFX_LOG_WARNING("Function: %s, error code: %s.",
__func__,
NRFX_LOG_ERROR_STRING_GET(err_code));
return err_code;
}
uint8_t i;
for (i = 0; i < NUMBER_OF_PINS; i++)
{
pin_in_use_clear(i);
}
for (i = 0; i < (GPIOTE_CH_NUM + NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS); i++)
{
channel_free(i);
}
memset(m_cb.configured_pins, 0, sizeof(m_cb.configured_pins));
NRFX_IRQ_PRIORITY_SET(GPIOTE_IRQn, NRFX_GPIOTE_CONFIG_IRQ_PRIORITY);
NRFX_IRQ_ENABLE(GPIOTE_IRQn);
nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_PORT);
nrf_gpiote_int_enable(GPIOTE_INTENSET_PORT_Msk);
m_cb.state = NRFX_DRV_STATE_INITIALIZED;
err_code = NRFX_SUCCESS;
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
return err_code;
}
首先判断是否已经定义了驱动库if (m_cb.state != NRFX_DRV_STATE_UNINITIALIZED)
清除掉所有引脚初始化pin_in_use_clear(i);
释放所有通道channel_free(i);
设置中断,并配置优先级NRFX_IRQ_PRIORITY_SET(GPIOTE_IRQn, NRFX_GPIOTE_CONFIG_IRQ_PRIORITY);NRFX_GPIOTE_CONFIG_IRQ_PRIORITY);
使能中断NRFX_IRQ_ENABLE(GPIOTE_IRQn);
清除事件标志nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_PORT);
使能通道事件nrf_gpiote_int_enable(GPIOTE_INTENSET_PORT_Msk);
修改状态m_cb.state = NRFX_DRV_STATE_INITIALIZED;
2. 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(pin < NUMBER_OF_PINS);
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;
}
判断引脚是否初始化完成if (pin_in_use(pin))
判断引脚是否存在task中if (p_config->task_pin)
为GPIOTE分配通道 nrf_gpiote_task_configure
根据参数设置引脚电平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);
3. nrf_drv_gpiote_out_task_enable
使能任务模式
4. nrf_drv_gpiote_in_init
nrfx_err_t nrfx_gpiote_in_init(nrfx_gpiote_pin_t pin,
nrfx_gpiote_in_config_t const * p_config,
nrfx_gpiote_evt_handler_t evt_handler)
{
NRFX_ASSERT(pin < NUMBER_OF_PINS);
nrfx_err_t err_code = NRFX_SUCCESS;
/* Only one GPIOTE channel can be assigned to one physical pin. */
if (pin_in_use_by_gpiote(pin))
{
err_code = NRFX_ERROR_INVALID_STATE;
}
else
{
int8_t channel = channel_port_alloc(pin, evt_handler, p_config->hi_accuracy);
if (channel != NO_CHANNELS)
{
if (!p_config->skip_gpio_setup)
{
if (p_config->is_watcher)
{
nrf_gpio_cfg_watcher(pin);
}
else
{
nrf_gpio_cfg_input(pin, p_config->pull);
}
pin_configured_set(pin);
}
if (p_config->hi_accuracy)
{
nrf_gpiote_event_configure((uint32_t)channel, pin, p_config->sense);
}
else
{
m_cb.port_handlers_pins[channel -
GPIOTE_CH_NUM] |= (p_config->sense) << SENSE_FIELD_POS;
}
}
else
{
err_code = NRFX_ERROR_NO_MEM;
}
}
NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
return err_code;
}
5. nrf_drv_gpiote_in_event_enable
使能事件模式
示例代码(附注释)
在sdk_config,h中使能宏定义GPIOTE
可使用Configuration Wizard可视化配置,使能nRF_Drivers 下的 GPIOTE_ENABLED
和 NRFX_GPIOTE_ENABLED
// <e> GPIOTE_ENABLED - nrf_drv_gpiote - GPIOTE peripheral driver - legacy layer
//==========================================================
#ifndef GPIOTE_ENABLED
#define GPIOTE_ENABLED 1
#endif
// <o> GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS - Number of lower power input pins
#ifndef GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS
#define GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS 1
#endif
// <o> GPIOTE_CONFIG_IRQ_PRIORITY - Interrupt priority
// <i> Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice
// <0=> 0 (highest)
// <1=> 1
// <2=> 2
// <3=> 3
// <4=> 4
// <5=> 5
// <6=> 6
// <7=> 7
#ifndef GPIOTE_CONFIG_IRQ_PRIORITY
#define GPIOTE_CONFIG_IRQ_PRIORITY 7
#endif
// </e>
// <e> NRFX_GPIOTE_ENABLED - nrfx_gpiote - GPIOTE peripheral driver
//==========================================================
#ifndef NRFX_GPIOTE_ENABLED
#define NRFX_GPIOTE_ENABLED 1
#endif
// <o> NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS - Number of lower power input pins
#ifndef NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS
#define NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS 1
#endif
// <o> NRFX_GPIOTE_CONFIG_IRQ_PRIORITY - Interrupt priority
// <0=> 0 (highest)
// <1=> 1
// <2=> 2
// <3=> 3
// <4=> 4
// <5=> 5
// <6=> 6
// <7=> 7
#ifndef NRFX_GPIOTE_CONFIG_IRQ_PRIORITY
#define NRFX_GPIOTE_CONFIG_IRQ_PRIORITY 7
#endif
// <e> NRFX_GPIOTE_CONFIG_LOG_ENABLED - Enables logging in the module.
//==========================================================
#ifndef NRFX_GPIOTE_CONFIG_LOG_ENABLED
#define NRFX_GPIOTE_CONFIG_LOG_ENABLED 0
#endif
// <o> NRFX_GPIOTE_CONFIG_LOG_LEVEL - Default Severity level
// <0=> Off
// <1=> Error
// <2=> Warning
// <3=> Info
// <4=> Debug
#ifndef NRFX_GPIOTE_CONFIG_LOG_LEVEL
#define NRFX_GPIOTE_CONFIG_LOG_LEVEL 3
#endif
// <o> NRFX_GPIOTE_CONFIG_INFO_COLOR - ANSI escape code prefix.
// <0=> Default
// <1=> Black
// <2=> Red
// <3=> Green
// <4=> Yellow
// <5=> Blue
// <6=> Magenta
// <7=> Cyan
// <8=> White
#ifndef NRFX_GPIOTE_CONFIG_INFO_COLOR
#define NRFX_GPIOTE_CONFIG_INFO_COLOR 0
#endif
// <o> NRFX_GPIOTE_CONFIG_DEBUG_COLOR - ANSI escape code prefix.
// <0=> Default
// <1=> Black
// <2=> Red
// <3=> Green
// <4=> Yellow
// <5=> Blue
// <6=> Magenta
// <7=> Cyan
// <8=> White
#ifndef NRFX_GPIOTE_CONFIG_DEBUG_COLOR
#define NRFX_GPIOTE_CONFIG_DEBUG_COLOR 0
#endif
// </e>
// </e>
主函数代码如下;
#include <stdbool.h>
#include "nrf.h"
#include "nrf_drv_gpiote.h"
#include "app_error.h"
#include "boards.h"
#include "nrf_delay.h"
//按键的中断函数,在nrf_drv_gpiote_in_init(BSP_BUTTON_0,&in_config,in_handle_event);中定义
void in_handle_event(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
if(pin == BSP_BUTTON_0)
{
nrf_delay_ms(50);//消抖
if(0 == nrf_gpio_pin_read(BSP_BUTTON_0))//下降沿
{
nrf_drv_gpiote_out_task_trigger(BSP_LED_0);//翻转LED
nrf_drv_gpiote_out_task_trigger(BSP_LED_1);
}
}
}
//GPIOTE初始化函数
static void gpiote_init(void)
{
ret_code_t err_code;
/*初始化GPIOTE*/
err_code = nrf_drv_gpiote_init();
APP_ERROR_CHECK(err_code);
/*初始化BSP_LED_0的task模式*/
nrfx_gpiote_out_config_t out_config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(true);//翻转模式
err_code = nrf_drv_gpiote_out_init(BSP_LED_0,&out_config);
APP_ERROR_CHECK(err_code);
nrf_drv_gpiote_out_task_enable(BSP_LED_0);
/*初始化BSP_LED_1的task模式*/
err_code = nrf_drv_gpiote_out_init(BSP_LED_1,&out_config);
APP_ERROR_CHECK(err_code);
nrf_drv_gpiote_out_task_enable(BSP_LED_1);
/*初始化BSP_BUTTON_0的事件模式*/
nrfx_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(false);//下降沿触发中断
in_config.pull = NRF_GPIO_PIN_PULLUP;//按键上拉,默认引脚是NOPULL
err_code = nrf_drv_gpiote_in_init(BSP_BUTTON_0,&in_config,in_handle_event);//定义中断函数入口地址
APP_ERROR_CHECK(err_code);
nrf_drv_gpiote_in_event_enable(BSP_BUTTON_0,true);
}
int main(void)
{
gpiote_init();
while(1)
{
// nrf_drv_gpiote_out_task_trigger(BSP_LED_0);
nrf_delay_ms(1000);
}
}