提问人:Mendi 提问时间:7/28/2023 最后编辑:IssylinMendi 更新时间:8/1/2023 访问量:60
将闪存与STM32C031C6TX一起使用
Using Flash memory with STM32C031C6TX
问:
我试图添加的是 LED 熄灭 5 秒后,我想保存最后的 LED 颜色,然后当我重新打开 LED 时,它是我之前关闭 LED 之前的最后一种颜色。我在网上读到的是,我应该将闪存与我的微控制器一起使用,以获得我试图实现的功能。
我使用的微控制器是STM32C031C6TX。
我似乎无法让它正常工作。这是我目前的设置:
包括:#include“stm32c0xx_hal_flash.h”和 #define LAST_COLOR_ADDRESS((uint32_t)0x08000000)
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdbool.h>
#include "stm32c0xx_hal_flash.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define LAST_COLOR_ADDRESS ((uint32_t)0x08000000)
/* USER CODE END PD */
void switch_off_all_leds(void)
{
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)));
HAL_FLASH_Unlock();
FLASH_Erase_Sector(FLASH_SECTOR_0, FLASH_VOLTAGE_RANGE_1); // Erase the sector before programming
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, LAST_COLOR_ADDRESS, lastColor);
HAL_FLASH_Lock();
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, 0); // Red
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 0); // Green
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 0); // Blue
};
完整代码:
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM3_Init();
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
uint8_t sins[360] = {
127,129,131,134,136,138,140,143,145,147,149,151,154,156,158,160,162,164,166,169,171,173,175,177,179,181,183,185,187,189,191,193,195,196,198,200,
202,204,205,207,209,211,212,214,216,217,219,220,222,223,225,226,227,229,230,231,233,234,235,236,237,239,240,241,242,243,243,244,245,246,247,248,
248,249,250,250,251,251,252,252,253,253,253,254,254,254,254,254,254,254,255,254,254,254,254,254,254,254,253,253,253,252,252,251,251,250,250,249,
248,248,247,246,245,244,243,243,242,241,240,239,237,236,235,234,233,231,230,229,227,226,225,223,222,220,219,217,216,214,212,211,209,207,205,204,
202,200,198,196,195,193,191,189,187,185,183,181,179,177,175,173,171,169,166,164,162,160,158,156,154,151,149,147,145,143,140,138,136,134,131,129,
127,125,123,120,118,116,114,111,109,107,105,103,100,98,96,94,92,90,88,85,83,81,79,77,75,73,71,69,67,65,63,61,59,58,56,54,
52,50,49,47,45,43,42,40,38,37,35,34,32,31,29,28,27,25,24,23,21,20,19,18,17,15,14,13,12,11,11,10,9,8,7,6,
6,5,4,4,3,3,2,2,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,2,2,3,3,4,4,5,
6,6,7,8,9,10,11,11,12,13,14,15,17,18,19,20,21,23,24,25,27,28,29,31,32,34,35,37,38,40,42,43,45,47,49,50,
52,54,56,58,59,61,63,65,67,69,71,73,75,77,79,81,83,85,88,90,92,94,96,98,100,103,105,107,109,111,114,116,118,120,123,125
};
enum button_state_e {
BUTTON_NOT_PRESSED,
BUTTON_JUST_PRESSED,
BUTTON_PRESSED
};
static enum button_state_e button_state = BUTTON_NOT_PRESSED;
static uint8_t color_sequence = 0;
void red_sequence(void) {
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, 230); // Red
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 0); // Green
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 0); // Blue
};
void green_sequence(void) {
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, 0); // Red
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 230); // Green
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 0); // Blue
};
void blue_sequence(void) {
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, 0); // Red
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 0); // Green
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 230); // Blue
};
void pink_sequence(void) {
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, 230); // Red
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 0); // Green
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 50); // Blue
};
void teal_sequence(void) {
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, 0); // Red
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 230); // Green
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 230); // Blue
};
void yellow_sequence(void) {
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, 230); // Red
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 140); // Green
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 0); // Blue
};
void orange_sequence(void) {
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, 230); // Red
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 25); // Green
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 0); // Blue
};
void purple_sequence(void) {
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, 230); // Red
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 0); // Green
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 100); // Blue
};
void white_sequence(void) {
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, 230); // Red
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 230); // Green
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 230); // Blue
};
void party_sequence(void) {
int i = 0;
while (1) {
for (i = 0; i < 360; i++) {
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, sins[i]); // Red
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, sins[(i + 120) % 360]); // Green
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, sins[(i + 240) % 360]); // Blue
HAL_Delay(2);
if (HAL_GPIO_ReadPin(Toggle_Switch_GPIO_Port, Toggle_Switch_Pin) != GPIO_PIN_SET)
return;
}
}
};
void switch_off_all_leds(void)
{
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)));
HAL_FLASH_Unlock();
FLASH_Erase_Sector(FLASH_SECTOR_0, FLASH_VOLTAGE_RANGE_1);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, LAST_COLOR_ADDRESS, lastColor);
HAL_FLASH_Lock();
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, 0); // Red
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 0); // Green
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 0); // Blue
};
while (1)
{
bool pressed = (HAL_GPIO_ReadPin(Toggle_Switch_GPIO_Port, Toggle_Switch_Pin) == GPIO_PIN_SET);
switch (button_state)
{
case BUTTON_NOT_PRESSED:
if (pressed)
button_state = BUTTON_JUST_PRESSED;
break;
case BUTTON_JUST_PRESSED:
if (pressed)
{
button_state = BUTTON_PRESSED;
switch (color_sequence) {
case 0:
red_sequence();
break;
case 1:
green_sequence();
break;
case 2:
blue_sequence();
break;
case 3:
pink_sequence();
break;
case 4:
teal_sequence();
break;
case 5:
yellow_sequence();
break;
case 6:
orange_sequence();
break;
case 7:
purple_sequence();
break;
case 8:
white_sequence();
break;
case 9:
party_sequence();
break;
}
color_sequence = (color_sequence + 1) % 10;
}
else
button_state = BUTTON_NOT_PRESSED;
break;
case BUTTON_PRESSED:
if (!pressed)
{
button_state = BUTTON_NOT_PRESSED;
switch_off_all_leds();
}
break;
}
HAL_Delay(10);
}
}
如果我错过了任何有价值的信息,请告诉我,我会提供更多。
谢谢!
答:
似乎您只想在 MCU 打开时执行此操作,因此您只需使用 RAM 中的常规变量来跟踪当前状态,而无需在闪存等非易失性存储器中存储任何东西。
创建一个新变量以记录 LED 熄灭时的当前毫秒滴答值:
uint32_t led_off_tick;
....the code that switches off the LEDs...
case BUTTON_PRESSED:
if (!pressed)
{
button_state = BUTTON_NOT_PRESSED;
switch_off_all_leds();
led_off_tick = HAL_GetTick(); // Record when the LEDs went off
}
更改“开机”代码,仅当自上次关机以来打开的时间少于 5 秒时才增加当前配色方案:
case BUTTON_JUST_PRESSED:
if (pressed)
{
button_state = BUTTON_PRESSED;
if ((HAL_GetTick() - led_off_tick) < 5000u)
color_sequence = (color_sequence + 1) % 10;
switch (color_sequence) {
case 0:
red_sequence();
break;
... etc ...
}
并且显然删除了该代码末尾的增量。color_sequence
如果您确实需要跟踪电源循环期间的状态,则可能需要使用闪存,但也可以使用电池备份寄存器(如果您的系统中有电池,则用于 RTC)。
评论
告诉你你的设计被误导了,就像这里的其他答案一样,没有多大用处。
您正在将变量保存到闪存中,但我没有看到您将其拉回的任何地方。我建议使用像STM32CubeProgrammer这样的工具来检查闪存中的那个位置,以确保它被保存在那里。
当您启动程序时,您需要提取该部分内存,并使用它来设置灯光的初始状态。 有关如何使用闪存的更多详细信息,请参阅微控制器的 HAL 手册: https://www.st.com/resource/en/user_manual/um3029-description-of-stm32c0-hal-and-lowlayer-drivers-stmicroelectronics.pdf
评论