这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 【FRDM-MCXA366】③彻底搞通MCX系列MCU的GPIO(输出、输入、中

共2条 1/1 1 跳转至

【FRDM-MCXA366】③彻底搞通MCX系列MCU的GPIO(输出、输入、中断)

菜鸟
2026-09-03 22:11:30     打赏

本篇先吐槽下,MCX 是 NXP 新一代通用物联网 / 工业 MCU,接替 Kinetis、LPC 系列,统一软件生态(MCUXpresso),内核以 Cortex‑M33/M0+ 为主,集成 SmartDMA、FlexIO、EdgeLock 安全子系统,覆盖低成本、主流、低功耗、无线、AI 边缘多个档位。


系列内核主频核心特点典型应用代表开发板
MCX‑CCortex‑M0+48 MHz高性价比,16 位 ADC,USB/LCD,小封装,替代 8/16 位 MCU小家电、简单传感器、IO 控制FRDM‑MCXC444
MCX‑A(主流)Cortex‑M3396‑240 MHz强模拟、电机 PWM、FlexIO、SmartDMA;部分型号集成 T1S 工业以太网工业 IO、电机控制、家电、楼宇控制FRDM‑MCXA156 / FRDM‑MCXA346
MCX‑L(超低功耗)2×M33 + M0+

M33




@96 M,M0+@10 M

多电源域,有源功耗~23 μA/MHz,M0 + 专做常开检测电池设备、传感器节点、可穿戴FRDM‑MCXL556
MCX‑W(无线)Cortex‑M3396 MHz内置 BLE、Thread、Zigbee,支持 Matter;W72 支持蓝牙 6.0 信道测距智能家居、Matter 节点、无线传感器FRDM‑MCXW72
MCX‑N(AI / 高性能)单 / 双 Cortex‑M33150 MHzeIQ‑Neutron NPU、PowerQuad DSP、CAN‑FD、FlexSPI、SDIO;EdgeLock PSA‑L3 安全认证边缘 AI、HMI、音频、摄像头采集FRDM‑MCXN947、FRDM‑MCXN236
MCX‑ECortex‑M3396 MHz5V 耐压 IO,工业强抗干扰工业现场 5V 输入场景


最早的型号是MCXN947,2022‑11‑02 正式发布,2023 年样品,2024 量产。

远远晚于STM32,甚至瑞萨RA系列MCU,这就导致网上可参考的中文资料非常少,野火、正点原子也没有推出对应的开发板和教程,这就导致开发难度比较大,得死啃SDK中的驱动库。


image.png


比如:IO输出为1的函数

/*!
 * @brief Sets the output level of the multiple GPIO pins to the logic 1.
 *
 * @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
 * @param mask GPIO pin number macro
 */
static inline void GPIO_PortSet(GPIO_Type *base, uint32_t mask)
{
#if !(defined(FSL_FEATURE_GPIO_HAS_NO_INDEP_OUTPUT_CONTROL) && FSL_FEATURE_GPIO_HAS_NO_INDEP_OUTPUT_CONTROL)
base->PSOR = GPIO_FIT_REG(mask);
#else
base->PDOR |= GPIO_FIT_REG(mask);
#endif
}


好在MCUXpresso IDE v25.6.136也提供了图形化的配置软件,类似STM32的CubeIDE和CubeMX。


需要说明的是,在上一贴中,详细说明了最新IDE  MCUXpresso IDE v25.6.136默认是不支持MCXA366的,需要额外下载软件。

本篇为了方便讲解,以MCXA153为例介绍GPIO的 输出、输入、中断

其他型号也都一样。


话不多说,先贴main.c文件

#include <stdio.h>
#include "board.h"
#include "peripherals.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "fsl_debug_console.h"
#include "fsl_common.h"

#define SDK_DelayMs(ms)  SDK_DelayAtLeastUs((ms)*1000U, 100000000U)

volatile bool SW3_flag = false;  //中断和main循环共享的全局标志,必须加volatile

/* TODO: insert other include files here. */

/* TODO: insert other definitions and declarations here. */

/*
 * @brief   Application entry point.
 */
int main(void) {

/* Init board hardware. */
BOARD_InitBootPins();
BOARD_InitBootClocks();
BOARD_InitBootPeripherals();
#ifndef BOARD_INIT_DEBUG_CONSOLE_PERIPHERAL
/* Init FSL debug console. */
BOARD_InitDebugConsole();
#endif

PRINTF("Hello World\r\n");

/* Force the counter to be placed into memory. */
volatile static int i = 0 ;
/* Enter an infinite loop, just incrementing a counter. */
while(1) {
i++ ;
/* 'Dummy' NOP to allow source level single stepping of
            tight while() loop */

//GPIO_PortToggle(GPIO3, 1u << 12);
//SDK_DelayMs(500);               //延时500ms

/*GPIO_PortSet(GPIO3, 1u << 12);
        SDK_DelayMs(500);
        GPIO_PortClear(GPIO3, 1u << 12);
        SDK_DelayMs(500);*/

/*        if(GPIO_PinRead(GPIO1, 7) == 0)
        {GPIO_PortSet(GPIO3, 1u << 12);}
        else
        {GPIO_PortClear(GPIO3, 1u << 12);}*/


if(GPIO_PinRead(GPIO3, 29) == 0)   //SW2 轮询
{GPIO_PortSet(GPIO3, 1u << 0);}
else
{GPIO_PortClear(GPIO3, 1u << 0);}


if(SW3_flag == true)              //SW3 中断
{
		SW3_flag = false;
		GPIO_PortToggle(GPIO3, 1u << 12);
}

__asm volatile ("nop");
}
return 0 ;
}


/* GPIO1_IRQn interrupt handler */
void INT_0_IRQHANDLER(void) {
/*  Place your code here */
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F
     Store immediate overlapping exception return operation might vector to incorrect interrupt. */
	uint32_t flags = GPIO_GpioGetInterruptFlags(GPIO1);   //GPIO_PinGetInterruptFlag(GPIO_Type *base, uint32_t pin);
	if (flags & (1u << 7))
	{
		SW3_flag = true;
		//GPIO_PortToggle(GPIO3, 1u << 12);
		GPIO_PinClearInterruptFlag(GPIO1,7);
	}




#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}



要彻底搞通MCX系列MCU的GPIO(输出、输入、中断)

在此之前需要先配置IO的功能选择(GPIO)、方向(输入输出)、初始值、中断。

点击IDE右侧的芯片图标,打开引脚配置页面。

需要重点吐槽下,如果IDE有多个工程,即便选择了某个工程,一定还要在左侧的工程栏选中正确的工程,IDE他不会自动切换,这真是个Bug。

image.png


image.png


image.png



接下来配置 GPIO

P3_0 是输出——LED  BLUE

P3_12 是输出——LED  RED


P1_7是按键输入——SW3  下降沿中断

P3_29是按键输入——SW2  关闭中断


image.png


接下来点击IDE右上角的USB图标配置外设(中断 NVIC)

屏幕截图 2026-08-30 184149.png


新建NVIC,选择中断源为GPIO0

enable中断优先级0

使用默认中断函数void INT_0_IRQHANDLER(void),并在其中编写指令。


/* GPIO1_IRQn interrupt handler */
void INT_0_IRQHANDLER(void) {
  /*  Place your code here */
  /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F
     Store immediate overlapping exception return operation might vector to incorrect interrupt. */
  #if defined __CORTEX_M && (__CORTEX_M == 4U)
    __DSB();
  #endif
}

屏幕截图 2026-08-30 184243.png


全部配置完成后,点击菜单栏左侧“更新源代码”,相关代码就自动生成了。

image.png


  1. 延时函数


#define SDK_DelayMs(ms)  SDK_DelayAtLeastUs((ms)*1000U, 100000000U)

    2.    GPIO输出

GPIO_PortToggle(GPIO3, 1u << 12);
SDK_DelayMs(500);               //延时500ms

GPIO_PortSet(GPIO3, 1u << 12);
SDK_DelayMs(500);
GPIO_PortClear(GPIO3, 1u << 12);
SDK_DelayMs(500);

3.    GPIO输入(不带中断)

采用轮询方式

if(GPIO_PinRead(GPIO3, 29) == 0)   //SW2 轮询
{GPIO_PortSet(GPIO3, 1u << 0);}
else
{GPIO_PortClear(GPIO3, 1u << 0);}


4. GPIO输出(带中断)

采用前后台

后台中断仅获取中断,并置状态位SW3_flag

前台while(1)中根据SW3_flag状态执行对应操作


中断函数(后台)

/* GPIO1_IRQn interrupt handler */
void INT_0_IRQHANDLER(void) {
/*  Place your code here */
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F
     Store immediate overlapping exception return operation might vector to incorrect interrupt. */
	uint32_t flags = GPIO_GpioGetInterruptFlags(GPIO1);   //GPIO_PinGetInterruptFlag(GPIO_Type *base, uint32_t pin);
	if (flags & (1u << 7))
	{
		SW3_flag = true;
		//GPIO_PortToggle(GPIO3, 1u << 12);
		GPIO_PinClearInterruptFlag(GPIO1,7);
	}




#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}


while(1)函数(前台)

if(SW3_flag == true)              //SW3 中断
{
		SW3_flag = false;
		GPIO_PortToggle(GPIO3, 1u << 12);
}


这样就实现了LED输出 闪烁

按键SW2按下 输入轮询

按键SW3按下 中断执行




专家
2026-09-04 08:12:54     打赏
2楼

谢谢楼主分享


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]