GPIO通常都会具有中断功能,上一讲的GPIO中并没有涉及到中断的相关寄存器。

51822将GPIO的中断相关做成了一个单独的模块GPIOTE,这个模块不仅提供了GPIO的中断功能,同时提供了 通过task和event的方式来访问GPIO的功能。其实中断功能也是通过 event来使能的,即中断是通过设置寄存器中相关位来决定  当event发生时是否发生中断 来设置中断功能的,具体下面介绍寄存器就明白了。

(task和event的引入主要是为了和51822中的PPI(可编程外围设备互联系统)模块的配合使用,举个简单的例子,ppi模块可以将event和task分别绑定在它的两端,当event发生时,taks就会自动触发,具体的细节 参见 PPI教程)

本将主要介绍GPIO的中断功能,所以只牵涉到GPIOTE中的event,(上面说过中断是通过设置 event发生时触发中断 来使用中断功能的)。

GPIOTE模块主要提供的了 4 个通道,这四个通道可以通过单独设置分别和普通的 GPIO 绑定,我们需要使用GPIO的中断功能可以设置相关寄存器的相关位让某个通道作为event,以及配置触发event的动作,比如绑定的引脚有上升沿跳变或者下降沿跳变触发event , 然后配置中断使能寄存器,配置让其event产生时是触发中断。 这样就实现了我们需要的 GPIO的中断方式。

初学者可能对这个event无法理解,event理解不就是事件么?设置的相应动作发生了会产生事件这不就是中断么?为什么又搞了一个 事件发生了才触发中断。

比如设置上升沿产生中断:

通常的 中断的都是 : 引脚上升沿->触发中断

51822却是: 引脚上升沿->产生eventà产生中断。

为什么中间多了个event?  就像上面说的主要是因为GPIOTE除了可以简单的作为设置GPIO来产生中断外还可以和PPI来配合作出更灵活的应用。所以才会有了这个event。PPI教程中会对这个event和task做更详细说明。 目前需要知道 中断的产生是需要配置相关寄存器中的位 来使能event发生时触发中断 才能实现GPIO的中断功能。

GPIOTE的四个通道都是通过CONFIG[0]-CONFIG[3]来配置的。其对应event0-event4以及task0-task4。来看下该寄存器中具体的配置位。

MODE功能位:该位用来配置本GPIOTE通道是作为event还是task的,这里我们用的是作为event,作为task的例子会在PPI教程中见到

PSEL功能位:用来设置本GPIOTE通道与哪个引脚绑定。

POLARITY功能位:用来设置作为event和task时的相应动作。如果作为前面的mode设置为event即相应动作发生时产生event, 如果上面的mode设置为task即当task被触发时就会执行该动作。

OUTINIT功能位:当上面的Mode配置为task时,这里设置的是引脚的初始值,当上面的mode配置为event时,设置为影响

比如我的板子上 按钮连再引脚21上,按钮按下时会产生低电平,为按下时为高电平。现在我想在按钮按下时(下降沿)产生中断。我使用GPIOTE的通道0,那么我就可以如下配置 CONFIG[0],让其在我按键按下时产生event0。

CONFIG[0] = (1 << 0 )        //作为event

| (21 << 8)          //与PIN21绑定

|(2 << 16)     //配置为下降沿产生event 0

上面说过 中断的产生不仅需要有event产生(event0-event4都是event,是对应的四个通道产生的event)。还需要设置 event发生时触发中断 才能真正产生我们需要的中断功能。

这个配置就是在INTEN  寄存器中配置,它也有两个更方便的配置寄存器INTENSET和INTENCLR。

按照上面的配置,我们按键按下后按钮后会产生event0,然后配置event0发生时产生中断

INTENSET  =  0x01;

这样配置后 才会真正在按键按下后出发中断。

下面是完整的使用GPIOTE来实现一个按键中断的程序

首先建立一个工程,这里是 keil5.14 + sdk9.0 的开发环境

创建一个新的工程,选择自己板子的芯片型号,我的是51422

根据使用到的资源勾选相应的组件,这里就是用到了GPIO相关的部分,所以勾选必要的 core部分(包含了芯片的系统控制相关寄存器的定义)和startup(启动函数,处理一些底层设置然后跳转到我们自己写的Main函数)。 以及nrf_drivers下面的nrf_gpio部分就可以了。

然后创建自己的 gpiote_main.c文件并添加到工程中,并编写自己的main.c函数

Main.c文件

#include "nrf_gpio.h"
#include "nrf51.h"
//定义自己板子上的按键和led灯
#define     BUTTON_PIN  17
#define   LED_PIN    21

int main(void){

    //讯联的板子上按钮上没有接上拉电阻,所以需要下面这两句来设置输入有
    //上拉电阻,不然的话每次按键后几秒钟内再按键都会没反应,要等一会按
    //才会有反应
    nrf_gpio_pin_pull_t config = NRF_GPIO_PIN_PULLUP;
    nrf_gpio_cfg_input(BUTTON_PIN, config);

    //配置GPIOTE通道0作为event,”绑定”按键引脚,设置下降沿产生event
    NRF_GPIOTE->CONFIG[] =  <<
                     |(BUTTON_PIN << )
                     |( << );

    //配置LED输出
    nrf_gpio_cfg_output(LED_PIN);  

    //配置 event发生的时候产生中断,
    NRF_GPIOTE->INTENSET = 0X01;

    //配置GPIOTE中断优先级,并使能GPIOTE中断
    NVIC_SetPriority(GPIOTE_IRQn, );
    NVIC_ClearPendingIRQ(GPIOTE_IRQn);
    NVIC_EnableIRQ(GPIOTE_IRQn);

    );
    ;

}

//中断处理函数:
void GPIOTE_IRQHandler(void){

    ] ==  ){
        //首先清楚event,不然会导致中断退出有event任然存在导致一直
        //触发中断
        NRF_GPIOTE->EVENTS_IN[] = ;
        nrf_gpio_pin_toggle(LED_PIN);
    }
}

上面虽然实现了GPIO的中断,但是我们是利用了GPIOTE,虽然能实现中断,但是GPIOTE只有四个通道,弊端就在这里。使用GPIOTE只能最多四个I/O中断。

所以51822提供了另外一种产生I/O中断的方式 即port event。这个event可以在所有 配置了可以产生DETECT signal 的引脚触发DETECT signal的时候产生。(DETECT signal在GPIO教程中有说明)

同样还是实现按键中断,通过port event方式产生中断的代码

main.c文件

#include "nrf_gpio.h"
#include "nrf51.h"

//定义自己板子上的按键和LED
#define BUTTON1      17
#define BUTTON2      18
#define BUTTON3      19
#define BUTTON4      20

#define LED1      21
#define LED2      22
#define LED3      23
#define LED4      24

int main(void){

    //配置上拉和 sense
    nrf_gpio_pin_pull_t config = NRF_GPIO_PIN_PULLUP;
    nrf_gpio_pin_sense_t sense = GPIO_PIN_CNF_SENSE_Low;

    //配置四个按键最为输入和上拉,并且设置低电平产生DETECT signal
    nrf_gpio_cfg_sense_input(BUTTON1,config, sense);
    nrf_gpio_cfg_sense_input(BUTTON2,config, sense);
    nrf_gpio_cfg_sense_input(BUTTON3,config, sense);
    nrf_gpio_cfg_sense_input(BUTTON4,config, sense);

    //配置LED引脚输出
    nrf_gpio_cfg_output(LED1);
    nrf_gpio_cfg_output(LED2);
    nrf_gpio_cfg_output(LED3);
    nrf_gpio_cfg_output(LED4);

    //跟GPIOTE配置产生中断一样,这里也要配置port event产生时触发中断
    NRF_GPIOTE->INTENSET =  << ;

    NVIC_SetPriority(GPIOTE_IRQn, );
    NVIC_ClearPendingIRQ(GPIOTE_IRQn);
    NVIC_EnableIRQ(GPIOTE_IRQn);

    );
    ;
}

void GPIOTE_IRQHandler(void){

     ){
       //中断处理函数中要清楚event,不然会导致一直产生中断
       NRF_GPIOTE->EVENTS_PORT = ;
       ){
           nrf_gpio_pin_toggle(LED1);
       }
       ){
           nrf_gpio_pin_toggle(LED2);
       }
       ){
           nrf_gpio_pin_toggle(LED3);
       }
       ){
           nrf_gpio_pin_toggle(LED4);
       }
    }
}

nrf51822裸机教程-GPIOTE的更多相关文章

  1. nrf51822裸机教程-PWM

    先简单介绍一下PWM的原理. 原理很简单. 假设COUNTER是个从0开始递增的计数器.  我们设置两个值 counter0 和counter1 在 COUNTER 计数到counter0的值时候翻转 ...

  2. nrf51822裸机教程-PPI

    Programmable Peripheral Interconnect即可编程外设互联 系统,该模块是51822 提供的一个特性. 目的是为了让51822 的外围模块可以不通过处理器而自动相互作用. ...

  3. nrf51822裸机教程-IIC

    关于IIC总线的核心有以下几点: :时钟线高电平期间必须保持数据线不变. :时钟线低电平期间可以改变数据. :时钟线和数据线上都要接上拉电阻,以使总线不工作时,两根线的电平都处于高电平状态. :每个传 ...

  4. nrf51822裸机教程-UART

    art硬件模块通常都有内置的硬件接收buff,比如51822的硬件uart模块图如下 因为通常接收到uart数据时都会做一些处理.比如保存到数据,或者对数据做一些判断之类的. 如果uart的波特率设置 ...

  5. nrf51822裸机教程-RTC

    RTC0被协议栈使用了.所以在跑蓝牙程序的情况下.RTC0不能使用. RTC相关寄存器如下: EVTEN,EVTENSET,EVTENCLR. 这三个寄存器用来设置是否使能某个事件.(TICK,OVR ...

  6. nrf51822裸机教程-硬件timer

    该讲介绍51822的Timer/Counter模块工作在timer模式下(定时器模式,还可以工作为计数器模式) 如何操作 51822的Timer/Counter结构如下图所示 Timer模块从PCLK ...

  7. nrf51822裸机教程-SPI(主)

    关于SPI总线的介绍这里就不细说了,网上有很多介绍SPI总线时序的. SPI总线的本质就是一个环形总线结构,在时钟驱动下两个双向移位寄存器进行数据交换. 所以SPI总线的特色就是:传输一字节数据的同时 ...

  8. nrf51822裸机教程-GPIO

    首先看看一下相关的寄存器说明 Out寄存器 输出设置寄存器 每个比特按顺序对应每个引脚,bit0对应的就是 引脚0 该寄存器用来设置 引脚作为输出的时候的 输出电平为高还是低. 与输出设置相关的 还有 ...

  9. 微信蓝牙BLE接入调试指引 硬件篇

    1 平台框架简介 微信蓝牙BLE由三个模块组成,分别是蓝牙设备.微信和第三方服务器,如下图: 蓝牙设备与微信之间的通信是通过蓝牙GATT协议进行. 微信与第三方服器之间的通信是通过网络http 接口进 ...

随机推荐

  1. CodeForces 304C

    E - E Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Statu ...

  2. javascript优化--02高质量编码

    方法调用: 通常某个对象调用方法查找该方法并将该对象作为该方法的接受者(this): 使用call自定义接受者 可以调用在给定对象中不存在的方法: 定义高阶函数,允许使用者给回调函数指定接受者: 使用 ...

  3. div垂直居中 css div盒子上下垂直居中

    div垂直居中 css div盒子上下垂直居中,让DIV盒子在任何浏览器中任何分辨率的显示屏浏览器中处于水平居中和上下垂直居中. div垂直居中常用于单个盒子,如一个页面里只有一个登录布局,使用div ...

  4. 简单几何(线段相交+最短路) POJ 1556 The Doors

    题目传送门 题意:从(0, 5)走到(10, 5),中间有一些门,走的路是直线,问最短的距离 分析:关键是建图,可以保存所有的点,两点连通的条件是线段和中间的线段都不相交,建立有向图,然后用Dijks ...

  5. BZOJ3853 : GCD Array

    1 n d v相当于给$a[x]+=v[\gcd(x,n)=d]$ \[\begin{eqnarray*}&&v[\gcd(x,n)=d]\\&=&v[\gcd(\fr ...

  6. BZOJ3682 : Phorni

    后缀平衡树+线段树. $O(1)$比较大小的标号法真是强大. #include<cstdio> #include<cmath> #define N 300010 #define ...

  7. HDU 4003 (树形DP+背包)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4003 题目大意:有K个机器人,走完树上的全部路径,每条路径有个消费.对于一个点,机器人可以出去再回来 ...

  8. 移动APP 中文输入法下的搜索优化

    最近做了一个移动端的搜索功能,带有suggest.实现上并没有什么可说的,但是在后续优化上,特别是在中文输入法的情况下的优化使我学到一些新东西,所以决定写一篇文章. 下面是我简化后的基本功能实现,监听 ...

  9. A Complete Guide to the <Picture> Element

    If you’ve ever struggled building responsive websites, this post is for you. It’s part of a series o ...

  10. UiAutomator 测试工程开发小结

    一.    关于bundle无法导入中文参数 答:    将文件改为UTF-8格式 二.    关于对无法抓取的控件进行快速输入问题 答:    主要通过pressKeyCode方法,首先将光标锁定在 ...