Funpack5-1 - 用FRDM-MCXA346开发板实现串口命令控制板载RGB LED
该项目使用了FRDM-MCXA346开发板,实现了通过串口控制板载RGB LED的设计,它的主要功能为:实现了一个简单的shell解析器,实现解析串口输入命令并控制板载的RGB LED。
标签
嵌入式系统
Funpack活动
开发板
NXP
红衣踏雪入梦来
更新2026-03-16
盐城工学院
7

一、项目介绍

本项目是基于NXP FRDM-MCXA346开发板实现的RGB LED亮度控制系统。该系统通过嵌入式的letter-shell(一个轻量级的命令行交互框架)提供了一个友好的串口命令行界面,用户可以通过简单的串口命令实时控制RGB LED的各个通道的亮度,从0%到100%任意调节。项目的核心设计目标是:

  1. 灵活的亮度控制:支持对红(R)、绿(G)、蓝(B)三个通道分别或同时调节亮度
  2. 用户友好的交互方式:通过串口命令行进行实时交互,无需额外硬件
  3. 可靠的硬件驱动:利用微控制器内部的CTMER模块生成精确的PWM波形
  4. 完整的功能验证:支持查询当前LED状态和硬件参数

整个项目包括了硬件初始化、定时器配置、PWM生成、shell命令处理等完整功能实现。

二、硬件介绍

FRDM-MCXA346开发板采用了来自NXP的型号为MCXA346的MCU,基于ARM Cortex-M33内核,最高主频可以达到180MHz, 同时拥有高达1MB的flash和256K的SRAM。同时拥有专用的电机控制模块(FlexPWM, eQDC, AOI)和可编程增益运放和低功耗比较器,为无刷电机的控制提供了非常完善的解决方案。同时该开发板还板载了MCU-Link-lite,可以刷写对应的Jlink-ob固件来使用jlink commander和ozone进行调试。兼容Arduino、PMOD和mikroBUS接口,很容易找到相关的扩展板。

硬件连接

本项目使用的RGB LED配置:

  • 红色LED(R): 使用Port3的第18管脚(P3_18),通过CTIMER2的Match0驱动
  • 绿色LED(G): 使用Port3的第19管脚(P3_19),通过CTIMER2的Match1驱动
  • 蓝色LED (B): 使用Port3的第21管脚(P3_21),通过CTIMER2的Match13驱动
  • 上拉电阻: 每个LED通道都外接了上拉电阻,形成低电平有效的驱动方式: 由于LED阳极接上拉电阻到电源,GPIO输出低电平时LED才点亮。因此软件在设置亮度时需要进行逻辑取反,即设置100%亮度时实际的PWM占空比应为0%(低电平)。

三、设计思路和工作流程

3.1 分层设计架构

底层硬件驱动层 (rgb_led.c/h):

  • 系统初始化(硬件、定时器、shell)
  • 直接操作CTIMER2和GPIO硬件
  • 提供标准化的亮度设置接口
  • 在该层进行PWM占空比的逻辑反演

中间shell命令层 (rgb_led_shell.c):

  • 实现shell命令的解析和参数提取
  • 将用户输入的亮度值(0-100)转换为硬件驱动函数调用
  • 提供友好的命令帮助和返回反馈

上层应用层 (hello_world.c):

  • 主循环运行shell的任务处理
  • 集成所有组件

3.2核心工作流程:

用户通过串口输入命令
     ↓
Shell接收并解析命令参数
     ↓
调用LED_SetBrightness()等函数
     ↓
进行亮度反演计算(duty = 100 - brightness)
     ↓
更新CTIMER的Match寄存器
     ↓
PWM波形产生并驱动LED
     ↓
LED亮度改变

3.3 软件工作流程

启动程序
   ↓
BOARD_InitHardware() - 初始化板级硬件
   ├─ 时钟配置
   ├─ GPIO初始化
   └─ UART初始化
   ↓
RGB_LED_Init() - 初始化CTIMERPWM
   ├─ 获取定时器时钟频率
   ├─ 计算PWM参数
   ├─ 配置三个PWM通道
   └─ 设置初始亮度(全暗)
   ↓
userShellInit() - 初始化shell
   ├─ 设置shell读写函数
   ├─ 注册命令表
   └─ 初始化命令缓冲区
   ↓
进入主循环
   ├─ shellTask(&shell) - 处理shell任务
   │  ├─ 从UART读取一个字符
   │  ├─ shellHandler() - 处理输入
   │  │  ├─ 检查是否为特殊键(方向键/Backspace)
   │  │  │  └─ 调用对应的按键处理函数
   │  │  └─ 否则进行普通字符处理(insertByte)
   │  ├─ 如果是回车则解析并执行命令
   │  │  ├─ 参数分割(shellSplit)
   │  │  ├─ 查找命令(shellSeekCommand)
   │  │  └─ 调用命令函数(ledCommand/ledInfoCommand)
   │  └─ 显示新提示符
   └─ (循环)

3.4 关键代码分析

RGB LED初始化部分 (rgb_led.c):

status_t RGB_LED_Init(void)
{
    ctimer_config_t config;
    uint32_t srcClock_Hz;
    /* 获取CTIMER2的时钟频率 */
    srcClock_Hz = CLOCK_GetCTimerClkFreq(2U);
    CTIMER_GetDefaultConfig(&config);
    /* 计算实际定时器时钟 */
    g_rgb_led_context.timerClock_Hz = srcClock_Hz / (config.prescale + 1);
    g_rgb_led_context.pwmPeriod = (g_rgb_led_context.timerClock_Hz / 20000U) - 1U;
    /* 初始化CTIMER */
    CTIMER_Init(CTIMER2, &config);
    /* 为三个通道设置PWM,初始亮度为100%(占空比100%)*/
    /* 设置CTIME2的kCTIMER_Match_2为PWM周期比较通道,其他通道设置为PWM匹配输出通道*/
    CTIMER_SetupPwm(CTIMER2, kCTIMER_Match_2, kCTIMER_Match_0, 100U, 20000U, timerClock, false);
    CTIMER_SetupPwm(CTIMER2, kCTIMER_Match_2, kCTIMER_Match_1, 100U, 20000U, timerClock, false);
    CTIMER_SetupPwm(CTIMER2, kCTIMER_Match_2, kCTIMER_Match_3, 100U, 20000U, timerClock, false);
    CTIMER_StartTimer(CTIMER2);
    /* 立即设置为全暗状态 */
    RGB_LED_SetBrightness(0U, 0U, 0U);
    return kStatus_Success;
}

Shell命令处理 (rgb_led_shell.c):

int ledCommand(int argc, char *argv[])
{
    uint8_t red, green, blue;
    if (argc < 2) {
        PRINTF("LED Control Command\r\n");
        PRINTF("  led set r <0-100>   - Set red brightness\r\n");
        PRINTF("  led set g <0-100>   - Set green brightness\r\n");
        PRINTF("  led set b <0-100>   - Set blue brightness\r\n");
        PRINTF("  led set <r> <g> <b> - Set RGB brightness (0-100)\r\n");
        PRINTF("  led get             - Get current brightness\r\n");
        PRINTF("  led off             - Turn off all LED\r\n");
        return 0;
    }
    if (strcmp(argv[1], "set") == 0) {
        if (argc == 4 && strlen(argv[2]) == 1) {
            /* 单通道模式: led set r/g/b <value> */
            uint8_t brightness = (uint8_t)atoi(argv[3]);
            if (brightness > 100) return -1;
            switch (argv[2][0]) {
                case 'r': RGB_LED_SetRed(brightness); break;
                case 'g': RGB_LED_SetGreen(brightness); break;
                case 'b': RGB_LED_SetBlue(brightness); break;
            }
        }
        else if (argc == 5) {
            /* 全通道模式: led set <r> <g> <b> */
            RGB_LED_SetBrightness((uint8_t)atoi(argv[2]),
                                  (uint8_t)atoi(argv[3]),
                                  (uint8_t)atoi(argv[4]));
        }
    }
    else if (strcmp(argv[1], "get") == 0) {
        RGB_LED_GetBrightness(&red, &green, &blue);
        PRINTF("Current RGB brightness: R:%d%% G:%d%% B:%d%%\r\n", red, green, blue);
    }
    return 0;
}

四、功能说明及展示

4.1 命令使用

# 输入led可查询led相关子命令
FunpackS5_1> led
LED Control Command
  led set r <0-100>   - Set red brightness
  led set g <0-100>   - Set green brightness
  led set b <0-100>   - Set blue brightness
  led set <r> <g> <b> - Set RGB brightness (0-100)
  led get             - Get current brightness
  led off             - Turn off all LED
# 设置led的红色通道亮度为100
FunpackS5_1> led set r 100
Red brightness set to 100%
# 同时设置三个led通道,Red-50%,Green-30%,Blue-80%
FunpackS5_1> led set 50 30 80
RGB brightness set to R:50% G:30% B:80%
# 获取当前led各个通道的亮度信息
FunpackS5_1> led get
Current RGB brightness: R:50% G:30% B:80%
# 关闭所有led
FunpackS5_1> led off
LED turned off
# 显示led各个通道的信息:对应的定时器输出管脚和亮度信息
FunpackS5_1> ledinfo
=== RGB LED Status ===
Timer: CTIMER2
PWM Frequency: 20 kHz
Red Channel: CT2_MAT0 (P3_18)
Green Channel: CT2_MAT1 (P3_19)
Blue Channel: CT2_MAT3 (P3_21)
Current Brightness:
  Red:   0%
  Green: 0%
  Blue:  0%

4.2功能展示

image.png

五、完成任务中遇到的问题和解决办法

  • Cmake工程的配置出错 由于NXP的SDK每次release所使用的IAR版本都是最新版本,导致在我当前工作的电脑上无法打开相关的工程示例,所以尝试改用CMake版本的SDK进行开发。但是发现即使将相关的外设驱动拷贝到driver文件夹下后,编译器还是无法找到ctimer的驱动文件,通过VS Code自带的Copilot AI进行分析,发现还需要在config.cmake中设置set(CONFIG_USE_driver_ctimer true)
  • shell处理过程中发现backspace键无法删除输入字符 通过Copilot分析后发现代码中错误的将0x7F映射到了Delete函数,修改后shell工作正常

六、心得与体会

  • 可以通过AI来分析基于CMake构建的大型工程,可以很快找到文件间的联系并对编译选项进行相关配置。
  • 通过AI来进行CMakelist的编写和代码框架的建立,通过细化功能的粒度来让AI能够更准确的生成代码。
  • 编译调试过程中可以将编译器报错提供给AI,使其进行相应的调整。
附件下载
funpackS5_1.zip
团队介绍
个人
团队成员
红衣踏雪入梦来
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号