外部中断是单片机实时地处理外部事件的一种内部机制。当某种外部事件发生时,单片机的中断系统将迫使 CPU 暂停正在执行的程序,转而去进行中断事件的处理;中断处理完毕后.又返回被中断的程序处,继续执行下去。LPC82X 系列的外部中断包含了单引脚中断和模式匹配中断两种方式。接下来,我们除了介绍 LPC82X 单引脚中断外,还会揭秘 LPC82X 的高级应用模式匹配中断。
一、PININT 模块功能简介
1.1 PININT 模块功能简介
- 有 8 路引脚信号输入,每路输入可以与任何一个 IO 引脚配接
− 这意味着每个 IO 脚都能产生外部中断,但最多选出 8 个脚
− 8 路输入可以按两种方式产生中断:引脚中断与模式匹配中断
− 单个引脚可以配接到多路输入
− 注意:即使某个 IO 脚不是当作 GPIO 使用,也能配接到 PININT 的中断源上。
- (常用)引脚(Pin)中断:单路信号产生中断,也就是常说的“外部中断”。
− 触发条件可配置为:
电平触发:高电平、低电平
边沿触发:上升沿、下降沿、双边沿
− 8 路输入每路都在 NVIC 中有自己专用的中断号,共 8 个
- (高级应用)模式匹配(Pattern match)中断:1-8 路信号经过布尔位运算为真时产生中断 ,每路信号亦可以选择电平或刚刚的边沿来触发
− 例如,三人意见表决器,以少数服从多数原则:(A&B)|(B&C)|(C&A)
二、 PININT 单引脚中断
2.1 单引脚中断的功能框图(如图 2-1-1 所示)
- 共 8 路独立工作的引脚输入中断信号,每路都可配接到任何 IO 引脚,而且不限于用作 GPIO 的脚
2.2 使用 PININT 模块的步骤(如图 2-2-1 所示)
2.3 PININT 中断源与 IO 引脚的配接(IO 不是 GPIO)
- 在 SYSCON 模块中,有一组寄存器 PINTSEL[8],用于配接每个 PINTSEL 对应一路中断源(如图 2-3-1 所示)
− 端口号:PINTSEL# / 32
− 引脚号:PINTSEL# % 32
− SYSCON.PINTSEL[5] = 20
− 中断可分为硬件中断(由硬件产生)和软件中断(由当前进程产生)。每个硬件设备或者设备集都有自己的 IRQ(中断请求),且硬件中断又可以分为内部中断和外部中断。外部中断,即 PINT 一般是指由 MCU 外设发出的中断请求,中断请求通过对应的 PIN 脚传递到 MCU;因为每个 PIN 脚都可以配置成多种模式,如:GPIO、ADC、I2C 等,如下举例。
- 即使某个引脚并不作为 GPIO 使用,也能配接到 PININT 的中断源
− 例如:要自动探测 4 个 I2C 接口中哪一个被连接到主机上,即可以把它们 4 个的 SCL 线所在的 IO 脚分别配接到 4 路 PININT 中断上。通信时,发生哪个中断,就认为连接到了哪个 I2C 接口。
− 上例中,IO 引脚并非作为 GPIO 使用,而是作为 I2C 的 SCL 信号。
2.4 PININT 单引脚中断的寄存器配置
- 通过 ISEL 寄存器决定信号的触发是电平还是边沿(如图 2-4-1 所示)
− PINT->ISEL = 0 : 将外部中断源 0 配置为边沿触发
− PINT->ISEL = 1 : 将外部中断源 0 配置为电平触发
- 配置 IENR 和 IENF 寄存器以决定触发方式的细节(如图 2-4-2 所示)
− 电平和边沿共享这一对配置寄存器,但是有各自的用法
电平触发:分别为每路输入设定是否允许电平触发和选择高/低电平
边沿触发:分别为每路输入设定是否分别允许上升沿和下降沿触发
− PINT->IENR = 0 : 将外部中断源 0 除能低电平触发或上升沿触发
− PINT->IENR = 1 : 将外部中断源 0 使能低电平触发或上升沿触发
− PINT->IENF = 0 : 将外部中断源 0 除能高电平触发或下降沿触发
− PINT->IENF = 1 : 将外部中断源 0 使能高电平触发或下降沿触发(使能高电平触发还需要配置 PINT->IENR = 1)
− PINT-> ISEL = 0 : 先将外部中断源 0 配置为边沿触发
− PINT->IENR = 1 : 将外部中断源 0 使能上升沿触发
− PINT->IENF = 1 : 将外部中断源 0 使能下降沿触发
- 边沿在检测后被锁存,因此提供了边沿检测与清除的功能,由寄存器”RISE”和”FALL”负责(如图 2-4-3 所示)
− 被读取时,反映上升沿/下降沿是否已检测待处理
PINT-> RISE = 0 : 自复位或上次写入该位以来,外部中断源 0 没有检测到上升沿。
PINT-> RISE = 1 : 自复位或上次写入此位以来,外部中断源 0 检测到上升沿。
PINT-> FALL = 0 : 自复位或上次写入该位以来,外部中断源 0 没有检测到下降沿。
PINT-> FALL = 1 : 自复位或上次写入此位以来,外部中断源 0 检测到下降沿。
− 被写 1 时(写 0 无效),清除对应的边沿检测锁存标志
PINT-> RISE = 1 : 清除外部中断源 0 的上升边沿检测锁存标志
PINT-> FALL = 1 : 清除外部中断源 0 的下降边沿检测锁存标志
- 通过“IST”寄存器查看各路中断请求的状态,并快速执行常用操作(如图 2-4-4 所示)
− 被读取时,反映当前各路中断是否已请求(触发)
PINT-> IST = 0 : 外部中断源 0 没有被请求(触发)
PINT-> IST = 1 : 外部中断源 0 正在被请求(触发)
− 被写入时,只能写 1,写 0 无效
PINT-> IST = 1 :
对于边沿触发,同时清除双边沿检测的锁存标志
对于电平触发,切换触发电平
注意:电平触发的中断由硬件在有效电平消失时自动清除标志,没有软件清除电平中断标志的操作——会被解释为切换触发电平!
2.5 用于化简“读-改-写”为单次操作的伴侣寄存器
- 为了免除“读-改-写”的麻烦,IENR 和 IENF 都有对应的两个伴侣寄存器,分别用于置 1 和置 0(如图 2-4-5 所示)
− IENR 的伴侣寄存器是 SIENR, CIENR; IENF 的是 SIENF 和 CIENF
− 伴侣寄存器都是写 1 有效的,写 0 无效,避免了读-改-写
− 往置 1 寄存器(SIENR, SIENF)的位里写 1,主寄存器的相应位被置 1
PINT-> SIENR = 1 => PINT-> IENR= 1
PINT-> SIENF = 1 => PINT-> IENR= 1
− 往置 0 寄存器(CIENR, CIENF)的位里写 1,主寄存器的相应位被置 0
PINT-> CIENR = 1 => PINT-> IENR= 0
PINT-> CIENF = 1 => PINT-> IENR= 0
三、PININT模式匹配引擎
3.1 模式匹配引擎功能简介引脚中断功能的扩展
- 模式匹配引擎是 PININT 模块的一部分,扩展了单引脚中断的功能。把多个引脚的状态进行逻辑运算后再产生中断
− 支持“与”,“或”,“非”,不原生支持“异或”
- 实现方式是,创建一个或多个布尔表达式,每个布尔表达式都可以产生中断请求
− 共有 8 个输入变量,每个变量可以与任一个 PININT 输入配接
− 同一变量可以在一个表达式中出现多次,
− 例如(三人表决器):A&B | B&C | C&A
3.2 模式匹配引擎的 8 个输入变量(Slice)(如图 3-2-1 所示)
3.3 变量布尔运算的实现逻辑(如图 3-3-1 所示)
3.4 示例 三人表决器(如图 3-4-1 所示)
四、 PININT单引脚中断实验
4.1 实验目的:
通过本实验,理解和掌握外部引脚中断配置的全过程、边沿触发中断的用法。
4.2 实验软/硬件环境搭建:
− 硬件:LPC824Lite-V1.0(评估板)
− 软件:SDK 从 NXP 官网下载(https://mcuxpresso.nxp.com/en/select);
工程位置:......driver_examples pintpin_interruptmdkpint_pin_interrupt.uvprojx
4.3 实验描述:
− 本实验把 S2 键所在的 PIO0_12 配置为上升沿触发中断,S4 键所在的 PIO0_1 配置为下降沿触发中断。
− S2 按下后或者 S4 按下时在引脚中断 ISR 里设置软件标志——全局变量 g_pinIntFlags 的 bit 1,并在 while 循环里检查此标志,如果设置就反转 LED1。
4.4 实验结果:
按下按键 S2 后,串口调试助手上会打印相关信息(外部中断源 1),并反转 LED1;按下按键 S4 时,立即打印相关信息(外部中断源 2),并反转 LED1。
4.5 实验代码:
/*!
* @brief Call back for PINT Pin interrupt 0-7.
*/
void pint_intr_callback(pint_pin_int_t pintr, uint32_t pmatch_status)
{
g_pinIntFlags = true;
PRINTF("frnPINT Pin Interrupt %d event detected.", pintr);}
/*!
* @brief Main function
*/
int main(void)
{
/* Define the init structure for the output LED pin*/
gpio_pin_config_t led_config = {
kGPIO_DigitalOutput,
0,
};
……
/* Init output LED GPIO. */
GPIO_PortInit(GPIO, 0U);
/* Connect trigger sources to PINT */
//将外部中断源与对应引脚相连
SYSCON_AttachSignal(SYSCON, kPINT_PinInt1, DEMO_PINT_PIN_INT1_SRC);
SYSCON_AttachSignal(SYSCON, kPINT_PinInt2, DEMO_PINT_PIN_INT2_SRC);
……
/* Initialize PINT */
//初始化 PINT 的外围设备
PINT_Init(PINT);
/* 设置外部中断源 1 为上升沿触发,并使能 */
/* Setup Pin Interrupt 1 for rising edge */
PINT_PinInterruptConfig(PINT, kPINT_PinInt1, kPINT_ PinIntEnableRiseEdge, pint_intr_callback);
/* Enable callbacks for PINT1 by Index */
PINT_EnableCallbackByIndex(PINT, kPINT_PinInt1);
/* 设置外部中断源 2 为下降沿触发,并使能 */
/* Setup Pin Interrupt 2 for falling edge */
PINT_PinInterruptConfig(PINT, kPINT_PinInt2, kPINT_PinIntEnableFallEdge, pint_intr_callback);
/* Enable callbacks for PINT2 by Index */
PINT_EnableCallbackByIndex(PINT, kPINT_PinInt2);
//LED 引脚配置,输出高电平
GPIO_PinInit(GPIO, 0U, 7U, &led_config);
GPIO_PinWrite(GPIO, 0U, 7U, 1);
……
while (1)
{
__WFI();
if(g_pinIntFlags)
{
GPIO_PortToggle(GPIO, 0U, 1u << 7U);
g_pinIntFlags = false;
}
}
}
五、 PININT 模式匹配引擎实验
5.1 实验目的:
通过本实验,理解和掌握外部引脚中断配置成模式匹配引擎的全过程及用法。
5.2 实验软/硬件环境搭建:
− 硬件:LPC824Lite-V1.0(评估板)
− 软件:SDK 从 NXP 官网下载(https://mcuxpresso.nxp.com/en/select);
工程位置:......driver_examples pintpattern_matchmdkpint_pattern_match.uvprojx
5.3 实验描述:
− 本实验把 S2 键所在的 PIO0_12 连接到外部中断源 2,S4 键所在的 PIO0_1 连接到外部中断源 0。
− 把外部中断源 0 的下降沿触发配置为单引脚中断;将外部中断源 0 的上升沿触发和外部中断源 2 的下降沿触发配置为模式匹配引擎。
5.4 实验结果:
按下按键 S2,串口调试助手上不会打印;按下按键 S4,立即打印相关信息(外部中断源 0);按下按键 S4 后再按下 S2,打印相关信息(外部中断源 2)。
5.5 实验代码:
/*!
* @brief Call back for PINT Pin interrupt 0-7.
*/
void pint_intr_callback(pint_pin_int_t pintr, uint32_t pmatch_status)
{
PRINTF("frnPINT Pin Interrupt %d event detected. PatternMatch status = %8brn", pintr, pmatch_status);
}
/*!
* @brief Main function
*/
int main(void)
{
pint_pmatch_cfg_t pmcfg;
……
/* Connect trigger sources to PINT */
//将外部中断源与对应引脚相连
SYSCON_AttachSignal(SYSCON, kPINT_PatternMatchInp0Src, kSYSCON_GpioPort0Pin1ToPintsel);
SYSCON_AttachSignal(SYSCON, kPINT_PatternMatchInp1Src, kSYSCON_GpioPort0Pin12ToPintsel);
……
/* Initialize PINT */
//初始化 PINT 的外围设备
PINT_Init(PINT);
/*
将模式匹配引擎变量 0 配置为单引脚中断
设置变量 0 的外部中断源为外部中断源 0,下降沿触发,结果变量
*/
/* configure kPINT_PatternMatchBSlice0 to show the single inputsrc */
/* Setup Pattern Match Bit Slice 0 */
pmcfg.bs_src = DEMO_PINT_BSLICE0_SRC;
pmcfg.bs_cfg = kPINT_PatternMatchStickyFall;
pmcfg.callback = pint_intr_callback;
pmcfg.end_point = true;
PINT_PatternMatchConfig(PINT, kPINT_PatternMatchBSlice0, &pmcfg);
/* Enable callbacks for PINT0 by Index */
//使能外部中断源 0
PINT_EnableCallbackByIndex(PINT, kPINT_PinInt0);
/*
将模式匹配引擎变量 1 和模式匹配引擎变量 2 配置为组合中断
设置变量 1 的中断源为外部中断源 0,上升沿触发,中间变量
设置变量 2 的中断源为外部中断源 2,下降沿触发,结果变量
*/
/* configure kPINT_PatternMatchBSlice1 and kPINT_PatternMatchBSlice2 to show the combined inputsrc */
/* Setup Pattern Match Bit Slice 1 */
pmcfg.bs_src = DEMO_PINT_BSLICE1_SRC;
pmcfg.bs_cfg = kPINT_PatternMatchStickyRise;
pmcfg.callback = pint_intr_callback;
pmcfg.end_point = false;
PINT_PatternMatchConfig(PINT, kPINT_PatternMatchBSlice1, &pmcfg);
/* Setup Pattern Match Bit Slice 2 for falling edge detection */
pmcfg.bs_src = DEMO_PINT_BSLICE2_SRC;
pmcfg.bs_cfg = kPINT_PatternMatchStickyRise;
pmcfg.callback = pint_intr_callback;
pmcfg.end_point = true;
PINT_PatternMatchConfig(PINT, kPINT_PatternMatchBSlice2, &pmcfg);
/* Enable callbacks for PINT2 by Index */
//使能外部中断源 2
PINT_EnableCallbackByIndex(PINT, kPINT_PinInt2);
/* Enable PatternMatch */
//使能模式匹配引擎
PINT_PatternMatchEnable(PINT);
……
while (1)
{
__WFI();
}
}
|