时间在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(官方文档)
实现功能: 按键点灯
按键原理图
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,同样的另外一端接了地
在上节中,把普通的GPIO端口配置为GPIOTE中断输入事件,能够绑定的只有8个通道,如果我们中断的数据量超过了8个,多的中断无法处理,如何出现这种情况,怎么处理?显然芯片设计厂家为了针对这种情况,特别在GPIOTE模块中提出了GPIOTE PORT功能。
GPIOTE PORT是从使用GPIO DETECT信号的多个I0输入引脚来生成的事件。该事件将在DETECT信号的上升沿而产生。也就是说这个功能可以通过普通的32个IO端口产生,相当与一个总通道,32个IO端口共用这个通道来申请中断。
同时GPIODETECT信号就是通过GPIO的SENSE寄存器打开,此功能始终处于启用状态。就是外围设备本身是休眠状态时,也不需要请求时钟或其他功率密集型基础架构来启用此功能。因此此功能可用于在系统启动时从WFI或WFE类型的睡眠时,来唤醒CPU、所有外设和CPU空闲。达到唤醒系统启动模式下的最低功耗模式。
代码如下:
线初始化GPIOTE
nrf_drv_gpiote_init();//启动GPIOTE时钟,可以这么说
也同样搞一个结构体
nrf_drv_gpiote_in_config_t key_ex_config; //按键中断配置用
结构体配置为
key_ex_config.hi_accuracy=false; // 启用低精确度PORT事件
key_ex_config.pull = NRF_GPIO_PIN_PULLUP ; //上啦
key_ex_config.sense = NRF_GPIOTE_POLARITY_HITOLO ;//下降沿
跟上一节的比较, 就是hi_accruacy从true改为了false 其他不变
写入寄存器和启动中断也是差不多,区别就是中断函数变成了同一个
然后按键个数改为4个(PORT最多32个吧,event模式是8个)
然后中断函数为
void KEY_Interrupt(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
if(KEY0 == pin)
nrf_gpio_pin_toggle(LED0);
if(KEY1 == pin)
nrf_gpio_pin_toggle(LED1);
if(KEY2 == pin)
nrf_gpio_pin_toggle(LED2);
if(KEY3 == pin)
nrf_gpio_pin_toggle(LED3);
}
完整代码如下:
#include <stdbool.h>
#include <stdint.h>
#include "nrf_delay.h"
#include "nrf_gpio.h"
#include "nrf_drv_gpiote.h"
uint32_t LED0,LED1,LED2,LED3;
uint32_t KEY0,KEY1,KEY2,KEY3;
void KEY_Interrupt(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action);
/**
* @brief Function for application main entry.
*/
int main(void)
{
nrf_drv_gpiote_in_config_t key_ex_config; //按键中断配置用
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 );
nrf_drv_gpiote_init();//启动GPIOTE时钟,可以这么说
key_ex_config.hi_accuracy=false; // 启用低精确度PORT事件
key_ex_config.pull = NRF_GPIO_PIN_PULLUP ; //上啦
key_ex_config.sense = NRF_GPIOTE_POLARITY_HITOLO ;//下降沿
nrf_drv_gpiote_in_init(KEY0, &key_ex_config, KEY_Interrupt);
nrf_drv_gpiote_in_init(KEY1, &key_ex_config, KEY_Interrupt);
nrf_drv_gpiote_in_init(KEY2, &key_ex_config, KEY_Interrupt);
nrf_drv_gpiote_in_init(KEY3, &key_ex_config, KEY_Interrupt);
nrf_drv_gpiote_in_event_enable(KEY0, true);//启动KEY0中断
nrf_drv_gpiote_in_event_enable(KEY1, true);//启动KEY1中断
nrf_drv_gpiote_in_event_enable(KEY2, true);//启动KEY2中断
nrf_drv_gpiote_in_event_enable(KEY3, true);//启动KEY3中断
while(1)
{
}
}
void KEY_Interrupt(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
if(KEY0 == pin)
nrf_gpio_pin_toggle(LED0);
if(KEY1 == pin)
nrf_gpio_pin_toggle(LED1);
if(KEY2 == pin)
nrf_gpio_pin_toggle(LED2);
if(KEY3 == pin)
nrf_gpio_pin_toggle(LED3);
}
按键KEY输入还有一个任务task模式,下节继续说