使用恩智浦MCXC444 MCU中的FlexIO模块轻松实现边沿捕捉

描述

总体概述

在MCU开发中,我们经常需要对外部信号的上升沿或下降沿进行检测,并据此触发中断。但在实际项目中,你可能会遇到这样的问题:

某些引脚(例如MCXC444的PortE)并不支持GPIO中断功能。

这时候,如果再调整硬件已经来不及,该怎么办?

一个非常实用的思路是:借助FlexIO来“模拟中断”。

FlexIO本质上是一个高度可编程的外设,不仅可以模拟UART、SPI、I²C,还能灵活实现:

波形捕捉

边沿检测

自定义时序逻辑

本文就带你一步步实现:利用FlexIO Timer,在FLEXIO_D4(PTE20)引脚上捕捉上升沿并触发中断~

一、设计思路

FlexIO Timer的核心机制如下:

PinSelect  → 选择输入引脚(FLEXIO_D4 PTE20)

TimerDecrement  → 由引脚电平驱动计数

TimerReset  → 在上升沿复位计数器

TimerCompare  → 计数达到比较值时置位中断标志

这样就能实现:每检测到一次上升沿,就触发一次中断

二、实现步骤

2.1 时钟配置

为FlexIO模块开启时钟。

 

/* Set FLEXIO clock source. */
  CLOCK_SetFlexio0Clock(SIM_FLEXIO_CLK_SEL_IRC48M_CLK);

 

2.2 配置引脚

PTE20 → 复用为 FLEXIO0_D4 输入

PTE30 → GPIO 输出(用于产生测试波形)

 

/* PORTE20 (pin 9) is configured as FXIO0_D4 */
   PORT_SetPinMux(PORTE, 20U, kPORT_MuxAlt6);
 /* PORTE30 (pin 18) is configured as PTE30 */
   PORT_SetPinMux(PORTE, 30U, kPORT_MuxAsGpio);

 

2.3 配置 FlexIO Timer

 

flexio_config_t flexioConfig;
  flexio_timer_config_t timerConfig;
 
   /* 3. 初始化 FlexIO 模块 */
  FLEXIO_GetDefaultConfig(&flexioConfig);
  FLEXIO_Init(BOARD_FLEXIO_BASE, &flexioConfig);
 
           memset(&timerConfig, 0, sizeof(timerConfig));
             timerConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
             timerConfig.pinSelect = 4;
             timerConfig.pinPolarity = kFLEXIO_PinActiveHigh;
 
             timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_PININPUT(FLEXIO_PIN);
            timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveHigh; // rising edge
            timerConfig.triggerSource   = kFLEXIO_TimerTriggerSourceExternal;
 
            timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveHigh;
 
            timerConfig.timerMode = kFLEXIO_TimerModeSingle16Bit;
            timerConfig.timerOutput = kFLEXIO_TimerOutputOneNotAffectedByReset;
            timerConfig.timerDecrement= kFLEXIO_TimerDecSrcOnPinInputShiftPinInput;
            timerConfig.timerReset = kFLEXIO_TimerResetOnTimerPinRisingEdge;
            timerConfig.timerDisable = kFLEXIO_TimerDisableNever;
            timerConfig.timerEnable = kFLEXIO_TimerEnabledAlways;
            timerConfig.timerCompare = 0x0001;
            FLEXIO_SetTimerConfig(BOARD_FLEXIO_BASE, 0, &timerConfig);
 
            FLEXIO_EnableTimerStatusInterrupts(BOARD_FLEXIO_BASE, 1U << 0);
            EnableIRQ(UART2_FLEXIO_IRQn);
            NVIC_SetPriority(UART2_FLEXIO_IRQn, 2);

 

关键点说明:

triggerSelect

FLEXIO_TIMER_TRIGGER_SEL_PININPUT(FLEXIO_PIN);

引脚输入作为触发源

timerReset

kFLEXIO_TimerResetOnTimerPinRisingEdge,确保每次上升沿都会触发

timerDecrement

kFLEXIO_TimerResetOnTimerPinRisingEdge, 由外部引脚驱动计数

pinConfig/pinSelect

指定输入引脚为FlexIO_D4

timerMode

单次计数模式,适合捕捉事件

timerCompare = 0x01, 确保每次边沿都会立刻触发中断。值太大会导致需要多次脉冲才触发

每次边沿立即产生中断(非常关键!)

注意:

MCXC444没有单独的 FLEXIO_IRQn, 而是复用在:UART2_FLEXIO_IRQn

2.4 中断服务函数

 

void UART2_FLEXIO_IRQHandler(void)
{
   uint32_t flags = FLEXIO_GetTimerStatusFlags(BOARD_FLEXIO_BASE);
   if (flags & (1U << FLEXIO_TIMER))
   {
      FLEXIO_ClearTimerStatusFlags(BOARD_FLEXIO_BASE, 1U << FLEXIO_TIMER);
       PRINTF("FlexIO: Rising edge detected!
");
   }
};

 

三、实验结果

当外部信号接入PTE20(FLEXIO0_D4)并产生上升沿时:

FlexIO Timer 成功捕获

中断被触发

串口打印提示信息

实验证明:

FlexIO完全可以作为“软件定义的外部中断模块”使用

四、重点优化

很多人认为:

没有GPIO中断=无法检测外部事件

但实际上,通过FlexIO,你可以:

自定义触发条件

灵活绑定任意引脚

实现比传统 GPIO 更复杂的逻辑

本质上,FlexIO提供的是一种“更高级的硬件编程能力”。当GPIO中断受限时,FlexIO就是你的“外挂神器”——不仅能替代,还能做得更强。

TIC: Harry Zhang

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分