Time in 2021 Nian 1 Yue 25 Ri , winter vacation home, a good school to learn
Development Board : snow's 100 head piece NRF52840 EVAL KIT
Download tool: JINLK V11 (preferably JLINK V9 or higher, some people use JLINK OB, other downloaders STLINK, DAP are not recommended)
Version number: KEIL5 programming environment, CMSIS is 5.3.0, CMSIS of NRF52840 is 8.35.0
Reference material: NRF52840-Eval-Kit-Schematic.pdf (Schematic)
nRF5_SDK_17.0.2_d674dde (official routine)
nRF5_SDK_17.0.0_offline_doc (official document)
Qingfeng NRF52832 button chapter
Realization function: button light
Button schematic
The IO ports are 11 and 18, of which 18 is the RESET button. Now I will not cancel the reset function of 18, and I will not use it for the time being
Configure IO as up input, then when the button is pressed, it is 0 level, when the button is not pressed or released, it is high level
Use nrf_gpio_cfg_input to configure as input mode
Code
nrf_gpio_cfg_input(11,NRF_GPIO_PIN_PULLUP );
Because there is only one button, I have three independent buttons externally, IO is 24, 20, 17, and the other end of the same is connected to the ground.
The GPIOTE external interrupt is used, GPIO is a general-purpose input and output pin, and T/E represents the pin for task or interrupt setting
add files
Specifically, find it in E:\nRF52840\nRF5_SDK_17.0.2_d674dde\modules\nrfx\drivers\src
GPIOTE has only 8 channels, all of which are operated through the 8 registers of CONFIG[0~7]
code show as below:
NRF_GPIOTE->CONFIG[0] = (GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos)
| (KEY0 << GPIOTE_CONFIG_PSEL_Pos)
| (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos);
Configure the first channel NRF_GPIOTE->CONFIG[0]
Where (GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos) is
Where (KEY0 << GPIOTE_CONFIG_PSEL_Pos) is
Where GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos); is
That is, set the event mode (EVENT), the pin is KEY0, and then high->low, that is, the falling edge triggers the interrupt
Then turn on interrupt
NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_IN0_Set << GPIOTE_INTENSET_IN0_Pos;// 使能中断CONFIG[0]:
Interrupt function:
void GPIOTE_IRQHandler(void)
{
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(KEY0)== 0)
{
nrf_gpio_pin_toggle(LED0);
}
}
}
The complete code is as follows:
#include <stdbool.h>
#include <stdint.h>
#include "nrf_delay.h"
#include "nrf_gpio.h"
#include "nrf_gpiote.h"
uint32_t LED0,LED1,LED2,LED3;
uint32_t KEY0,KEY1,KEY2,KEY3;
/**
* @brief Function for application main entry.
*/
int main(void)
{
LED0 = NRF_GPIO_PIN_MAP(0,13);
LED1 = NRF_GPIO_PIN_MAP(0,14);
LED2 = NRF_GPIO_PIN_MAP(1,9);
LED3 = NRF_GPIO_PIN_MAP(0,16);
KEY0 = NRF_GPIO_PIN_MAP(0,11);
KEY1 = NRF_GPIO_PIN_MAP(0,24);
KEY2 = NRF_GPIO_PIN_MAP(0,20);
KEY3 = NRF_GPIO_PIN_MAP(0,17);
nrf_gpio_cfg_output(LED0);
nrf_gpio_cfg_output(LED1);
nrf_gpio_cfg_output(LED2);
nrf_gpio_cfg_output(LED3);
nrf_gpio_pin_set(LED0);
nrf_gpio_pin_set(LED1);
nrf_gpio_pin_set(LED2);
nrf_gpio_pin_set(LED3);
nrf_gpio_cfg_input(KEY0,NRF_GPIO_PIN_PULLUP );
nrf_gpio_cfg_input(KEY1,NRF_GPIO_PIN_PULLUP );
nrf_gpio_cfg_input(KEY2,NRF_GPIO_PIN_PULLUP );
nrf_gpio_cfg_input(KEY3,NRF_GPIO_PIN_PULLUP );
NVIC_EnableIRQ(GPIOTE_IRQn);//中断嵌套设置
NRF_GPIOTE->CONFIG[0] = (GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos)
| (KEY0 << GPIOTE_CONFIG_PSEL_Pos)
| (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos);
// 设置事件模式(EVENT),引脚为KEY0,然后高->低,即下降沿触发中断
NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_IN0_Set << GPIOTE_INTENSET_IN0_Pos;// 使能中断类型:
NRF_GPIOTE->CONFIG[1] = (GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos)
| (KEY1 << GPIOTE_CONFIG_PSEL_Pos)
| (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos);
// 设置事件模式(EVENT),引脚为KEY1,然后高->低,即下降沿触发中断
NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_IN1_Set << GPIOTE_INTENSET_IN1_Pos;// 使能中断类型:
NRF_GPIOTE->CONFIG[2] = (GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos)
| (KEY2 << GPIOTE_CONFIG_PSEL_Pos)
| (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos);
// 设置事件模式(EVENT),引脚为KEY2,然后高->低,即下降沿触发中断
NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_IN2_Set << GPIOTE_INTENSET_IN2_Pos;// 使能中断类型:
NRF_GPIOTE->CONFIG[3] = (GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos)
| (KEY3 << GPIOTE_CONFIG_PSEL_Pos)
| (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos);
// 设置事件模式(EVENT),引脚为KEY3,然后高->低,即下降沿触发中断
NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_IN3_Set << GPIOTE_INTENSET_IN3_Pos;// 使能中断类型:
while(1)
{
// if(0 == nrf_gpio_pin_read(KEY0))
// {
// nrf_delay_ms(10); //xiaodou
// if(0 == nrf_gpio_pin_read(KEY0))
// {
// nrf_gpio_pin_toggle(LED0);
//
// while(0 == nrf_gpio_pin_read(KEY0)); //songshou
// }
// }
}
}
void GPIOTE_IRQHandler(void)
{
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(KEY0)== 0)
{
nrf_gpio_pin_toggle(LED0);
}
}
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(KEY1)== 0)
{
nrf_gpio_pin_toggle(LED1);
}
}
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(KEY2)== 0)
{
nrf_gpio_pin_toggle(LED2);
}
}
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(KEY3)== 0)
{
nrf_gpio_pin_toggle(LED3);
}
}
}
This kind of interrupt is very troublesome to write, because it is an operating register, and the stability is also very poor. Continue to interrupt in the next section