时间在2021年1月25日,寒假放假在家好好学一学
开发板:初雪的100出头那块 NRF52840 EVAL KIT
下载工具:JINLK V11(最好是JLINK V9以上 也有人用JLINK OB也行,其他的下载器STLINK,DAP不建议用)
版本号: KEIL5编程环境,CMSIS为5.3.0, NRF52840的CMSIS为8.35.0
参考资料: NRF52840-Eval-Kit-Schematic.pdf(原理图)
nRF5_SDK_17.0.2_d674dde(官方例程)
nRF5_SDK_17.0.0_offline_doc(官方文档)
青风NRF52832的按键章节
实现功能: 按键点灯
按键原理图
IO口为11和18,其中18为RESET按键,现在我还不会取消18的复位功能,暂时不用
配置IO为上啦输入,然后按键按下的时候为0电平,按键没有按或松开的时候为高电平
用到 nrf_gpio_cfg_input 配置为输入模式
代码
nrf_gpio_cfg_input(11,NRF_GPIO_PIN_PULLUP );
因为按键只有1个,我再外置三个独立按键,IO为24,20,17,同样的另外一端接了地
使用的是GPIOTE外部中断,GPIO是通用输入输出引脚,T/E代表引脚为任务或者中断设置
添加文件
具体在E:\nRF52840\nRF5_SDK_17.0.2_d674dde\modules\nrfx\drivers\src里面找
GPIOTE只有8个通道,都是通过CONFIG[0~7]8个寄存器操作的
代码如下:
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);
配置第一个通道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;// 使能中断CONFIG[0]:
中断函数:
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);
}
}
}
完整代码如下:
#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);
}
}
}
这种中断写起来非常麻烦,因为是操作的寄存器,而且稳定性也非常不好, 下节继续搞中断