我们还是先把所有中断相关寄存器列出来吧。与中断有关的寄存器一共7个,结构都差不多,下面一一讲解:

一、中断寄存器
GPIOIS Register (offset = 404h) [reset = 0h]

此寄存器指示中断检测方式,为0时表示边沿触发,为1时表示电平触发。
GPIOIBE Register (offset = 408h) [reset = 0h]

GPIO Interrupt Both Edges (GPIOIBE) 寄存器置1时可将中断配置为上升沿和下降沿皆可触发。当然,只有当GPIOIS寄存器设置为边沿检测(0)时方有效。
GPIOIEV Register (offset = 40Ch) [reset = 0h]

GPIO Interrupt Event (GPIOIEV) 寄存器配置中断是上升沿或高电平触发(1),还是下降沿触发或低电平触发(0)。当然,何种方式触发由GPIOIS寄存器决定。
GPIOIM Register (offset = 410h) [reset = 0h]

GPIO Interrupt Mask (GPIOIM)寄存器用于屏蔽中断。只有它的值为1时,中断方能被发送至中断控制器。
GPIORIS Register (offset = 414h) [reset = 0h]

GPIO Raw Interrupt Status (GPIORIS)寄存器用于检测相应的GPIO是否产生了中断条件。
GPIOMIS Register (offset = 418h) [reset = 0h]

GPIO Masked Interrupt Status (GPIOMIS)寄存器和上面的GPIORIS寄存器一样,用于检测中断条件。但GPIOMIS只显示那些可以被传递给中断控制器的中断条件,被屏蔽的就不显示了。GPIORIS则显示所中满足条件的中断。
GPIOICR Register (offset = 41Ch) [reset = 0h]

GPIO Interrupt Clear (GPIOICR) 寄存器用于清除中断。对于边沿触发中断的来说,在此寄存器写1则会清除GPIORIS和GPIOMIS寄存器中相应的位。如果为电平触发中断,则无影响。
二、中断初始化和配置
为配置特定端口的GPIO引脚:
  1. 使能特定端口时钟GPIO0CLKEN、GPIO1CLKEN、GPIO2CLKEN、GPIO3CLKEN和GPIO4CLKEN 。
  2. 通过GPIODIR寄存器配置GPIO引脚的方向。1表示输出,0表示输入。
  3. 通过 GPIO_PAD_CONFIG_#寄存器来配置引脚功能(引脚复用,这些寄存器的配置可参考这篇日志)。GPIODMACTL可将GPIO引脚配置为 μDMA触发。
  4. 通过 GPIOIS、GPIOIBE、GPIOEV和GPIOIM寄存器配置中断类型、事件和掩码。
下表是配置示例,将某端口的第2引脚配置为上升沿触发中断:

三、驱动库源码分析
接下来准备写Demo,写之前当然要熟悉驱动库中与中断有关的主要源码,先来看看GPIO.h中的中断回调函数原型:
/** @} */
/** @} end of GPIO_PinConfigSettings group *//*!*  @brief  GPIO回调函数类型**  @param      index       GPIO index。它和GPIO_setCallback()函数中传递的index*                          是同一个值。通过使用index来标识导致中断的GPIO,使得你可*                          以在多个GPIO中断中使用相同的回调函数。*/
typedef void (*GPIO_CallbackFxn)(uint_least8_t index);

那么回调函数被放在哪里呢?找到【boards\CC3220SF_LAUNCHXL\CC3220SF_LAUNCHXL.c】。此文件应该为PinMux文件的模板。看到如下代码:
/** 回调函数数组指针* NOTE: 此处引脚配置顺序必须与CC3220SF_LAUNCHXL.h中的所定义的保持一致* NOTE: 不用于中断的引脚可在此处省略,以减少内存使用(前提是不使用中断的*       引脚排放在数组未尾)*/
GPIO_CallbackFxn gpioCallbackFunctions[] = {NULL,  /* CC3220SF_LAUNCHXL_GPIO_SW2 */NULL   /* CC3220SF_LAUNCHXL_GPIO_SW3 */
};/* 具体设备 GPIO_config 结构体 */
const GPIOCC32XX_Config GPIOCC32XX_config = {.pinConfigs = (GPIO_PinConfig *)gpioPinConfigs,.callbacks = (GPIO_CallbackFxn *)gpioCallbackFunctions,.numberOfPinConfigs = sizeof(gpioPinConfigs)/sizeof(GPIO_PinConfig),.numberOfCallbacks = sizeof(gpioCallbackFunctions)/sizeof(GPIO_CallbackFxn),.intPriority = (~0)
};
注释中提到的与CC3220SF_LAUNCHXL.h中所定义的保持一致,指的是以下定义:
/*!*  @def    CC3220SF_LAUNCHXL_GPIOName*  @brief  Enum of GPIO names on the CC3220SF_LAUNCHXL dev board*/
typedef enum CC3220SF_LAUNCHXL_GPIOName {CC3220SF_LAUNCHXL_GPIO_SW2 = 0,CC3220SF_LAUNCHXL_GPIO_SW3,CC3220SF_LAUNCHXL_GPIO_LED_D7,CC3220SF_LAUNCHXL_GPIOCOUNT
} CC3220SF_LAUNCHXL_GPIOName;
由以上两段代码可知:
  1. 所有中断回调函数被放在了gpioCallbackFunctions数组之中。它的存放顺序必须与CC3220SF_LAUNCHXL.h中的CC3220SF_LAUNCHXL_GPIOName枚举中的顺序保持一致。
  2. 为节省内存,有中断回调函数的引脚应定义在CC3220SF_LAUNCHXL_GPIOName中的前面。这样放在gpioCallbackFunctions数组后方的无回调函数的引脚定义就可省略。
  3. 即使中断没有定义回调函数,也需要在gpioCallbackFunctions数组中加NULL,以方便之后使用GPIO_setCallback将真正的回调函数加入其中。
那么在库函数内部,如何快速判断引脚是否存在回调函数?如何快速定位一个引脚的回调函数呢。请参考GPIOCC32XX.c中的以下代码:
/** 赋予一个端口的8个引脚的用户定义引脚索引。* 用于端口中断函数,来定位一个引脚的回调函数。*/
typedef struct PortCallbackInfo {/** 端口的8个相应的用户定义pinId索引*/uint8_t pinIndex[NUM_PINS_PER_PORT];
} PortCallbackInfo;/** portCallbackInfos表,每端口一个。*/
static PortCallbackInfo gpioCallbackInfo[NUM_PORTS];

驱动库中,给每个引脚安排了一块内存地址,用于存放回调函数的索引号,把上面代码抽象成下图更好理解:

这里所说的回调函数索引号就是回调函数在gpioCallbackFunctions数组中的索引号,实际上就是引脚在CC3220SF_LAUNCHXL_GPIOName数组中的索引号。如果没有回调函数,则存放CALLBACK_INDEX_NOT_CONFIGURED宏,此宏值为0xFF。
我们在写程序时,为某个引脚中断写了回调函数,那么如何将它跟引脚进行关联呢?打开GPIOCC32XX.c文件,找到GPIO_setCallback()函数:
void GPIO_setCallback(uint_least8_t index, GPIO_CallbackFxn callback)
{uint32_t   pinNum;uint32_t   portIndex;PinConfig *config = (PinConfig *) &GPIOCC32XX_config.pinConfigs[index];DebugP_assert(initCalled && index < GPIOCC32XX_config.numberOfCallbacks);/** 此段代码将回调函数索引号加入gpioCallbackInfo数组。*/pinNum = getPinNumber(config->pin);portIndex = config->port & PORT_MASK;if (callback == NULL) {gpioCallbackInfo[portIndex].pinIndex[pinNum] =CALLBACK_INDEX_NOT_CONFIGURED;}else {gpioCallbackInfo[portIndex].pinIndex[pinNum] = index;}/** 此段代码将回调函数加入 callBackFunctions 数组.*/if (GPIOCC32XX_config.callbacks[index] != callback) {GPIOCC32XX_config.callbacks[index] = callback;}
}
四、示例程序1
外部中断,还是用按钮来做示例比较合适。先看电路图查找按钮连线:

400多块钱的电路板,外设少点也就算了,弄个硬件消抖总可以吧。真是杯具。由图可知,SW2连接的是GPIO_13,SW3连接的是GPIO_22,按钮按下时为高电平。
打开Pin Mux Tool发现13和22引脚不给配置,原来这工具专为开发板准备的。现在也知道为何CC3220SF_LAUNCHXL.c文件里配置好两个SW了。那么只能从上一个Demo里拷贝了。
1、在【Project Explorer】中拷贝 上篇日志中的demo_gpio_PinMux项目,命名为demo_interrupt_PinMux。
2、在CC3220SF_LAUNCHXL.c文件里找到gpioPinConfigs[],更改为:

GPIO_PinConfig gpioPinConfigs[] = {GPIOCC32XX_GPIO_22 | GPIO_CFG_INPUT | GPIO_CFG_IN_INT_RISING, //SW2GPIOCC32XX_GPIO_13 | GPIO_CFG_INPUT | GPIO_CFG_IN_INT_RISING, //SW3GPIOCC32XX_GPIO_09 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,GPIOCC32XX_GPIO_10 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,GPIOCC32XX_GPIO_11 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
};
加粗部分为新加入的代码。上篇日志中的Demo其实是有错误的,之后的gpioCallbackFunctions[]数组中的两个NULL回调函数变成为led准备的了。
3、打开CC3220SF_LAUNCHXL.h,找到CC3220SF_LAUNCHXL_GPIOName枚举,更改为:
typedef enum CC3220SF_LAUNCHXL_GPIOName{CC3220SF_LAUNCHXL_GPIO_SW2 = 0,CC3220SF_LAUNCHXL_GPIO_SW3,CC3220SF_LAUNCHXL_GPIO_LED_09,CC3220SF_LAUNCHXL_GPIO_LED_10,CC3220SF_LAUNCHXL_GPIO_LED_11,CC3220SF_LAUNCHXL_GPIOCOUNT
} CC3220SF_LAUNCHXL_GPIOName;

4、打开Board.h文件,更改为:

#ifndef __BOARD_H
#define __BOARD_H#ifdef __cplusplus
extern "C" {
#endif#include "CC3220SF_LAUNCHXL.h"#define BUTTON0           CC3220SF_LAUNCHXL_GPIO_SW2
#define BUTTON1           CC3220SF_LAUNCHXL_GPIO_SW3#define LED_ON            CC3220SF_LAUNCHXL_GPIO_LED_ON
#define LED_OFF           CC3220SF_LAUNCHXL_GPIO_LED_OFF
#define RED_LED           CC3220SF_LAUNCHXL_GPIO_LED_09
#define YELLOW_LED        CC3220SF_LAUNCHXL_GPIO_LED_10
#define GREEN_LED         CC3220SF_LAUNCHXL_GPIO_LED_11#ifdef __cplusplus
}
#endif#endif /* __BOARD_H */

5、打开main_tirtos.c文件,更改为:

#include <ti/drivers/GPIO.h>
#include <ti/drivers/gpio/GPIOCC32XX.h>
#include "Board.h"
#include <ti/sysbios/BIOS.h>//Button0中断服务函数
void Button0_isr(uint_least8_t index)
{GPIO_toggle(RED_LED);
}//Button1中断服务函数
void Button1_isr(uint_least8_t index)
{GPIO_toggle(GREEN_LED);
}int main(void)
{GPIO_init();//关联BUTTON0的中断回调函数GPIO_setCallback(BUTTON0, Button0_isr);GPIO_enableInt(BUTTON0);//关联BUTTON1的中断回调函数GPIO_setCallback(BUTTON1, Button1_isr);GPIO_enableInt(BUTTON1);BIOS_start();return (0);
}
烧写程序,按左边按钮,控制绿灯亮灭。按右边按钮,控制红灯亮灭。
五、示例程序2
上例没能自己配置GPIO,不爽。正好还有一个灯没控制,就外接一个按钮来控制中间的黄灯。参考上面的按钮电路图来接线:
按钮接到P63引脚,也就是GPIO_08引脚。接下来写程序。
1、在【Project Explorer】中拷贝demo_interrupt_PinMux项目,命名为demo_interrupt_PinMux2。
2、在CC3220SF_LAUNCHXL.c文件里找到gpioPinConfigs[],更改为:
GPIO_PinConfig gpioPinConfigs[] =
{GPIOCC32XX_GPIO_22 | GPIO_CFG_INPUT | GPIO_CFG_IN_INT_RISING, //SW2GPIOCC32XX_GPIO_13 | GPIO_CFG_INPUT | GPIO_CFG_IN_INT_RISING, //SW3GPIOCC32XX_GPIO_08 | GPIO_CFG_INPUT | GPIO_CFG_IN_INT_RISING, //外接SWGPIOCC32XX_GPIO_09 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,GPIOCC32XX_GPIO_10 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,GPIOCC32XX_GPIO_11 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
};GPIO_CallbackFxn gpioCallbackFunctions[] =
{NULL,  /* CC3220SF_LAUNCHXL_GPIO_SW2 */NULL,  /* CC3220SF_LAUNCHXL_GPIO_SW3 */NULL   /* CC3220SF_LAUNCHXL_GPIO_EXTERNAL_SW */
};
加粗部分为新添加代码。这里注意 gpioCallbackFunctions数组里多了一个NULL,它用来存放外接按钮的回调函数。
3、打开CC3220SF_LAUNCHXL.h,找到CC3220SF_LAUNCHXL_GPIOName枚举,更改为:
typedef enum CC3220SF_LAUNCHXL_GPIOName {CC3220SF_LAUNCHXL_GPIO_SW2 = 0,CC3220SF_LAUNCHXL_GPIO_SW3,CC3220SF_LAUNCHXL_GPIO_EXTERNAL_SW,CC3220SF_LAUNCHXL_GPIO_LED_09,CC3220SF_LAUNCHXL_GPIO_LED_10,CC3220SF_LAUNCHXL_GPIO_LED_11,CC3220SF_LAUNCHXL_GPIOCOUNT
} CC3220SF_LAUNCHXL_GPIOName;
加粗部分为新添加代码。
4、打开Board.h文件,更改为:
#ifndef __BOARD_H
#define __BOARD_H#ifdef __cplusplus
extern "C" {
#endif#include "CC3220SF_LAUNCHXL.h"#define BUTTON0           CC3220SF_LAUNCHXL_GPIO_SW2
#define BUTTON1           CC3220SF_LAUNCHXL_GPIO_SW3
#define BUTTON2           CC3220SF_LAUNCHXL_GPIO_EXTERNAL_SW#define LED_ON            CC3220SF_LAUNCHXL_GPIO_LED_ON
#define LED_OFF           CC3220SF_LAUNCHXL_GPIO_LED_OFF
#define RED_LED           CC3220SF_LAUNCHXL_GPIO_LED_09
#define YELLOW_LED        CC3220SF_LAUNCHXL_GPIO_LED_10
#define GREEN_LED         CC3220SF_LAUNCHXL_GPIO_LED_11#ifdef __cplusplus
}
#endif#endif /* __BOARD_H */
加粗部分为新添加代码。
5、打开main_tirtos.c文件,更改为:
#include <unistd.h>
#include <xdc/runtime/System.h>
#include <ti/drivers/GPIO.h>
#include <ti/drivers/gpio/GPIOCC32XX.h>
#include "Board.h"
#include <ti/sysbios/BIOS.h>#define DELAY_TIME  (0x18fff)void delay(int temp)
{int i = 0;for (i = 0; i < temp; i++);
}
//Button0中断服务函数
void Button0_isr(uint_least8_t index)
{delay(DELAY_TIME); //8毫秒延时if(GPIO_read(index)){GPIO_toggle(RED_LED);}
}//Button1中断服务函数
void Button1_isr(uint_least8_t index)
{delay(DELAY_TIME); //8毫秒延时if(GPIO_read(index)){GPIO_toggle(GREEN_LED);}
}void Button2_isr(uint_least8_t index)
{delay(DELAY_TIME); //8毫秒延时if(GPIO_read(index)){GPIO_toggle(YELLOW_LED);}
}int main(void)
{GPIO_init();//关联BUTTON0的中断回调函数GPIO_setCallback(BUTTON0, Button0_isr);GPIO_enableInt(BUTTON0);//关联BUTTON1的中断回调函数GPIO_setCallback(BUTTON1, Button1_isr);GPIO_enableInt(BUTTON1);//关联外接BUTTON2的中断回调函数GPIO_setCallback(BUTTON2, Button2_isr);GPIO_enableInt(BUTTON2);BIOS_start();return (0);
}

现在,终于可以使用按钮控制黄灯了。这回添加了消抖代码,虽然代码不是很正规,但用起来舒服了很多。这个消抖延时时间经过试验,基本可以达到百分之百的命中。

CC3220学习笔记---中断相关推荐

  1. 009 - STM32学习笔记 - 中断

    009 - STM32学习笔记 - 中断 这节的内容,野火的官方视频我反复看了好几次,但是感觉火哥在这块讲解的特别绕,理解起来很吃力,后来在看了一下其他老师的视频,结合一些书本资料和官方手册,才搞清楚 ...

  2. 10.FreeRTOS学习笔记-中断管理

    FreeRTOS 的中断管理支持: 开/关中断. 恢复中断. 中断使能. 中断屏蔽. 可选择系统管理的中断优先级 中断管理的运作机制 当中断产生时,处理机将按如下的顺序执行: 保存当前处理机状态信息 ...

  3. stm32学习笔记-中断系统

    文章目录 问题引入 1.中断系统概述. 1.1 为什么要中断(中断意义) 中断和轮询比较: 1.2 中断处理过程 1.3 中断笔试题 1.4 中断服务函数 2.STM32中断的体系结构. 2.1 结构 ...

  4. 7、江科大stm32视频学习笔记——中断的应用:对射式红外传感器计次旋转编码器计次

    目录 1.标志位函数 2. 初始化的中断的步骤 3.对射式红外传感器计次 (1)接线图 (2)CountSensor.c (3)main.c 4.旋转编码器计次 (1)接线图(旋转编码器接在PB1.P ...

  5. 微机原理学习笔记——中断系统

    中断系统 目录 中断系统 一.中断的基本概念 中断源 开中断和关中断 中断优先权 中断向量表 中断过程 二.8086中断系统 中断源 可屏蔽中断周期 中断向量表 中断过程 三.可编程中断控制器8259 ...

  6. 嵌入式linux 添加中断,《嵌入式linux应用程序开发完全手册》中断控制器操作(外部中断)学习笔记...

    <嵌入式linux应用程序开发完全手册>中断控制器操作(外部中断)学习笔记 一.ARM中断体系 当一个"异常"发生时,或者说当收到一个中断触发信号时,ARM9将会自动完 ...

  7. Windows保护模式学习笔记(四)—— 中断门陷阱门

    Windows保护模式学习笔记(四)-- 中断门&陷阱门 要点回顾 中断描述符表(IDT) 一.中断门 实验:构造一个中断门 第一步:初步构造参数 第二步:确定 Offset in Segme ...

  8. 【OS学习笔记】四十 保护模式十:中断和异常的处理与抢占式多任务对应的汇编代码----动态加载的用户程序/任务二代码

    本文是以下几篇文章对应的微型动态加载的用户程序/任务二代码: [OS学习笔记]三十四 保护模式十:中断和异常区别 [OS学习笔记]三十五 保护模式十:中断描述符表.中断门和陷阱门 [OS学习笔记]三十 ...

  9. 【OS学习笔记】三十九 保护模式十:中断和异常的处理与抢占式多任务对应的汇编代码----动态加载的用户程序/任务一代码

    本文是以下几篇文章对应的动态加载的用户程序/任务一代码: [OS学习笔记]三十四 保护模式十:中断和异常区别 [OS学习笔记]三十五 保护模式十:中断描述符表.中断门和陷阱门 [OS学习笔记]三十六 ...

最新文章

  1. python连接数据库,处理数据结果后生成excel文件
  2. 基于Springboot实现企业人事管理系统
  3. Tensorflow: 保存和复原模型(save and restore)
  4. LeetCode Odd Even Linked List
  5. jupyter kernel_jupyter增加多版本python内核
  6. anaconda换源和恢复默认源
  7. hystrix 单独使用_Spring cloud微服务架构-Hystrix工作原理(微服务故障熔断)
  8. python实现冒泡排序视频_Python实现冒泡排序
  9. 第二天linux,yum源配置和ftp部分设置
  10. Open VSwitch简介
  11. 百度地图API学习之路(1)
  12. python获取验证码_python如何获取验证码
  13. 混沌世界里的临界点(博弈论的诡计)
  14. 使用plupload压缩图片
  15. ODL(C版本)安装过程
  16. 惠普微型计算机 使用教程,惠普打印机怎么用 打印机使用注意事项【图文教程】...
  17. hive分区表之insert overwrite 注意事项
  18. final修饰变量、方法、类的作用
  19. c语言Int16_t 什么意思,__IO uint16_t 是什么意思,在定义参数时为什么不直接写成 uint16...
  20. 大数据的一生一世——谈数据冷热分离技术

热门文章

  1. CAS:1001015-18-4,CORM-401是一种对氧化剂敏感的 CO 释放分子
  2. 两种闪存:NAND Flash与NOR Flash对比
  3. 串口通讯隔离利用光耦隔离的问题
  4. DRGS 分组器源码
  5. TN、HTN、STN、FSTN、DSTN、CSTN、TFT、LCD 的区别
  6. 【练习】JavaSE实现控制台版本的斗地主部分功能
  7. 最优服务次序问题-贪心算法
  8. java 二十四节气_获取二十四节气示例代码
  9. 凌乱的yyy / 线段覆盖(贪心)
  10. java 定时器 手动触发_Spring+Quartz 实现手动开关定时器