将闪存与STM32C031C6TX一起使用

Using Flash memory with STM32C031C6TX

提问人:Mendi 提问时间:7/28/2023 最后编辑:IssylinMendi 更新时间:8/1/2023 访问量:60

问:

我试图添加的是 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);

  }
}

如果我错过了任何有价值的信息,请告诉我,我会提供更多。

谢谢!

C STM32

评论

0赞 pmacfarlane 7/28/2023
几乎可以肯定的是,您不希望每次关闭 LED 时都擦除和写入闪光灯。你想解决的问题是什么(在你开始考虑闪存之前,你的代码还没有实现)?如果要保存某些在电源循环中幸存下来的状态,则可以使用闪存。这不是你所描述的。
0赞 Mendi 7/28/2023
@pmacfarlane 你好!所以现在一切都很好。我有 9 种颜色,每次打开和关闭开关时都会循环显示。现在我想添加一个新功能。假设我正在打开和关闭开关,我停止打开橙色,然后关闭 LED。关闭 5 秒后,然后重新打开 LED,我希望颜色是橙色,而不是变成下一个颜色。我想有一种方法可以保存 LED 亮起的最后一种颜色,仅在 LED 熄灭 5 秒后。如果这是有道理的。

答:

1赞 pmacfarlane 7/28/2023 #1

似乎您只想在 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)。

评论

0赞 Mendi 7/28/2023
效果很好!我刚刚意识到,当我将电路板从电源上拔下并重新插入电路板时,它会从情况 0 开始:应该如此,但我希望它保存在我断开电源 (USB) 之前的最后颜色。如果不将其保存到内存中,这仍然可能吗?
0赞 pmacfarlane 7/28/2023
如果您的电路板上有电池(用于 RTC),那么您可以使用一些寄存器在电源循环中幸存下来。如果你不这样做,你确实必须使用闪光灯。对于您的应用程序来说,这将是比它的价值更多的痛苦。
-1赞 Oscar Beausoleil 8/1/2023 #2

告诉你你的设计被误导了,就像这里的其他答案一样,没有多大用处。

您正在将变量保存到闪存中,但我没有看到您将其拉回的任何地方。我建议使用像STM32CubeProgrammer这样的工具来检查闪存中的那个位置,以确保它被保存在那里。

当您启动程序时,您需要提取该部分内存,并使用它来设置灯光的初始状态。 有关如何使用闪存的更多详细信息,请参阅微控制器的 HAL 手册: https://www.st.com/resource/en/user_manual/um3029-description-of-stm32c0-hal-and-lowlayer-drivers-stmicroelectronics.pdf

评论

0赞 Community 8/7/2023
您的答案可以通过额外的支持信息得到改进。请编辑以添加更多详细信息,例如引文或文档,以便其他人可以确认您的答案是正确的。您可以在帮助中心找到有关如何写出好答案的更多信息。