基于FTHR-G0001开发板的5LED多模式流水灯系统设计与实现

分享作者:XIUYUAN
作者昵称:XIUYUAN
评测品牌:灵动微电子
评测型号:FTHR-G0001
发布时间:2025-10-13 11:41:58
2
视频链接
【FTHR-G0001开发板实现花样5色灯(2倍速版)-哔哩哔哩】 https://b23.tv/SwyiHee
概要
FTHR-G0001是一款基于MM32G0001微控制器的高性能开发板,凭借其低功耗、高集成度的特点,在物联网和嵌入式应用中备受青睐。本文将详细介绍如何在KEIL开发环境中实现5个外部LED的多模式控制系统,包括流水灯、跑马灯、呼吸灯等7种动态显示效果。这不仅是GPIO编程的进阶应用,更是智能LED控制系统的核心技术基础,为复杂的LED矩阵控制和智能照明应用奠定重要基础。
开源口碑分享内容

引言

       FTHR-G0001是一款基于MM32G0001微控制器的高性能开发板,凭借其低功耗、高集成度的特点,在物联网和嵌入式应用中备受青睐。本文将详细介绍如何在KEIL开发环境中实现5个外部LED的多模式控制系统,包括流水灯、跑马灯、呼吸灯等7种动态显示效果。这不仅是GPIO编程的进阶应用,更是智能LED控制系统的核心技术基础,为复杂的LED矩阵控制和智能照明应用奠定重要基础。

  • FTHR-G0001开发板外观图


硬件平台介绍

MM32G0001微控制器特性

       处理器内核:ARM Cortex-M0+

       工作频率:最高48MHz  

       存储容量:32KB Flash + 4KB SRAM

       GPIO接口:多达32个可编程I/O引脚

       封装形式:LQFP48/QFN32等多种封装选择

       工作电压:2.0V-5.5V宽电压范围

       特色功能:支持低功耗模式、多种通信接口


FTHR-G0001开发板布局

开发板集成了电源管理、调试接口、用户LED、按键等外设,为快速原型开发提供了完整的解决方案。本项目将使用PA5-PA9引脚连接5个外部LED,实现丰富的显示效果。


硬件连接方案

引脚连接表:

MCU引脚    功能     LED编号    连接方式

PA5   →   GPIO  →   LED1   →  330Ω电阻 → 3mm红色LED → GND
PA6   →   GPIO  →   LED2   →  330Ω电阻 → 3mm黄色LED → GND  
PA7   →   GPIO  →   LED3   →  330Ω电阻 → 3mm绿色LED → GND
PA8   →   GPIO  →   LED4   →  330Ω电阻 → 3mm蓝色LED → GND
PA9   →   GPIO  →   LED5   →  330Ω电阻 → 3mm白色LED → GND

开发环境搭建

KEIL MDK配置

       1. 安装KEIL MDK-ARM:推荐使用5.25及以上版本

       2. 添加器件支持包:安装MindMotion MM32G0001 DFP

       3. 调试器配置:支持ST-Link、J-Link等多种调试器

           4. 编译器设置:配置为C89/C90标准以确保最佳兼容性

  • KEIL环境配置截图

具体详细的环境配置请参考开源社区:https://www.iceasy.com/review/list?keyword=FTHR-G0001


项目工程分析

工程文件结构

基于标准的分层架构设计,工程结构如下:

GPIO_LED_MultiPattern/
├── APP/
│   ├── main.c                    // 主程序文件
│   ├── gpio_led_toggle.c         // 多模式LED控制逻辑
│   ├── gpio_led_toggle.h         // LED控制头文件
│   └── platform.c                // 平台相关函数
├── STARTUP/
│   ├── system_mm32g0001.c        // 系统初始化
│   └── startup_mm32g0001_keil.s  // 启动文件  
└── HAL_LIB/                      // 硬件抽象层库
    ├── inc/                      // 头文件目录
    └── src/                      // 源文件目录
```
  • KEIL工程目录树截图


核心代码实现

/***********************************************************************************************************************
    @file    gpio_led_toggle.c
    @author  XIU YUAN
    @date    11-Oct-2025
    @brief   THIS FILE PROVIDES ALL THE SYSTEM FUNCTIONS.
  **********************************************************************************************************************
    @attention

    <h2><center>© Copyright(c) <2023> <MindMotion></center></h2>

      Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
    following conditions are met:
    1. Redistributions of source code must retain the above copyright notice,
       this list of conditions and the following disclaimer.
    2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
       the following disclaimer in the documentation and/or other materials provided with the distribution.
    3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or
       promote products derived from this software without specific prior written permission.

      THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *********************************************************************************************************************/

/* Define to prevent recursive inclusion */
#define _GPIO_LED_TOGGLE_C_

/* Files include */
#include <stdio.h>
#include "platform.h"
#include "gpio_led_toggle.h"

/**
  * @addtogroup MM32G0001_LibSamples
  * @{
  */

/**
  * @addtogroup GPIO
  * @{
  */

/**
  * @addtogroup GPIO_LED_Toggle
  * @{
  */

/* Private typedef ****************************************************************************************************/

/* Private define *****************************************************************************************************/
#define LED_COUNT 5

/* Private macro ******************************************************************************************************/

/* Private variables **************************************************************************************************/
uint16_t LED_PINS[LED_COUNT] = {GPIO_Pin_5, GPIO_Pin_6, GPIO_Pin_7, GPIO_Pin_8, GPIO_Pin_9};

/* Private functions **************************************************************************************************/

/***********************************************************************************************************************
  * @brief  配置5个LED的GPIO引脚 (A5, A6, A7, A8, A9)
  * @note   none
  * @param  none
  * @retval none
  *********************************************************************************************************************/
void GPIO_Configure(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;

    RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOA, ENABLE);

    GPIO_StructInit(&GPIO_InitStruct);
    GPIO_InitStruct.GPIO_Pin   = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_High;
    GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* 初始化时关闭所有LED */
    GPIO_ResetBits(GPIOA, GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9);
}

/***********************************************************************************************************************
  * @brief  控制单个LED的开关
  * @note   none
  * @param  led_index: LED索引 (0-4)
  * @param  state: Bit_SET点亮, Bit_RESET熄灭
  * @retval none
  *********************************************************************************************************************/
void LED_Control(uint8_t led_index, BitAction state)
{
    if (led_index < LED_COUNT)
    {
        GPIO_WriteBit(GPIOA, LED_PINS[led_index], state);
    }
}

/***********************************************************************************************************************
  * @brief  关闭所有LED
  * @note   none
  * @param  none
  * @retval none
  *********************************************************************************************************************/
void LED_All_Off(void)
{
    uint8_t i;
    
    for (i = 0; i < LED_COUNT; i++)
    {
        LED_Control(i, Bit_RESET);
    }
}

/***********************************************************************************************************************
  * @brief  点亮所有LED
  * @note   none
  * @param  none
  * @retval none
  *********************************************************************************************************************/
void LED_All_On(void)
{
    uint8_t i;
    
    for (i = 0; i < LED_COUNT; i++)
    {
        LED_Control(i, Bit_SET);
    }
}

/***********************************************************************************************************************
  * @brief  流水灯效果 - 从左到右
  * @note   none
  * @param  delay_ms: 延时时间(毫秒)
  * @retval none
  *********************************************************************************************************************/
void LED_Flow_LeftToRight(uint16_t delay_ms)
{
    uint8_t i;
    
    for (i = 0; i < LED_COUNT; i++)
    {
        LED_All_Off();
        LED_Control(i, Bit_SET);
        PLATFORM_DelayMS(delay_ms);
    }
}

/***********************************************************************************************************************
  * @brief  流水灯效果 - 从右到左
  * @note   none
  * @param  delay_ms: 延时时间(毫秒)
  * @retval none
  *********************************************************************************************************************/
void LED_Flow_RightToLeft(uint16_t delay_ms)
{
    int8_t i;
    
    for (i = LED_COUNT - 1; i >= 0; i--)
    {
        LED_All_Off();
        LED_Control(i, Bit_SET);
        PLATFORM_DelayMS(delay_ms);
    }
}

/***********************************************************************************************************************
  * @brief  跑马灯效果 - 往返
  * @note   none
  * @param  delay_ms: 延时时间(毫秒)
  * @retval none
  *********************************************************************************************************************/
void LED_Running_Horse(uint16_t delay_ms)
{
    /* 从左到右 */
    LED_Flow_LeftToRight(delay_ms);
    /* 从右到左 */
    LED_Flow_RightToLeft(delay_ms);
}

/***********************************************************************************************************************
  * @brief  呼吸灯效果 - 所有LED同时闪烁
  * @note   none
  * @param  delay_ms: 延时时间(毫秒)
  * @retval none
  *********************************************************************************************************************/
void LED_Breathing(uint16_t delay_ms)
{
    LED_All_On();
    PLATFORM_DelayMS(delay_ms);
    LED_All_Off();
    PLATFORM_DelayMS(delay_ms);
}

/***********************************************************************************************************************
  * @brief  交替闪烁效果
  * @note   none
  * @param  delay_ms: 延时时间(毫秒)
  * @retval none
  *********************************************************************************************************************/
void LED_Alternating_Blink(uint16_t delay_ms)
{
    uint8_t i;
    
    /* 奇数LED亮,偶数LED灭 */
    for (i = 0; i < LED_COUNT; i++)
    {
        LED_Control(i, (i % 2 == 0) ? Bit_SET : Bit_RESET);
    }
    PLATFORM_DelayMS(delay_ms);
    
    /* 偶数LED亮,奇数LED灭 */
    for (i = 0; i < LED_COUNT; i++)
    {
        LED_Control(i, (i % 2 == 1) ? Bit_SET : Bit_RESET);
    }
    PLATFORM_DelayMS(delay_ms);
}

/***********************************************************************************************************************
  * @brief  中心扩散效果
  * @note   none
  * @param  delay_ms: 延时时间(毫秒)
  * @retval none
  *********************************************************************************************************************/
void LED_Center_Expand(uint16_t delay_ms)
{
    uint8_t center;
    uint8_t i;
    
    center = LED_COUNT / 2;
    
    LED_All_Off();
    LED_Control(center, Bit_SET);  /* 点亮中心LED */
    PLATFORM_DelayMS(delay_ms);
    
    for (i = 1; i <= center; i++)
    {
        if (center >= i)
            LED_Control(center - i, Bit_SET);
        if (center + i < LED_COUNT)
            LED_Control(center + i, Bit_SET);
        PLATFORM_DelayMS(delay_ms);
    }
    
    PLATFORM_DelayMS(delay_ms * 2);
}

/***********************************************************************************************************************
  * @brief  随机闪烁效果
  * @note   none
  * @param  delay_ms: 延时时间(毫秒)
  * @retval none
  *********************************************************************************************************************/
void LED_Random_Blink(uint16_t delay_ms)
{
    static uint32_t seed = 1;
    uint8_t random_led;
    
    LED_All_Off();
    
    /* 简单的随机数生成 */
    seed = seed * 1103515245 + 12345;
    random_led = (seed / 65536) % LED_COUNT;
    
    LED_Control(random_led, Bit_SET);
    PLATFORM_DelayMS(delay_ms);
}

/***********************************************************************************************************************
  * @brief  流水灯和花样灯主程序
  * @note   none
  * @param  none
  * @retval none
  *********************************************************************************************************************/
void GPIO_LED_Toggle_Sample(void)
{
    uint8_t pattern = 0;
    uint16_t pattern_count = 0;
    
    printf("\r\nTest %s - 5 LED Pattern Control", __FUNCTION__);

    GPIO_Configure();
    
    while (1)
    {
        switch (pattern)
        {
            case 0:  /* 流水灯 - 左到右 */
                LED_Flow_LeftToRight(150);
                break;
                
            case 1:  /* 流水灯 - 右到左 */
                LED_Flow_RightToLeft(150);
                break;
                
            case 2:  /* 跑马灯效果 */
                LED_Running_Horse(100);
                break;
                
            case 3:  /* 呼吸灯效果 */
                LED_Breathing(300);
                break;
                
            case 4:  /* 交替闪烁 */
                LED_Alternating_Blink(200);
                break;
                
            case 5:  /* 中心扩散 */
                LED_Center_Expand(200);
                break;
                
            case 6:  /* 随机闪烁 */
                LED_Random_Blink(100);
                break;
                
            default:
                pattern = 0;
                break;
        }
        
        pattern_count++;
        
        /* 每个模式运行一段时间后切换到下一个模式 */
        if (pattern_count > 20)  /* 调整这个值来控制每个模式的持续时间 */
        {
            pattern_count = 0;
            pattern++;
            if (pattern > 6)
            {
                pattern = 0;
            }
            
            /* 模式切换时短暂停顿 */
            LED_All_Off();
            PLATFORM_DelayMS(500);
        }
    }
}

/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */

/********************************************** (C) Copyright MindMotion **********************************************/

关键技术要点

1. GPIO工作模式深度解析

MM32G0001的GPIO支持多种工作模式,本项目采用推挽输出模式的原因:

       推挽输出:能够提供足够的驱动电流(最大20mA)

       高速响应:GPIO_Speed_High配置确保快速切换

       低功耗:相比开漏输出,推挽模式功耗更低

2. C89/C90标准兼容性处理

为确保代码在不同编译器版本中的兼容性,严格遵循C89标准:

/* 正确的变量声明方式 - C89兼容 */
void LED_Function(void)
{
    uint8_t i;                    /* 在函数开头声明 */
    uint8_t pattern_count;        /* 所有变量统一声明 */
    
    for (i = 0; i < LED_COUNT; i++)
    {
        /* 循环体 */
    }
}

3. 延时精度与系统性能

本项目使用PLATFORM_DelayMS()函数实现精确延时:

/* 延时函数特性分析 */
- 基于SysTick定时器实现
- 延时精度:±1ms
- 支持范围:1ms - 65535ms
- CPU占用:阻塞式延时,适合简单应用

4. 内存优化策略

/* 内存使用分析 */
代码段:约3.2KB Flash
数据段:约120字节RAM  
堆栈:约200字节RAM
总占用率:Flash < 10%, RAM < 8%

扩展应用方案

1. 智能响应式控制

扩展系统支持传感器输入响应:

/* 声控LED系统扩展 */
void LED_Sound_Response(void)
{
    uint16_t sound_level;
    sound_level = ADC_GetSoundLevel();    /* 获取声音强度 */
    
    if (sound_level > THRESHOLD_HIGH)
        LED_Breathing(100);               /* 高音触发呼吸灯 */
    else if (sound_level > THRESHOLD_MID)
        LED_Flow_LeftToRight(200);        /* 中音触发流水灯 */
    else
        LED_All_Off();                    /* 静音关闭 */
}
```

2. PWM调光控制

利用定时器PWM功能实现LED亮度渐变:

/* PWM调光扩展 */
void LED_PWM_Dimming(uint8_t led_index, uint16_t brightness)
{
    TIM_SetCompare1(TIM1, brightness);    /* 0-1000对应0-100%亮度 */
}
/* 渐变呼吸灯效果 */
void LED_Fade_Breathing(void)
{
    uint16_t brightness;
    
    for (brightness = 0; brightness <= 1000; brightness += 10)
    {
        LED_PWM_Dimming(0, brightness);
        PLATFORM_DelayMS(5);
    }
    
    for (brightness = 1000; brightness >= 0; brightness -= 10)
    {
        LED_PWM_Dimming(0, brightness);
        PLATFORM_DelayMS(5);
    }
}

3. 通信接口扩展

添加串口控制功能,支持PC端控制:

/* 串口命令控制扩展 */
void UART_Command_Handler(uint8_t cmd)
{
    switch (cmd)
    {
        case 'A': LED_Flow_LeftToRight(100); break;
        case 'B': LED_Breathing(200); break;
        case 'C': LED_Random_Blink(150); break;
        case 'S': LED_All_Off(); break;
        default: break;
    }
}

总结

本文详细介绍了基于FTHR-G0001开发板和MM32G0001微控制器的5LED多模式控制系统。通过完整的设计、编程和调试过程,成功实现了以下技术目标:

       1. 硬件平台掌握:深入了解MM32G0001的GPIO特性和开发板布局

       2. 开发环境熟练:熟练使用KEIL MDK工具链进行嵌入式开发  

       3. 模块化编程:采用分层架构设计,代码结构清晰可维护

       4. 多模式算法:实现7种不同的LED显示效果算法

       5. C标准兼容:严格遵循C89标准,确保编译器兼容性

       6. 工程化应用:提供完整的问题排查和性能优化方案


参考资料

1.MM32G0001数据手册 v2.1

2.FTHR-G0001开发板用户指南 v1.3

3.MindMotion HAL库参考手册

4.KEIL MDK-ARM用户手册 v5.37

5.ISO/IEC 9899:1990 (C89/C90标准)




全部评论
暂无评论
0/144