欢迎来到Introzo百科
Introzo百科
当前位置:网站首页 > 技术 > 批子恒嵌入式:比较NXP全系列MCU(包括Kinetis/LPC/i.MXRT/MCX)GPIO电平中断设计的差异

批子恒嵌入式:比较NXP全系列MCU(包括Kinetis/LPC/i.MXRT/MCX)GPIO电平中断设计的差异

日期:2023-10-02 16:06


  大家好,我是皮子恒,一个认真科技的痞子。今天皮子恒给大家介绍一下NXP全系列MCU(包括Kinetis、LPC、i.MXRT、MCX)在GPIO电平中断设计上的差异。

  在皮子恒的旧文章《以i.MXRT1xxx的GPIO模块为例谈谈中断处理函数(IRQHandler)的标准流程》中,皮子恒主要介绍了GPIO通用控制以及最常用的输入边沿中断的知识。近日,NXP官方社区有用户反映,i.MXRT1060上的GPIO中断状态寄存器(GPIO->ISR)在有效电平中断发生后不需要手动清零(W1C)。切换到平铺状态后自动清除,与手册中的描述不一致。

  首先,在皮子衡的认知中,GPIO输入电平中断并没有具体的应用场景。想象一下,如果 GPIO 中断事件是由输入电平值触发的。如果出现有效输入电平且其状态没有改变,则GPIO中断响应函数将被重复执行(此时CPU时间片不能再分配给主函数)。什么样的任务需要这样的处理?暂且不论应用场景如何,皮子恒今天就从NXP全系列MCU的行为角度进行对比。

1。 I/O中断控制模块的差异

  NXP现有经典Arm Cortex-M MCU产品线有以下五类。它们的不同之处在于GPIO通用控制和中断控制外设。首先,i.MXRT四位/Kinetis/LPC这三条线是完全不同的外设。然后,在LPC外设的基础上增强了i.MXRT三位数,并与Kinetis结合了最新的MCX系列。和LPC外围设备。

芯片系列 I/O 通用控制 I/O中断控制
Kinetis GPIO 类型1 港口
LPC GPIO 类型2品脱
i.MXRT 四位数 GPIO 类型3 GPIO 类型3
i.MXRT 三位数 GPIO 类型2 GPIO type2(添加中断A/B)
品脱
MCX GPIO 类型1 GPIO 类型 1(集成 Kinetis 端口)
品脱

2。不同系列MCU下的测试结果

  根据上一节的外设情况,我们知道只要测试了i.MXRT四位/Kinetis/LPC这三个系列,剩下的两个系列自然就不需要测试了。

2.1 Kinetis

  Kinetis系列分为K/KL/KE/KS/KW/KV/KM/K32L等几个子系列,但它们在GPIO中断设计上是相同的。皮子恒选择了MKL03Z芯片进行测试。查看其手册,PORTx->PCRn[ISF]位或PORTx->ISFR寄存器标记了中断状态并表明需要进行W1C操作。

  我们可以直接在\SDK_2.3.1_FRDM-KL03Z\boards\frdmkl03z\driver_examples\gpio\input_interrupt例程上进行测试。我们只需要进行简单的修改即可。皮子恒提取主要代码如下。 FRDM-KL03Z板上的SW3按钮对应PTB5引脚(按下时为低电平,释放时为高电平)。在代码设计中,按一次SW3将打印一次。根据测试结果,即使Kinetis上出现电平中断,也必须手动清除PORTx->ISFR寄存器,这与手册中的描述一致。

IRQ功能中Flag是否被清除 SW3 动作 IRQ 执行 打印结果
上电时默认释放(高电平) IRQ功能未触发
SW3 按下(低电平) IRQ功能重复执行
SW3 释放(高电平) IRQ 功能不再触发 出现一次并打印
没有 上电时默认释放(高电平) IRQ功能未触发
SW3 按下(低电平) IRQ功能重复执行
SW3 释放(高电平) IRQ功能重复执行
易失性 bool g_ButtonPress = false;
无效 PORTB_IRQHandler(无效)
{
    // 清除中断标志
    PORTB->ISFR = 1U << 5U;
    g_ButtonPress = true;
}
int 主函数(无效)
{
    // 省略PTB5引脚的PINMUX配置
    gpio_pin_config_t sw_config = {
        kGPIO_数字输入,0,
    };
    //此处仅修改:将GPIO中断模式改为低电平触发
    PORT_SetPinInterruptConfig(PORTB, 5U, kPORT_InterruptLogicZero);
    NVIC_EnableIRQ(PORTB_IRQn);
    GPIO_PinInit(GPIOB, 5U, &sw_config);
    而 (1)
    {
        如果(g_ButtonPress)
        {
            延迟();
            PRINTF(" %s 被按下 \r\n", "SW3");
            g_ButtonPress = false;
        }
    }
}

2.2 i.MXRT 四位数

  i.MXRT四位系列分为RT1010/1015/1020/1040/1050/1060/1160/1170/1180等几个子型号,但它们具有相同的GPIO中断设计。皮子恒选择了i.MXRT1062芯片进行测试。查看其手册,GPIOx->ISR寄存器标记了中断状态,也表明需要进行W1C操作。

  我们可以直接在\SDK_2_12_1_EVK-MIMXRT1060\boards\evkmimxrt1060\driver_examples\gpio\input_interrupt例程上进行测试。我们只需要进行简单的修改即可。主要代码如下。 MIMXRT1060-EVK 板上的 SW8 按钮对应 WAKEUP_GPIO5[0] 引脚(按下时为低电平,释放时为高电平)。在代码设计中,按一次SW8将打印一次。从测试结果来看,如果i.MXRT四位数字上出现电平中断,则电平状态切换时GPIOx->ISR寄存器会自动清零。这与手册中的描述略有不同,但这种设计看起来比 Kinetis 更好。更合理。

IRQ功能中Flag是否被清除 SW8 动作 IRQ 执行 打印结果
是/否 上电时默认释放(高电平) IRQ功能未触发
SW8 按下(低电平) IRQ功能重复执行
SW8 已释放(高电平) IRQ 功能不再触发 出现一次并打印
易失性 bool g_InputSignal = false;
无效GPIO5_Combined_0_15_IRQHandler(无效)
{
    // 清除中断标志
    GPIO5->ISR = 1U << 0U;
    g_InputSignal = true;
    __DSB();
}
int 主函数(无效)
{
    // PINMUX 配置省略 WAKEUP 引脚gpio_pin_config_t sw_config = {
        kGPIO_数字输入,
        0,
        kGPIO_IntLowLevel, //此处只需修改:将GPIO中断模式改为低电平触发
    };
    GPIO_PortEnableInterrupts(GPIO5, 1U << 0U);
    NVIC_EnableIRQ(GPIO5_Combined_0_15_IRQn);
    GPIO_PinInit(GPIO5, 0U, &sw_config);
    而 (1)
    {
        如果(g_输入信号)
        {
            延迟();
            PRINTF(" %s 已打开。\r\n", "SW8");
            g_InputSignal = false;
        }
    }
}

2.3 LPC

  LPC系列分为800/1x00/4000/4300/51Uxx/54000/5500等多个子型号,但它们具有相同的GPIO中断设计。皮子恒选择LPC54114芯片进行测试。检查它的手册。 PINT->IST 寄存器标记中断状态。这里,边缘模式和电平模式之间的区别是针对W1C操作而进行的。对于电平模式,W1C 是切换有效电平逻辑。

  我们可以直接在 \SDK_2_9_0_LPCXpresso54114\boards\lpcxpresso54114\driver_examples\pint\pin_interrupt 例程上进行测试。我们只需要进行简单的修改即可。主要代码如下。 LPCXpresso-54114板上的SW1按钮对应PIO0[24]引脚(按下时为低电平,释放时为高电平)。在代码设计中,按一次SW1将打印一次。从测试结果来看,如果是LPC上的电平中断,则电平状态切换时PINT->IST寄存器会自动清零,与手册中的描述略有不同,并且如果主动进行W1C操作添加到中断处理函数中,效果就变成了双边沿中断。这种设计比 i.MXRT 四位数更进了一步。

IRQ功能中Flag是否被清除 SW1 动作 IRQ 执行 打印结果
没有 上电时默认释放(高电平) IRQ功能未触发
SW1 按下(低电平) IRQ功能重复执行
SW1 释放(高电平) IRQ 功能不再触发 出现一次并打印
上电时默认释放(高电平) IRQ功能未触发
SW1 按下(低电平) IRQ功能执行一次 出现一次并打印
SW1 释放(高电平) IRQ功能执行一次 出现一次并打印
易失性 bool g_ButtonPress = false;
无效PIN_INT0_DriverIRQHandler(无效)
{
    uint32_t pmstatus = PINT_PatternMatchResetDetectLogic(PINT);
    if (s_pintCallback[kPINT_PinInt0] != NULL)
    {
        s_pintCallback[kPINT_PinInt0](kPINT_PinInt0, pmstatus);
    }
    // 清除中断标志
    PINT->IST = (1UL << (uint32_t)kPINT_PinInt0);
    __DSB();
}
无效pint_intr_callback(pint_pin_int_t pintr,uint32_t pmatch_status)
{
    g_ButtonPress = true;
}
int 主函数(无效)
{
    INPUTMUX_Init(INPUTMUX);
    INPUTMUX_AttachSignal(INPUTMUX, kPINT_PinInt0, kINPUTMUX_GpioPort0Pin24ToPintsel);
    PINT_Init(PINT);
    //此处仅修改:将GPIO中断模式改为低电平触发
    PINT_PinInterruptConfig(PINT, kPINT_PinInt0, kPINT_PinIntEnableLowLevel, pint_intr_callback);
    PINT_EnableCallbackByIndex(PINT, kPINT_PinInt0);
    而 (1)
    {
        如果(g_ButtonPress)
        {
            延迟();PRINTF(" 检测到 %s 引脚中断事件 \r\n", "SW1");
            g_ButtonPress = false;
        }
    }
}

  至此,皮子恒就介绍完了NXP全系列MCU在GPIO电平中断设计上的差异。掌声在哪里~~~

欢迎订阅

文章将同时发布到我的博客园主页、CSDN主页、知乎主页、微信公众号平台。

微信搜索“痽子hengembedded”或扫描下方二维码即可在手机上立即观看。

关灯