CC3220学习笔记---中断

news/2024/11/30 18:47:55/

我们还是先把所有中断相关寄存器列出来吧。与中断有关的寄存器一共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);
}
现在,终于可以使用按钮控制黄灯了。这回添加了消抖代码,虽然代码不是很正规,但用起来舒服了很多。这个消抖延时时间经过试验,基本可以达到百分之百的命中。

http://www.ppmy.cn/news/140945.html

相关文章

CC3220学习笔记---点亮LED PinMux版

上节课使用了driverlib API来实现了LED灯的点亮&#xff0c;在实际开发中&#xff0c;不可能这样写程序&#xff0c;效率太低。这时就需要把硬件的各种行为抽象出来&#xff0c;帮助开发人员更容易地&#xff0c;更符合人类思维的方式进行操作。 首先理解CC3220 SDK源码的架构&…

CC3220开发板

思前考后&#xff0c;还是得从底层学起&#xff0c;弄清楚芯片。先要在TI-RTOS下搞清楚&#xff0c;再转到Zephyr。问题是TI-RTOS不支持CC3200&#xff0c;仅FreeRTOS支持它。TI-RTOS已经弄过一段&#xff0c;还算有点熟&#xff0c;再花时间学FreeRTOS感觉不太值得。所以还是搞…

可以用的RAID 6:HighPoint RocketRAID 3220评测

可以用的RAID 6&#xff1a;HighPoint RocketRAID 3220评测 <script src"http://tech.ddvip.com/a_dir_d/title_bottom.js"></script> http://tech.ddvip.com 2008年11月14日 社区交流 收藏本文 <script src"http://tech.ddvip.com/a_dir_d…

初创公司办公网搭建-防火墙(用H3C MER3220企业路由器)搭建

初创公司办公网搭建-防火墙 背景公司需求H3C MER3220企业路由器搭建访问控制端外网配置内网配置开启防火墙防护内网间安全策略补充 背景 初创公司团队不少都不会请网络工程师搭建办公网络&#xff0c;所以一般办公网络问题不出意外都堆到了公司一堆可爱的码农身上….   本人四…

RG-AP3220 产品介绍

产品简介 RG-AP3220是锐捷网络推出的802.11n无线网络的无线接入点产品,每路射频单元可以提供高达300Mbps的接入速率,单个AP可以提供600Mbps的接入速率。RG-AP3220产品充分考虑了无线网络安全、射频控制、移动访问、服务质量保证、无缝漫游等重要因素,配合锐捷网络WS系列无线…

《Java并发编程实战》课程笔记(七)

Java 线程 Java 线程的生命周期 通用的线程生命周期 通用的线程生命周期基本上可以用下图这个“五态模型”来描述。这五态分别是&#xff1a;初始状态、可运行状态、运行状态、休眠状态和终止状态。 Java 中线程的生命周期 Java 语言中线程共有六种状态&#xff0c;分别是…

springboot+vue+element-ui在线招投标系统

本在线招投标系统管理员管理个人中心&#xff0c;投标人管理&#xff0c;招标人管理&#xff0c;评标人管理&#xff0c;招标信息管理&#xff0c;投标信息管理&#xff0c;评标信息管理&#xff0c;中标信息管理&#xff0c;系统管理。管理员负责所有的管理信息&#xff0c;招…

HR 的一些专有名词

文章目录 岗位相关JDODOASOP360评测虚线/实线人员 职级相关HRDHRM 各种原则STAR6W1HSMARTPDCA盖洛普 Q12 岗位相关 JD Job Discription 岗位描述 一般会写在招聘信息中&#xff0c;目的在于为求职者快速获取岗位指责信息 OD Organization Development 组织发展 是指将行为…