一、前言背景
Nordic52810虽然是ARM的框架,但是GPIO的中断与我们熟悉的STM32外部中断使用完全不一样,前面的文章里LZ有讲到过GPIO的结构图,使能PIN脚的Sense信号检测后,可触发GPIOTE模块的任务与事件
二、应用场景
1. 睡眠模式下的唤醒,使能蓝牙协议栈后,使用的是sd_app_evt_wait,可被任意事件中断唤醒
2. 不跑协议栈的话,可以进入system_off模式(官方提示功耗可在0.5uA)
由于睡眠状态下,我需要板子能持续进行广播,所以使用sd_app_evt_wait接口进入系统休眠
三、GPIOTE功能分类
GPIOTE做输入模块检测使用的话,有两种事件可供配置使用
PIN EVENT事件: 检测单个引脚电平变化;
优点:响应快,引脚中断之间互不干扰;
缺点:通道有限,最大支持8个引脚,功耗较高(使用高频时钟)
PORT EVENT事件:检测到任意引脚电平变化,高电平、低电平;触发DETECT Signal。
优点:通道不受限制,理论上所有引脚都可以配置,功耗低(使用低频时钟);
缺点:任意引脚中断有效时,其他引脚中断将无法触发(这个就优点恶心,因为是电平中断,这个中断就会一直保持,无法响应其他中断)。即任意时刻如果有两个中断触发,其中一个可能就会丢失
四、寄存器
GPIOTE模块的寄存器并不是很多,主要是配置中断禁用与使能与引脚的触发方式
INTENSET:[RW IN0 - IN7]低7位控制PIN事件中断使能(对应8路引脚) PORT[31] 最高位PORT事件中断使能
写1 Enable 使能中断;
写0 无效
INTENCLR: 禁用中断;
同上,写1 Disable 禁用中断
CONFIG[0 - 7]:配置寄存器
MODE[0-1] 事件、任务的模式选择(可读写)
PSEL[8-12] 占用5bit(0 - 31),配置31个引脚关联到对应的任务或事件(SET CLR OUT 可读写)
POLARITY[16-17] 配置级性,输出模式下可进行引脚 低到高 高到低 翻转
OUTINIT 任务模式下面引脚初始电平(0 低电平 1高电平)
五、程序实例
配置引脚前需要进行GPIOTE模块的使能与优先级的配置,考虑到蓝牙的功耗至上的原则,下面程序我配置的是PORT EVENT,
按键使用的PIN13,低电平触发
#define BUTTON1_PIN 13
void InitButtonIO(void)
{
//必须先配置GPIOTE模块
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);
//上拉低电平触发事件
nrf_gpio_cfg_sense_input(BUTTON1_PIN,NRF_GPIO_PIN_PULLUP,NRF_GPIO_PIN_SENSE_LOW);
return;
}
中断入口的配置
当中断触发后,为了防止一直进中断,可以根据当前按键电平重新配置,这样就不会一直进中断了,烧录代码后,可见按键按下弹起LED灯也跟着进行翻转
void GPIOTE_IRQHandler(void)
{
nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_PORT); //清中断事件//判断当前按键电平,设置触发电平
if(nrf_gpio_pin_read(BUTTON1_PIN))
nrf_gpio_cfg_sense_set(BUTTON1_PIN, NRF_GPIO_PIN_SENSE_LOW);
else
nrf_gpio_cfg_sense_set(BUTTON1_PIN, NRF_GPIO_PIN_SENSE_HIGH);LedToggle();
}