STM32C031C6TX Flash存储LED最后颜色功能实现求助
STM32C031C6TX LED颜色保存与恢复故障排查及修复
问题概述
需要实现:LED关闭5秒后保存最后显示的颜色,再次开启时恢复该颜色,采用STM32C031C6TX的Flash存储,但当前功能无法正常运行。
现有代码的核心问题
- Flash地址错误:
0x08000000是芯片程序存储的起始地址,直接擦写会覆盖固件,导致程序崩溃。 - 缺少读取恢复逻辑:仅实现了颜色保存,未在开机时读取Flash中的保存值并恢复LED颜色。
- 保存时机不符合需求:当前开关松开立即保存,未实现“关闭5秒后保存”的延迟逻辑。
- Flash操作无错误检查:擦除、编程过程未校验返回值,无法定位失败原因。
- 扇区擦写方法不规范:直接调用底层
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, §orError) == 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
相关产品推荐
相关产品推荐

