本文介绍了恩智浦 FRDM-MCXA156 开发板的相关软硬件资料、开发环境搭建流程、工程编译、上传与测试流程等。
1.介绍主控
MCXA156 系统框图


® Arm Cortex-M33® 96MHz,带 396 CoreMark (4.12 CoreMark/MHz)
高达 1MB 的闪存、高达 128KB 的 SRAM、带 ECC 的 8 kB SRAM
所有 RAM 都可以保留到深度掉电模式
温度范围:-40 °C 至 125 °C
Arm 32 位 Cortex-M33 CPU,带 FPU 和 DSP 扩展指令 set、no TrustZone、no MPU
单区闪存:高达 1024 kB 的闪存,带 ECC(支持 1 位) 校正和两位检测)
Flash 的最小编程大小为 16 字节
支持 8 kB 粒度的 Flash Swap
具有 4 kB RAM 的缓存引擎
高达 128 kB 的 RAM,可通过 ECC 配置高达 8 kB(支持 单位校正、两位检测)
所有 RAM 都可以保留到深度 Power-down 模式
模拟
最多两个采样率为 4.0 的单端 16 位 ADC 12 位模式下的 Msamples/s,16 位模式下的 3.2Msamples/sec。 多达 32 个 ADC 输入通道,具有多个内部和外部通道 触发输入
每个 ADC 一个集成温度传感器
一个 12 位 DAC
两个高速比较器,具有 8 个输入引脚和一个 8 位 DAC 作为 内部参考,一个比较器功能低至 省电模式,可用作低功耗的唤醒源 模式
一个运算放大器支持 PGA
定时器
多达 5 个 32 位标准通用异步 定时器/计数器,每个定时器最多支持四个捕获输入和 4 个 compare 输出;可以选择特定的计时器事件 生成 DMA 请求
低功耗定时器
频率测量定时器
窗口式看门狗定时器
唤醒定时器
从 1 MHz 时钟运行的 Microtick 计时器 (UTICK)。这可以从 低功耗模式直至关闭闪光灯的深度睡眠,功耗极低
42 位自由运行的操作系统定时器作为系统的连续时基,可用于任何 低功耗模式
通信接口
USB 2.0 全速器件控制器,带片上 PHY,支持无晶振操作 设备模式
多达 2 个 LPSPI 模块,在初级模式下支持高达 50MHz 的工作频率
多达四个 LPI2C,支持 Standard、Fast、Fast+ 和 Ultra Fast 模式
多达 5 个 LPUART 提供异步、串行通信功能
一个 I3C 总线接口
一个 FlexIO 可编程为各种串行和并行接口,包括但不限于 仅限于显示驱动程序和摄像头接口(取决于部件号)
一个带 FD 的 FlexCAN(取决于零件编号)
高级电机控制子系统
最多两个 FlexPWM,每个 FlexPWM 有 3 个子模块,提供 12 个 PWM 互补输出(无 Nanoedge 模块)
多达两个正交解码器 (eQDC),提供位置/速度的接口能力 工业电机控制应用中使用的传感器
最多两个 AOI(和/或/反转)模块支持最多 4 个输出触发器
MCUXpresso生态系统支持
选择 IDE 选项
引脚、时钟、外设、安全和内存配置工具
安全编程和配置工具
软件开发工具包 (SDK)
设备生命周期管理
Flash 读/写/执行权限保护 MBC 并可锁定
每个设备 128 位通用唯一标识符 (UUID) 符合 IETF 的 RFC4122 版本 5 规范
代码看门狗和抗毛刺攻击的密钥访问 (Glikey) 支持安全监控
LQFP100 (14x14 mm)
: MCX A14x/15x MCU搭载Arm® Cortex® M33内核,提供可扩展的设备选项、低功耗和智能外设
: I3C/I²C总线精确数字温度传感器,精度为±0.5 °C
: ±2g/±4g/±8g/±16g、12位低功耗数字加速度传感器
: ±2g/±4g/±8g/±16g、12位低功耗数字加速度传感器






MCXA15x Arm Cortex-M33 内核®®
高达 128KB 的闪存,高达 32 kB 的 RAM,8kB ECC, LPLUART、LPSPI、LPI2C、FS USB、DMA 和 LDO
FS USB 端口,带 USB Type-C 连接器,用于设备功能
HS USB Type-C 连接器(板载 MCU-Link 调试器)
SPI/I²C/UART 连接器(Arduino、PMOD/mikroBUS、DNP)
Wi-Fi 连接器(Arduino、PMOD/mikroBUS、DNP)
带有 CMSIS-DAP 的板载 MCU-Link 调试器
JTAG/SWD 连接器
I3C/I²C 温度传感器
Arduino 接头®
FRDM 报头
Pmod (英语)™*DNP
米克罗巴士™
RGB 用户 LED,以及重置、ISP、唤醒按钮




























开发板展示




FRDM-MCXA156 开发板 LED 闪烁程序,以验证设备是否按预期工作。
将 Type-C USB 数据线连接开发板和主机(电源),以启动电路板并运行演示程序。此时,RGB LED 以稳定的节奏闪烁。




开发板示例工程详见官方 GitHub 仓库 .
SDK 构建通过 快速构建 SDK


下载并安装 开发环境;


打开示例工程,软件会自动安装相应设备的 pack 包;
或在 Keil 官网 下载后手动安装。
安装


根据首页提示安装开发板 SDK 文件, 选择 Download and Install SDKs


MCUXpresso IDE 是基于 Eclipse 的开发环境,适用于基于Arm® Cortex®-M内核的恩智浦® MCU,包括通用、跨界和无线MCU。
MCUXpresso IDE 提供高级编辑、编译和调试功能,增加了MCU专用的调试视图、代码跟踪和分析、多核调试和集成配置工具。
MCUXpresso IDE调试连接采用来自恩智浦、P&E Micro® 和SEGGER® 优化的开源和商用硬件调试器,支持Freedom、塔式® 系统、LPCXpresso、基于i.MX RT的EVK,以及定制开发板。
打开目标工程, Rebuild 工程,点击魔术棒 - Debug - 选择 CMSIS-DAP 调试 - Setting - 读取到设备信息


点击 Download 按钮即可上传工程。
MCUXpresso 设置点击 Import SDK examples - Go straight to the Wizard... - 勾选目标 Demo 工程,即可打开示例工程;
工程文件夹右键 - 构建工程,


工程文件夹右键 - 调试方式 - 调试配置 - 双击第一个选项 C/C++ (NXP Semiconductors) MCU Application ,点击 Debug 即可


上传工程至开发板,Reset 运行程序。
代码#include "board.h"
#include "app.h"
void SysTick_Handler(void)
{
/* Toggle pin connected to LED */
GPIO_PortToggle(BOARD_LED_GPIO, 1u << BOARD_LED_GPIO_PIN);
}
int main(void)
{
/* Board pin init */
BOARD_InitHardware();
while (1)
{
}
}效果

上传工程至开发板,配置串口参数并连接串口通信助手软件,Reset 运行程序。
代码#include "fsl_device_registers.h"
#include "fsl_debug_console.h"
#include "board.h"
#include "app.h"
int main(void)
{
char ch;
/* Init board hardware. */
BOARD_InitHardware();
PRINTF("hello world.\r\n");
while (1)
{
ch = GETCHAR();
PUTCHAR(ch);
}
}串口配置波特率 115200
数据位 8
校验位 None
停止位1
流控制 None


上传工程至开发板,配置串口参数并连接串口通信助手软件,Reset 运行程序。
运行工程时,调试控制台显示命令MCU进入目标电源模式的菜单。
短按复位按钮可从深度掉电模式唤醒,并串口打印【Normal Boot】。
代码#include "fsl_cmc.h"
#include "fsl_spc.h"
#include "fsl_clock.h"
#include "fsl_debug_console.h"
#include "power_mode_switch.h"
#include "app.h"
#include "board.h"
#include "fsl_lpuart.h"
#include "fsl_waketimer.h"
#include "fsl_wuu.h"
#include "fsl_gpio.h"
static void APP_SetSPCConfiguration(void);
static void APP_SetVBATConfiguration(void);
static void APP_SetCMCConfiguration(void);
static void APP_InitWaketimer(void);
static app_wakeup_source_t APP_SelectWakeupSource(void);
static uint8_t APP_GetWakeupTimeout(void);
static void APP_GetWakeupConfig(app_power_mode_t targetMode);
static void APP_PowerPreSwitchHook(void);
static void APP_PowerPostSwitchHook(void);
static void APP_EnterSleepMode(void);
static void APP_EnterDeepSleepMode(void);
static void APP_EnterPowerDownMode(void);
static void APP_EnterDeepPowerDownMode(void);
static void APP_PowerModeSwitch(app_power_mode_t targetPowerMode);
static app_power_mode_t APP_GetTargetPowerMode(void);
/*******************************************************************************
* Variables
******************************************************************************/
char *const g_modeNameArray[] = APP_POWER_MODE_NAME;
char *const g_modeDescArray[] = APP_POWER_MODE_DESC;
/*******************************************************************************
* Code
******************************************************************************/
int main(void)
{
uint32_t freq;
app_power_mode_t targetPowerMode;
bool needSetWakeup = false;
BOARD_InitHardware();
APP_SetVBATConfiguration();
APP_SetSPCConfiguration();
APP_InitWaketimer();
#if !(defined(APP_NOT_SUPPORT_WAKEUP_BUTTON) && APP_NOT_SUPPORT_WAKEUP_BUTTON)
EnableIRQ(APP_WUU_IRQN);
#endif /* APP_NOT_SUPPORT_WAKEUP_BUTTON */
EnableIRQ(APP_WAKETIMER_IRQN);
PRINTF("\r\nNormal Boot.\r\n");
while (1)
{
if ((SPC_GetRequestedLowPowerMode(APP_SPC) & (kSPC_PowerDownWithSysClockOff | kSPC_DeepPowerDownWithSysClockOff)) != 0UL)
{
SPC_ClearPeriphIOIsolationFlag(APP_SPC);
}
/* Clear CORE domain's low power request flag. */
SPC_ClearPowerDomainLowPowerRequestFlag(APP_SPC, APP_SPC_MAIN_POWER_DOMAIN);
SPC_ClearLowPowerRequest(APP_SPC);
/* Normal start. */
APP_SetCMCConfiguration();
freq = CLOCK_GetFreq(kCLOCK_CoreSysClk);
PRINTF("\r\n########################### Power Mode Switch Demo ###########################\r\n");
PRINTF(" Core Clock = %dHz \r\n", freq);
PRINTF(" Power mode: Active\r\n");
targetPowerMode = APP_GetTargetPowerMode();
if ((targetPowerMode > kAPP_PowerModeMin) && (targetPowerMode < kAPP_PowerModeMax))
{
/* If target mode is Active mode, don't need to set wakeup source. */
if (targetPowerMode == kAPP_PowerModeActive)
{
needSetWakeup = false;
}
else
{
needSetWakeup = true;
}
}
/* Print description of selected power mode. */
PRINTF("\r\n");
if (needSetWakeup)
{
APP_GetWakeupConfig(targetPowerMode);
APP_PowerPreSwitchHook();
APP_PowerModeSwitch(targetPowerMode);
APP_PowerPostSwitchHook();
}
PRINTF("\r\nNext loop.\r\n");
}
}
static void APP_InitWaketimer(void)
{
waketimer_config_t waketimer_config;
WAKETIMER_GetDefaultConfig(&waketimer_config);
WAKETIMER_Init(WAKETIMER0, &waketimer_config);
}
static void APP_SetSPCConfiguration(void)
{
status_t status;
spc_active_mode_regulators_config_t activeModeRegulatorOption;
SPC_EnableSRAMLdo(APP_SPC, true);
/* Disable analog modules that controlled by SPC in active mode. */
SPC_DisableActiveModeAnalogModules(APP_SPC, (kSPC_controlUsb3vDet | kSPC_controlCmp0 | kSPC_controlCmp1 | kSPC_controlCmp0Dac | kSPC_controlCmp1Dac));
/* Disable LVDs and HVDs in active mode first. */
SPC_EnableActiveModeCoreLowVoltageDetect(APP_SPC, false);
SPC_EnableActiveModeSystemHighVoltageDetect(APP_SPC, false);
SPC_EnableActiveModeSystemLowVoltageDetect(APP_SPC, false);
while (SPC_GetBusyStatusFlag(APP_SPC))
;
activeModeRegulatorOption.bandgapMode = kSPC_BandgapEnabledBufferDisabled;
/* DCDC output voltage mid voltage in active mode. */
activeModeRegulatorOption.CoreLDOOption.CoreLDOVoltage = APP_ACTIVE_CFG_LDO_VOLTAGE_LEVEL;
activeModeRegulatorOption.CoreLDOOption.CoreLDODriveStrength = kSPC_CoreLDO_NormalDriveStrength;
status = SPC_SetActiveModeRegulatorsConfig(APP_SPC, &activeModeRegulatorOption);
#if !(defined(FSL_FEATURE_MCX_SPC_HAS_NO_GLITCH_DETECT) && FSL_FEATURE_MCX_SPC_HAS_NO_GLITCH_DETECT)
/* Disable Vdd Core Glitch detector in active mode. */
SPC_DisableActiveModeVddCoreGlitchDetect(APP_SPC, true);
#endif
if (status != kStatus_Success)
{
PRINTF("Fail to set regulators in Active mode.");
return;
}
while (SPC_GetBusyStatusFlag(APP_SPC))
;
/* Enable LVDs and HVDs in active mode. */
SPC_EnableActiveModeCoreLowVoltageDetect(APP_SPC, true);
SPC_EnableActiveModeSystemHighVoltageDetect(APP_SPC, true);
SPC_EnableActiveModeSystemLowVoltageDetect(APP_SPC, true);
/* Disable analog modules that controlled by SPC in low power mode. */
SPC_DisableLowPowerModeAnalogModules(APP_SPC, (kSPC_controlUsb3vDet | kSPC_controlCmp0 | kSPC_controlCmp1 | kSPC_controlCmp0Dac | kSPC_controlCmp1Dac));
/* Disable LVDs and HVDs in low power mode to save power. */
SPC_EnableLowPowerModeCoreLowVoltageDetect(APP_SPC, false);
SPC_EnableLowPowerModeSystemHighVoltageDetect(APP_SPC, false);
SPC_EnableLowPowerModeSystemLowVoltageDetect(APP_SPC, false);
spc_lowpower_mode_regulators_config_t lowPowerRegulatorOption;
lowPowerRegulatorOption.lpIREF = false;
lowPowerRegulatorOption.bandgapMode = kSPC_BandgapDisabled;
lowPowerRegulatorOption.CoreLDOOption.CoreLDOVoltage = kSPC_CoreLDO_MidDriveVoltage;
lowPowerRegulatorOption.CoreLDOOption.CoreLDODriveStrength = kSPC_CoreLDO_LowDriveStrength;
status = SPC_SetLowPowerModeRegulatorsConfig(APP_SPC, &lowPowerRegulatorOption);
#if !(defined(FSL_FEATURE_MCX_SPC_HAS_NO_GLITCH_DETECT) && FSL_FEATURE_MCX_SPC_HAS_NO_GLITCH_DETECT)
/* Disable Vdd Core Glitch detector in low power mode. */
SPC_DisableLowPowerModeVddCoreGlitchDetect(APP_SPC, true);
#endif
if (status != kStatus_Success)
{
PRINTF("Fail to set regulators in Low Power Mode.");
return;
}
while (SPC_GetBusyStatusFlag(APP_SPC))
;
SPC_SetLowPowerWakeUpDelay(APP_SPC, APP_LDO_LPWKUP_DELAY);
}
static void APP_SetVBATConfiguration(void)
{
/* Provide clock for the wake timer which is located in the system domain. */
CLOCK_SetupFRO16KClocking(kCLKE_16K_SYSTEM);
}
static void APP_SetCMCConfiguration(void)
{
/* Disable low power debug. */
CMC_EnableDebugOperation(APP_CMC, false);
/* Allow all power mode */
CMC_SetPowerModeProtection(APP_CMC, kCMC_AllowAllLowPowerModes);
/* Disable flash memory accesses and place flash memory in low-power state whenever the core clock
is gated. And an attempt to access the flash memory will cause the flash memory to exit low-power
state for the duration of the flash memory access. */
CMC_ConfigFlashMode(APP_CMC, true, true, false);
}
static app_power_mode_t APP_GetTargetPowerMode(void)
{
uint8_t ch;
app_power_mode_t inputPowerMode;
do
{
PRINTF("\r\nSelect the desired operation \n\r\n");
for (app_power_mode_t modeIndex = kAPP_PowerModeActive; modeIndex <= kAPP_PowerModeDeepPowerDown; modeIndex++)
{
PRINTF("\tPress %c to enter: %s mode\r\n", modeIndex,
g_modeNameArray[(uint8_t)(modeIndex - kAPP_PowerModeActive)]);
}
PRINTF("\r\nWaiting for power mode select...\r\n\r\n");
ch = GETCHAR();
if ((ch >= 'a') && (ch <= 'z'))
{
ch -= 'a' - 'A';
}
inputPowerMode = (app_power_mode_t)ch;
if ((inputPowerMode > kAPP_PowerModeDeepPowerDown) || (inputPowerMode < kAPP_PowerModeActive))
{
PRINTF("Wrong Input!");
}
} while (inputPowerMode > kAPP_PowerModeDeepPowerDown);
PRINTF("\t%s\r\n", g_modeDescArray[(uint8_t)(inputPowerMode - kAPP_PowerModeActive)]);
return inputPowerMode;
}
static app_wakeup_source_t APP_SelectWakeupSource(void)
{
char ch;
PRINTF("Please select wakeup source:\r\n");
PRINTF("\tPress %c to select TIMER as wakeup source;\r\n", kAPP_WakeupSourceWakeupTimer);
#if !(defined(APP_NOT_SUPPORT_WAKEUP_BUTTON) && APP_NOT_SUPPORT_WAKEUP_BUTTON)
PRINTF("\tPress %c to select WAKE-UP-BUTTON as wakeup source;\r\n", kAPP_WakeupSourceButton);
#endif /* APP_NOT_SUPPORT_WAKEUP_BUTTON */
PRINTF("Waiting for wakeup source select...\r\n");
ch = GETCHAR();
if ((ch >= 'a') && (ch <= 'z'))
{
ch -= 'a' - 'A';
}
return (app_wakeup_source_t)ch;
}
/* Get wakeup timeout and wakeup source. */
static void APP_GetWakeupConfig(app_power_mode_t targetMode)
{
app_wakeup_source_t wakeupSource;
uint8_t timeOutValue;
char *isoDomains = NULL;
wakeupSource = APP_SelectWakeupSource();
switch (wakeupSource)
{
case kAPP_WakeupSourceWakeupTimer:
{
PRINTF("Wakeup Timer Selected As Wakeup Source!\r\n");
timeOutValue = APP_GetWakeupTimeout();
PRINTF("Will wakeup in %d seconds.\r\n", timeOutValue);
/* In case of target mode is powerdown/deep power down mode. */
WUU_SetInternalWakeUpModulesConfig(APP_WUU, APP_WUU_WAKEUP_TIMER_IDX, kWUU_InternalModuleInterrupt);
WAKETIMER_StartTimer(WAKETIMER0, timeOutValue * 1000);
if (targetMode > kAPP_PowerModeSleep)
{
/* Isolate some power domains that are not used in low power modes, note that in order to save
* more power, it is better to not power the isolated domains.*/
SPC_SetExternalVoltageDomainsConfig(APP_SPC, APP_SPC_WAKEUP_TIMER_LPISO_VALUE, APP_SPC_WAKEUP_TIMER_ISO_VALUE);
isoDomains = APP_SPC_WAKEUP_TIMER_ISO_DOMAINS;
PRINTF("Isolate power domains: %s\r\n", isoDomains);
}
break;
}
#if !(defined(APP_NOT_SUPPORT_WAKEUP_BUTTON) && APP_NOT_SUPPORT_WAKEUP_BUTTON)
case kAPP_WakeupSourceButton:
{
PRINTF("Wakeup Button Selected As Wakeup Source.\r\n");
/* Set WUU to detect on rising edge for all power modes. */
wuu_external_wakeup_pin_config_t wakeupButtonConfig;
wakeupButtonConfig.edge = kWUU_ExternalPinFallingEdge;
wakeupButtonConfig.event = kWUU_ExternalPinInterrupt;
wakeupButtonConfig.mode = kWUU_ExternalPinActiveAlways;
WUU_SetExternalWakeUpPinsConfig(APP_WUU, APP_WUU_WAKEUP_BUTTON_IDX, &wakeupButtonConfig);
PRINTF("Please press %s to wakeup.\r\n", APP_WUU_WAKEUP_BUTTON_NAME);
if (targetMode > kAPP_PowerModeSleep)
{
/* Isolate some power domains that are not used in low power modes, note that in order to save
* more power, it is better to not power the isolated domains.*/
SPC_SetExternalVoltageDomainsConfig(APP_SPC, APP_SPC_WAKEUP_BUTTON_LPISO_VALUE, APP_SPC_WAKEUP_BUTTON_ISO_VALUE);
isoDomains = APP_SPC_WAKEUP_BUTTON_ISO_DOMAINS;
PRINTF("Isolate power domains: %s\r\n", isoDomains);
}
break;
}
#endif /* APP_NOT_SUPPORT_WAKEUP_BUTTON */
default:
assert(false);
break;
}
}
/*!
* Get input from user about wakeup timeout
*/
static uint8_t APP_GetWakeupTimeout(void)
{
uint8_t timeout;
while (1)
{
PRINTF("Select the wake up timeout in seconds.\r\n");
PRINTF("The allowed range is 1s ~ 9s.\r\n");
PRINTF("Eg. enter 5 to wake up in 5 seconds.\r\n");
PRINTF("\r\nWaiting for input timeout value...\r\n\r\n");
timeout = GETCHAR();
PRINTF("%c\r\n", timeout);
if ((timeout > '0') && (timeout <= '9'))
{
return timeout - '0';
}
PRINTF("Wrong value!\r\n");
}
}
static void APP_PowerPreSwitchHook(void)
{
/* Wait for debug console output finished. */
while (!(kLPUART_TransmissionCompleteFlag & LPUART_GetStatusFlags((LPUART_Type *)BOARD_DEBUG_UART_BASEADDR)))
{
}
APP_DeinitDebugConsole();
}
static void APP_PowerPostSwitchHook(void)
{
#if !(defined(APP_POST_INIT_CLOCK) && APP_POST_INIT_CLOCK)
BOARD_BootClockFRO48M();
#else
APP_POST_INIT_CLOCK_FUNCTION();
#endif
APP_InitDebugConsole();
}
static void APP_PowerModeSwitch(app_power_mode_t targetPowerMode)
{
if (targetPowerMode != kAPP_PowerModeActive)
{
switch (targetPowerMode)
{
case kAPP_PowerModeSleep:
APP_EnterSleepMode();
break;
case kAPP_PowerModeDeepSleep:
APP_EnterDeepSleepMode();
break;
case kAPP_PowerModePowerDown:
APP_EnterPowerDownMode();
break;
case kAPP_PowerModeDeepPowerDown:
APP_EnterDeepPowerDownMode();
break;
default:
assert(false);
break;
}
}
}
static void APP_EnterSleepMode(void)
{
cmc_power_domain_config_t config;
config.clock_mode = kCMC_GateCoreClock;
config.main_domain = kCMC_ActiveOrSleepMode;
CMC_EnterLowPowerMode(APP_CMC, &config);
}
static void APP_EnterDeepSleepMode(void)
{
cmc_power_domain_config_t config;
config.clock_mode = kCMC_GateAllSystemClocksEnterLowPowerMode;
config.main_domain = kCMC_DeepSleepMode;
CMC_EnterLowPowerMode(APP_CMC, &config);
}
static void APP_EnterPowerDownMode(void)
{
cmc_power_domain_config_t config;
config.clock_mode = kCMC_GateAllSystemClocksEnterLowPowerMode;
config.main_domain = kCMC_PowerDownMode;
CMC_EnterLowPowerMode(APP_CMC, &config);
}
static void APP_EnterDeepPowerDownMode(void)
{
cmc_power_domain_config_t config;
config.clock_mode = kCMC_GateAllSystemClocksEnterLowPowerMode;
config.main_domain = kCMC_DeepPowerDown;
CMC_EnterLowPowerMode(APP_CMC, &config);
}效果

我要赚赏金
