0%

【nRF52832】学习笔记 --> GPIOTE (TASK/EVENT)

😊 转载请全文转载,并标明文章出处

环境介绍

  • 操作系统: Window10 企业版
  • IDE开发环境: ARM_MDK5 (Keil5)
  • SDK版本: SDK_17.0.0
  • 硬件开发板: 官方开发板 PCA10040

GPIOTE (TASK/EVENT)

1. 概述介绍

  GPIOTE 驱动控制 GPIO 和 GPIOTE 外设,并配置和控制输出和输入引脚。可以将输出引脚配置为手动控制或者通过 GPIOTE 任务进行控制。输入引脚可以配置在不同模式下进行控制。

2. GPIOTE 功能

  nRF52832 的GPIOTE共有8个通道,每个通道否可以分配给一个引脚,分配的引脚可以配置为任务模式或时间模式。不能将某个引脚同事分配给多个GPIOTE通道,否则会导致无法预料的错误。

  • GPIOTE 每个通道有Set、Clear和Out三个任务,Set和Clear任务对引脚时固定操作,Out 任务可以引脚PIN执行以下操作:
    • Set (置位 输出高电平)
    • Clear (清零 输出低电平 )
    • Toggle (翻转)
  • GPIOTE 模块遵循以下输入条件之一,GPIOTE每个通道产生事件:
    • Rising edge (上升沿)
    • Falling edge (下降沿)
    • Any change (任意电平跳变)

3. PIN Events and Tasks (引脚事件和任务)

  • GPIOTE模块有许多任务和事件,可以配置GPIOTE模块对单个任务红外事件进行操作GPIO Pin。
  • 任务(Set[n]、Clr[n]、Out[n])可用于向单个引脚写入,而事件(IN[n])可有单个引脚输入处发生的变化生成。
  • GPIOTE通带被配置用于操作一个任务引脚时,引脚的初始状态时可以配置的,可以通过配置CONFIG[n]寄存器中OUTINIT来设置引脚初始化状态为高电平或低电平。
  • 同一个GPIOTE通道中同时触发了有冲突的任务,任务会安装优先级的顺序执行:
优先级 任务
1 OUT
2 CLEAR
3 SET

4. Port Event (端口事件)

  Port 是一个事件,可以从多个输入引脚使用GPIO检测信号的产生。P0.00~P0.31均可以触发Port事件,Port事件使用了GPIO外设的感知机制,也就是如果使用Port事件,必须操作GPIO外设,在GPIO外设中打开引脚的感知功能,注意Port事件寄存器时属于GPIOTE外设的。
  Port不需要任何时钟或者其他电源相关的外设,即使外设处于空闲状态,Port事件也可以使能。当CPU和所有外设处于IDLE状态时,Port是啊金可以将CPU从WFI或WFE类型休眠中,以及CPU空闲模式下唤醒,即在系统ON模式下实现最低的功耗。
  Port事件页可以作为唤醒源,将系统从System Off模式唤醒,但本质上还是使用了GPIO外设的感知机制唤醒系统。
  配置Port事件时,为了防止Port事件产生虚假的中断,用户应首先禁止Port事件中断,然后再配置Port事件,之后通过清零EVENTS_PORT寄存器清除事件,最后使能Port事件中断。

5. GPIOTE 代码实现

5.1 Sdk_config.h 配置
5.1.1 Registers (寄存器版本)

  如果配置寄存器版本的话,不许需要在Sdk_config.h文件中配置。

5.1.2 Library (库版本)
  1. 添加 GPIOTE 驱动文件 nrfx_gpiote.c ,SDK 路径目录:…\modules\nrfx\drivers\src\nrfx_gpiote.c

  2. 头文件引用 “nrf_drv_gpiote.h”。

  3. 添加头文件路径:

    • …\modules\nrfx\drivers\include
    • …\integration\nrfx\legacy
  4. Sdk_config.h 文件配置

    • Text Editor 配置

      • GPIOTE_ENABLED 0
      • GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS 4
      • GPIOTE_CONFIG_IRQ_PRIORITY 1
      • NRFX_GPIOTE_ENABLED 1
      • NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS 1
      • NRFX_GPIOTE_CONFIG_IRQ_PRIORITY 1
      • NRFX_GPIOTE_CONFIG_LOG_ENABLED 0
      • NRFX_GPIOTE_CONFIG_LOG_LEVEL 3
      • NRFX_GPIOTE_CONFIG_INFO_COLOR 0
      • NRFX_GPIOTE_CONFIG_DEBUG_COLOR 0
    • Configuration Wizard 配置

      GPIOTE

5.2 GPIOTE Registers (寄存器版本)
5.2.1 gpiote.h 配置
/*
* gpiote.h
*
* Created on: 2020-08-06
* Author: wuliZhao_ch
* Description: GPIOTE Interrupt Configuration
*/

#ifndef GPIOTE_H__
#define GPIOTE_H__

#include <stdbool.h>
#include <stdint.h>
#include "nrf52.h"
#include "nrf_gpio.h"
#include "nrf_drv_gpiote.h"
#include "app_error.h"

/* Register versions and library versions select */
// #define REGISTER_VERSION
#define LIBRARY_VERSION

/* BUTTON DEFINE */
#define PCA10040_BUTTON1 13
#define PCA10040_BUTTON2 14
#define PCA10040_BUTTON3 15
#define PCA10040_BUTTON4 16

/* LED PIN DEFINE */
#define PCA10040_LED1 17
#define PCA10040_LED2 18
#define PCA10040_LED3 19
#define PCA10040_LED4 20


//void GPIOTE_IRQHandler(void);
void gpiote_init(void);

#endif /* GPIOTE_H__ */
5.2.2 gpiote.c 配置
/*
* gpiote.c
*
* Created on: 2020-08-06
* Author: wuliZhao_ch
* Description: GPIOTE Interrupt Configuration
Register versions and library function versions implement GPIOTE
*/

#include "gpiote.h"

void gpiote_init(void)
{

nrf_gpio_cfg_input(PCA10040_BUTTON1, NRF_GPIO_PIN_PULLUP);
nrf_gpio_cfg_input(PCA10040_BUTTON2, NRF_GPIO_PIN_PULLUP);
nrf_gpio_cfg_input(PCA10040_BUTTON3, NRF_GPIO_PIN_PULLUP);
nrf_gpio_cfg_input(PCA10040_BUTTON4, NRF_GPIO_PIN_PULLUP);

NVIC_EnableIRQ(GPIOTE_IRQn); /* Enable Interrupt */

NRF_GPIOTE->CONFIG[0] = (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos) | (PCA10040_BUTTON1 << GPIOTE_CONFIG_PSEL_Pos) |(GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos);
NRF_GPIOTE->CONFIG[1] = (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos) | (PCA10040_BUTTON2 << GPIOTE_CONFIG_PSEL_Pos) |(GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos);
NRF_GPIOTE->CONFIG[2] = (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos) | (PCA10040_BUTTON3 << GPIOTE_CONFIG_PSEL_Pos) |(GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos);
NRF_GPIOTE->CONFIG[3] = (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos) | (PCA10040_BUTTON4 << GPIOTE_CONFIG_PSEL_Pos) |(GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos);

NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_IN0_Set << GPIOTE_INTENSET_IN0_Pos;
NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_IN1_Set << GPIOTE_INTENSET_IN1_Pos;
NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_IN2_Set << GPIOTE_INTENSET_IN2_Pos;
NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_IN3_Set << GPIOTE_INTENSET_IN3_Pos;

}


void GPIOTE_IRQHandler(void)
{
if(nrf_gpio_pin_read(PCA10040_BUTTON1)== 0)
{
if ((NRF_GPIOTE->EVENTS_IN[0] == 1) && (NRF_GPIOTE->INTENSET & GPIOTE_INTENSET_IN0_Msk))
{
NRF_GPIOTE->EVENTS_IN[0] = 0; //中断事件清零.

if(nrf_gpio_pin_read(PCA10040_BUTTON1)== 0)
{
nrf_gpio_pin_toggle(PCA10040_LED1);//led灯翻转
}
}
}

if(nrf_gpio_pin_read(PCA10040_BUTTON2)== 0)
{
if ((NRF_GPIOTE->EVENTS_IN[1] == 1) && (NRF_GPIOTE->INTENSET & GPIOTE_INTENSET_IN1_Msk))
{
NRF_GPIOTE->EVENTS_IN[1] = 0; //中断事件清零.

if(nrf_gpio_pin_read(PCA10040_BUTTON2)== 0)
{
nrf_gpio_pin_toggle(PCA10040_LED2);//led灯翻转
}
}
}

if(nrf_gpio_pin_read(PCA10040_BUTTON3)== 0)
{
if ((NRF_GPIOTE->EVENTS_IN[2] == 1) && (NRF_GPIOTE->INTENSET & GPIOTE_INTENSET_IN2_Msk))
{
NRF_GPIOTE->EVENTS_IN[2] = 0; // 中断事件清零.

if(nrf_gpio_pin_read(PCA10040_BUTTON3)== 0)
{
nrf_gpio_pin_toggle(PCA10040_LED3);// LED灯翻转
}
}
}

if(nrf_gpio_pin_read(PCA10040_BUTTON4)== 0)
{
if ((NRF_GPIOTE->EVENTS_IN[3] == 1) && (NRF_GPIOTE->INTENSET & GPIOTE_INTENSET_IN3_Msk))
{
NRF_GPIOTE->EVENTS_IN[3] = 0; //中断事件清零.

if(nrf_gpio_pin_read(PCA10040_BUTTON4)== 0)
{
nrf_gpio_pin_toggle(PCA10040_LED4);//LED灯翻转
}
}
}
}
5.3 GPIOTE Library (库版本)
5.3.1 gpiote.h 配置
/*
* gpiote.h
*
* Created on: 2020-08-06
* Author: wuliZhao_ch
* Description: GPIOTE Interrupt Configuration
*/

#ifndef GPIOTE_H__
#define GPIOTE_H__

#include <stdbool.h>
#include <stdint.h>
#include "nrf52.h"
#include "nrf_gpio.h"
#include "nrf_drv_gpiote.h"
#include "app_error.h"

/* Register versions and library versions select */
#define REGISTER_VERSION
//#define LIBRARY_VERSION

/* BUTTON DEFINE */
#define PCA10040_BUTTON1 13
#define PCA10040_BUTTON2 14
#define PCA10040_BUTTON3 15
#define PCA10040_BUTTON4 16

/* LED PIN DEFINE */
#define PCA10040_LED1 17
#define PCA10040_LED2 18
#define PCA10040_LED3 19
#define PCA10040_LED4 20

void GPIOTE_IRQHandler(void);
void gpiote_init(void);

#endif /* GPIOTE_H__ */
5.3.2 gpiote.c配置
/*
* gpiote.c
*
* Created on: 2020-08-06
* Author: wuliZhao_ch
* Description: GPIOTE Interrupt Configuration
Register versions and library function versions implement GPIOTE
*/
void in_gpiote_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
switch (pin)
{
case PCA10040_BUTTON1:
nrf_gpio_pin_toggle(PCA10040_LED1);
break;
case PCA10040_BUTTON2:
nrf_gpio_pin_toggle(PCA10040_LED2);
break;
case PCA10040_BUTTON3:
nrf_gpio_pin_toggle(PCA10040_LED3);
break;
case PCA10040_BUTTON4:
nrf_gpio_pin_toggle(PCA10040_LED4);
break;
default:
break;
}
}

void gpiote_init(void)
{
ret_code_t err_code;

err_code = nrf_drv_gpiote_init();
APP_ERROR_CHECK(err_code);

nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(true);
in_config.pull = NRF_GPIO_PIN_PULLUP;

err_code = nrf_drv_gpiote_in_init(PCA10040_BUTTON1, &in_config, in_gpiote_handler);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_gpiote_in_init(PCA10040_BUTTON2, &in_config, in_gpiote_handler);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_gpiote_in_init(PCA10040_BUTTON3, &in_config, in_gpiote_handler);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_gpiote_in_init(PCA10040_BUTTON4, &in_config, in_gpiote_handler);
APP_ERROR_CHECK(err_code);

nrf_drv_gpiote_in_event_enable(PCA10040_BUTTON1, true);
nrf_drv_gpiote_in_event_enable(PCA10040_BUTTON2, true);
nrf_drv_gpiote_in_event_enable(PCA10040_BUTTON3, true);
nrf_drv_gpiote_in_event_enable(PCA10040_BUTTON4, true);
}
5.4 MAIN.C 调用实现
#include <stdbool.h>
#include <stdint.h>

#include "nrf.h"
#include "nordic_common.h"
#include "boards.h"

#include "nrf_delay.h"
#include "nrf_drv_systick.h"
#include "nrf_drv_clock.h"
#include "nrf_drv_timer.h"

#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"

#include "nrf_pwr_mgmt.h"

/* wuliZhaoch Include File */
#include "led.h"
#include "timer.h"
#include "gpiote.h"


/**
* @brief Function for application main entry.
*/
int main(void)
{

gpiote_init();

while (true)
{

if (NRF_LOG_PROCESS() == false)
{
nrf_pwr_mgmt_run();
}
}
}
/** @} */