Funpack4-3 - 用MAX32655FTHR完成LED灯效切换控制
该项目使用了MAX32655FTHR核心板,实现了板载LED灯灯效控制的设计,它的主要功能为:通过板上的按键,切换三色LED灯的运行模式。
标签
嵌入式系统
Funpack活动
开发板
红衣踏雪入梦来
更新2026-03-02
11

一、项目描述

1.1 项目介绍

本项目是基于MAX32655FTHR核心板实现的模式RGB LED控制系统。该系统实现了三种独立的LED显示模式,通过按键进行切换,能够展示不同的视觉效果。

核心功能:

  • 呼吸灯模式 (Breathing Mode):蓝色LED通过PWM调制实现平滑的亮度呼吸效果
  • 跑马灯模式 (Running Light Mode):红→绿 两个个LED轮流点亮
  • 彩虹模式 (Rainbow Mode):RGB LED组合显示渐变的彩虹颜色序列

用户交互:

  • PB0按键:在呼吸灯和跑马灯模式间切换
  • PB1按键:在当前模式和彩虹模式间切换

1.2 设计思路

该项目采用了模块化设计,将功能划分为以下几个核心模块:

  1. 主程序:主要包含系统初始化和事件处理的主循环还有按键中断回调的管理
  2. led模式切换模块:主要实现了RGB灯所用IO的初始化配置,三种闪烁模式的实现和闪烁模式的切换
  3. 呼吸灯模块:主要实现了呼吸灯所有PWM输出的初始化,占空比的配置

设计原则:

- 清晰的职责划分:主程序只处理应用逻辑,LED控制逻辑集中在库函数中

- 使用状态机模式管理三个LED模式的切换

二、硬件介绍

本次活动所选用的开发板是来自美信的MAX35655FTHR, 其主控芯片具有运行速率高达100MHz的cortex-M4F内核,同时还有一个专用于蓝牙BLE RSIC-V内核。除了内置的512K flash外,还提供了外部的Quad flash用来存放相关的程序资源。同时板载了PMIC,DAPLink调试器和音频解码器及数字麦克风,可以说是麻雀虽小五脏俱全,搭配面包板可以快速搭建一个原型验证平台。

2.1 LED的硬件连接

红色 -->P0_18(复用为GPIO)

绿色 -->P0_19(复用为GPIO)

蓝色 -->P0_26(复用为TMR2的输出用于控制呼吸灯)

2.2 按键的配置

BUTTON1 --> P0_2(GPIO输入, 用于呼吸灯和跑马灯模式的互相切换)

BUTTON2 --> P0_3(GPIO输入, 用于呼吸灯和彩虹灯模式的互相切换)

三、软件流程与代码实现

3.1 整体流程

3.2 三种工作模式的实现

呼吸灯模式:使用正弦波函数调制PWM的占空比, 实现平滑的亮度变化

void LED_Breathing_Update(void)
{
    uint32_t periodTicks;
    uint32_t pwm_value;
    float brightness;
    float progress;
    periodTicks = MXC_TMR_GetPeriod(PWM_TIMER, PWM_CLOCK_SOURCE, 16, PWM_FREQ);
    // 计算进度(0.0 - 1.0)
    progress = (float)breathing_step / BREATHING_SAMPLES;
    // 使用正弦波计算亮度曲线
    brightness = sinf(progress * 3.14159f);
    brightness = brightness * brightness;  // 非线性映射,使呼吸更自然
    // 计算PWM占空比
    pwm_value = (periodTicks * (100 - (uint32_t)(brightness * 100))) / 100;
    MXC_TMR_SetPWM(PWM_TIMER, pwm_value);
    breathing_step++;
    if (breathing_step >= BREATHING_SAMPLES) {  // 200步循环一个周期
        breathing_step = 0;
    }
}

跑马灯模式:三个LED按顺序轮流点亮,形成流动效果。

void LED_RunningLight_Update(void)
{
    /* 首先关闭所有LED */
    MXC_GPIO_OutSet(LED_GPIO_PORT, MXC_GPIO_PIN_18);  // 红色关闭
    MXC_GPIO_OutSet(LED_GPIO_PORT, MXC_GPIO_PIN_19);  // 绿色关闭
    /* 红→绿→蓝顺序点亮 */
    switch (running_light_step % 3) {
    case 0:
        MXC_GPIO_OutClr(LED_GPIO_PORT, MXC_GPIO_PIN_18);  // 点亮红色
        break;
    case 1:
        MXC_GPIO_OutClr(LED_GPIO_PORT, MXC_GPIO_PIN_19);  // 点亮绿色
        break;
    case 2:
        /* 蓝色由PWM控制,设置为100%占空比 */
        MXC_TMR_SetPWM(PWM_TIMER, 0);  // 占空比为100%
        break;
    }
    running_light_step++;
    if (running_light_step >= 3) {
        running_light_step = 0;
    }
}

彩虹灯模式:生成多种颜色的循环

void LED_Rainbow_Update(void)
{
    uint8_t red, green, blue;
    uint32_t periodTicks;
    periodTicks = MXC_TMR_GetPeriod(PWM_TIMER, PWM_CLOCK_SOURCE, 16, PWM_FREQ);
    /* HSV色彩空间转RGB */
    float hue = (float)(rainbow_step % 360) / 360.0f;  // 色调:0-360°
    float sat = 1.0f;    // 饱和度:100%
    float val = 1.0f;    // 亮度:100%
    float h = hue * 6.0f;
    float f = h - (int)h;
    float p = val * (1.0f - sat);
    float q = val * (1.0f - f * sat);
    float t = val * (1.0f - (1.0f - f) * sat);
    // HSV → RGB的分段转换
    switch ((int)h % 6) {
    case 0:
        red = 255;
        green = (uint8_t)(t * 255);
        blue = (uint8_t)(p * 255);
        break;
    case 1:
        red = (uint8_t)(q * 255);
        green = 255;
        blue = (uint8_t)(p * 255);
        break;
    // ... 其他颜色段
    }
    // 控制红、绿LED亮度(简化实现:GPIO全亮或全灭)
    if (red > 128) MXC_GPIO_OutClr(LED_GPIO_PORT, MXC_GPIO_PIN_18);
    else MXC_GPIO_OutSet(LED_GPIO_PORT, MXC_GPIO_PIN_18);
    if (green > 128) MXC_GPIO_OutClr(LED_GPIO_PORT, MXC_GPIO_PIN_19);
    else MXC_GPIO_OutSet(LED_GPIO_PORT, MXC_GPIO_PIN_19);
    // 蓝色用PWM调节
    uint32_t blue_pwm = (periodTicks * blue) / 256;
    MXC_TMR_SetPWM(PWM_TIMER, blue_pwm);
    rainbow_step++;
}

3.3 主程序流程

int main(void)
{
    int err;
    // 1. 系统和硬件初始化
    Board_Init();           // 板级初始化
    LED_RGB_Init();         // RGB GPIO配置
    LED_PWM_Init();         // PWM定时器初始化
    PB_Init_Custom();       // 按键中断注册
    SysTick_Config();       // 系统滴答定时器
    // 2. 主循环 - 事件驱动处理
    while (1) {
        if (pb0_pressed) {           // PB0按键被按下
            pb0_pressed = 0;
            led_mode_t mode = LED_Get_Mode();
            if (mode == LED_MODE_BREATHING)
                LED_Mode_RunningLight();  // 切换到跑马灯
            else if (mode == LED_MODE_RAINBOW)
                LED_Mode_RunningLight();  // 从彩虹切换到跑马灯
            else
                LED_Mode_Breathing();     // 从跑马灯切换到呼吸灯
        }
        if (pb1_pressed) {           // PB1按键被按下
            pb1_pressed = 0;
            led_mode_t mode = LED_Get_Mode();
            if (mode == LED_MODE_BREATHING)
                LED_Mode_Rainbow();       // 从呼吸灯切换到彩虹
            else if (mode == LED_MODE_RUNNING_LIGHT)
                LED_Mode_Rainbow();       // 从跑马灯切换到彩虹
            else
                LED_Mode_Breathing();     // 从彩虹切换到呼吸灯
        }
        LED_Update_Handler();        // 根据当前模式更新LED
    }
}

四、作品功能展示:

具体功能实现及效果可见视频, 下方图片仅作演示:

1. 彩虹灯模式

2. 呼吸灯模式

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

5.1 makefile的工程配置问题

由于以前接触过的NXP和STM的芯片都会提供IAR或Keil的相关工程,但是美信的SDK只有很久之前的版本才提供了Keil的pack,最新版本只提供了makefile+eclipse方式,由于之前只使用过简单的makefile文件,不熟悉大工程构建过程中使用的各种makefile技巧。所以通过VS Code自带的AI助手来对SDK示例工程中的makefile进行分析,逐步了解了工程的组织结构以及实现的方法。

5.2 GPIO与PWM并行控制

红/绿LED使用GPIO直接控制(0/1电平),蓝色LED使用PWM占空比控制,三者需要在不同模式下协调动作。通过设置蓝色LED输出时的占空比为100%,实现了三色LED的切换。

5.3 板级支持的实现

在MaxSDK的示例工程中,提供了板级外设的配置,但是该板级配置是在SDK内部,修改该文件可能会导致SDK中其他实例工程无法运行。想要实现自己的板级外设的支持,需要自己构建board.c和board.h文件,并配置makefile不使用SDK中的board文件。

六、心得与体会

6.1 makefile构建系统的深入理解

  • 理解了makefile构建系统的运行行为
  • 掌握了参数化Makefile的配置方法

6.2 AI编程的使用和与AI联动进行调试

  • 通过AI来进行makefile的编写和代码框架的建立,通过细化功能的粒度来让AI能够更准确的生成代码。
  • 编译调试过程中可以将编译器报错提供给AI,使其进行相应的调整。


附件下载
funpack-s4-3.7z
团队介绍
个人
团队成员
红衣踏雪入梦来
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号