You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32C031C6TX Flash存储LED最后颜色功能实现求助

STM32C031C6TX LED颜色保存与恢复故障排查及修复

问题概述

需要实现:LED关闭5秒后保存最后显示的颜色,再次开启时恢复该颜色,采用STM32C031C6TX的Flash存储,但当前功能无法正常运行。

现有代码的核心问题

  1. Flash地址错误:0x08000000是芯片程序存储的起始地址,直接擦写会覆盖固件,导致程序崩溃。
  2. 缺少读取恢复逻辑:仅实现了颜色保存,未在开机时读取Flash中的保存值并恢复LED颜色。
  3. 保存时机不符合需求:当前开关松开立即保存,未实现“关闭5秒后保存”的延迟逻辑。
  4. Flash操作无错误检查:擦除、编程过程未校验返回值,无法定位失败原因。
  5. 扇区擦写方法不规范:直接调用底层FLASH_Erase_Sector,未使用HAL库封装的HAL_FLASHEx_Erase函数。

修复方案

1. 修正Flash存储地址

STM32C031C6TX的Flash共32KB,分为两个16KB扇区:

  • Sector 0:0x08000000 - 0x08003FFF(存储程序代码)
  • Sector 1:0x08004000 - 0x08007FFF(空闲扇区,用于存储数据)

修改地址定义:

#define LAST_COLOR_ADDRESS ((uint32_t)0x08004000)

2. 添加开机读取恢复逻辑

在main函数初始化PWM后,添加读取Flash并恢复颜色的代码:

HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3); // Red
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2); // Green
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_4); // Blue

// 读取Flash中保存的颜色
uint32_t savedColor = *(uint32_t*)LAST_COLOR_ADDRESS;
uint8_t red = (savedColor >> 16) & 0xFF;
uint8_t green = (savedColor >> 8) & 0xFF;
uint8_t blue = savedColor & 0xFF;

// 若Flash未被写入过(默认值0xFFFFFFFF),则设置默认颜色为红色
if(savedColor != 0xFFFFFFFF){
    __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, red);
    __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, green);
    __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, blue);
} else {
    red_sequence();
}

3. 实现“关闭5秒后保存”的逻辑

修改button_state的BUTTON_PRESSED分支逻辑,先关闭LED,延迟5秒期间检查开关是否再次按下,若未按下则保存颜色:

case BUTTON_PRESSED:
    if (!pressed)
    {
        button_state = BUTTON_NOT_PRESSED;
        // 立即关闭LED
        __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, 0);
        __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 0);
        __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 0);
        
        uint32_t startTick = HAL_GetTick();
        bool shouldSave = true;
        // 等待5秒,期间若开关再次按下则取消保存
        while(HAL_GetTick() - startTick < 5000){
            if(HAL_GPIO_ReadPin(Toggle_Switch_GPIO_Port, Toggle_Switch_Pin) == GPIO_PIN_SET){
                shouldSave = false;
                break;
            }
            HAL_Delay(10);
        }
        
        if(shouldSave){
            uint32_t lastColor = ((__HAL_TIM_GET_COMPARE(&htim3, TIM_CHANNEL_3) << 16) |
                                  (__HAL_TIM_GET_COMPARE(&htim3, TIM_CHANNEL_2) << 8) |
                                  (__HAL_TIM_GET_COMPARE(&htim3, TIM_CHANNEL_4)));
            
            // 先检查当前颜色与Flash中保存的是否一致,避免不必要的擦写
            uint32_t savedColor = *(uint32_t*)LAST_COLOR_ADDRESS;
            if(lastColor != savedColor){
                HAL_FLASH_Unlock();
                
                FLASH_EraseInitTypeDef eraseInit;
                eraseInit.TypeErase = FLASH_TYPEERASE_SECTORS;
                eraseInit.Sector = FLASH_SECTOR_1;
                eraseInit.NbSectors = 1;
                eraseInit.VoltageRange = FLASH_VOLTAGE_RANGE_1;
                uint32_t sectorError = 0;
                
                // 擦除扇区并检查错误
                if(HAL_FLASHEx_Erase(&eraseInit, &sectorError) == HAL_OK){
                    // 编程Flash并检查错误
                    if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, LAST_COLOR_ADDRESS, lastColor) != HAL_OK){
                        Error_Handler();
                    }
                } else {
                    Error_Handler();
                }
                
                HAL_FLASH_Lock();
            }
        }
    }
    break;

4. 移除冗余的switch_off_all_leds函数

上述逻辑已包含关闭LED和保存颜色的功能,可删除原switch_off_all_leds函数,避免代码冗余。

额外注意事项

  • Flash擦写有寿命限制(约10万次),通过“颜色变化才擦写”的逻辑可有效延长寿命。
  • 若调试时仍出现问题,可在Error_Handler中添加LED闪烁等指示,快速定位Flash操作错误。

内容的提问来源于stack exchange,提问作者Mendi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 21:29:52