在线时间2233 小时
UID3253523
注册时间2016-3-21
NXP金币3997
该用户从未签到
超级版主
 
- 积分
- 25704
- 最后登录
- 2025-9-30
|
本帖最后由 小恩GG 于 2025-9-29 17:48 编辑
一、概述
在 MCU 开发过程中,我们经常需要检测外部信号的上升沿或下降沿,并据此触发中断。然而,有些端口(如 MCXC444 的 PortE)并不直接支持 GPIO 中断,这时候就需要寻找替代方案。
FlexIO 模块本质上是一个可编程外设,可以模拟 UART、SPI、I²C,也可以灵活实现 波形捕捉、边沿检测。我们就利用它的 Timer 功能实现外部边沿捕捉。
本文将介绍如何利用 FlexIO 模块,在 FLEXIO_D4(PTE20)引脚上实现上升沿捕捉中断。
硬件环境:
开发板:FRDM-MCXC444
软件环境:
IDE:MCUXpresso IDE v11.9.0
SDK:SDK Builder | MCUXpresso SDKBuilder (nxp.com)
基础工程: Hello World
二、设计思路
FlexIO Timer 的核心思想是:
PinSelect → 指定输入引脚(FLEXIO_D4 ↔ PTE20)。
TimerDecrement → 由引脚电平驱动计数。
TimerReset → 在引脚上升沿复位计数器。
TimerCompare → 计数到比较值时置位中断标志(TIF)。
这样就能保证:每次上升沿触发一次中断。
三、实现步骤
3.1 时钟配置
- /* Set FLEXIO clock source. */
- CLOCK_SetFlexio0Clock(SIM_FLEXIO_CLK_SEL_IRC48M_CLK);
复制代码 为 FlexIO 模块开启时钟。
3.2 配置引脚
- /* 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);
复制代码
将 PTE20 复用为 FLEXIO0_D4。为了产生上升延和下降延,将 PTE30配置成GPIO 输出。
3.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,这样每次上升沿都会触发 flag。
timerDecrement: 选择 kFLEXIO_TimerDecSrcOnPinInputShiftPinInput,保证计数由外部引脚驱动。
pinConfig/pinSelect:指定输入引脚为 FlexIO_D4。
timerMode:单次计数模式,用于捕获事件而非周期计数。
TimerCompare: 设为 0x01,确保每次边沿都会立刻触发中断。值太大会导致需要多次脉冲才触发。
MCXC444 没有单独的 FLEXIO_IRQn,而是复用在 UART2_FLEXIO_IRQ
3.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!\r\n");
- }
- };
复制代码
四、实验结果
当外部信号接入 PTE20 (FLEXIO0_D4) 并产生上升沿时,FlexIO Timer检测到事件,触发中断,串口会输出提示信息。
验证了 FlexIO Timer 可以作为额外的“可编程外部中断”使用。
五、总结
本文展示了如何利用 MCXC444 MCU 的 FlexIO 模块实现边沿检测中断。
相比传统 GPIO 中断方式,FlexIO 提供了更高的灵活性,适合在 GPIO 资源有限或需要复杂触发条件的场景下使用。
|
|