当前位置:   article > 正文

STM32读写内部FLASH

STM32读写内部FLASH

文章目录

1. FLASH

2. 读写内部FLASH

2.1 软件调试

2.2  MyFLASH.c

2.3  MyFLASH.h

2.4 Store.c

2.5 Store.h

2.6 main.c

3. 读取芯片ID

3.1 main.c


1. FLASH

对于FLASH闪存的详细解析可以看下面这篇文章:

STM32单片机FLASH闪存详解-CSDN博客

2. 读写内部FLASH

代码中My实现闪存的读取,擦除和编程功能,store实现参数数据的读写和储存管理。最终实现任意读写参数,参数掉电不丢失。

2.1 软件调试

使用STM32 ST-LINK Utility软件可以实时查看闪存中保存的参数。

打开软件后,使用ST-link将stm32连接到电脑,点击第三个按钮(Connect to the target),就可以看到闪存中保存的参数。

Address: 0x08000000 代表闪存地址的起始位。下面数据就是程序代码

size:0x1000 代表从起始地址开始,一共查看多少个字节。这里是查看64kb的字节数,计算方法为:先转为十进制:65536,然后除以1024,得到64.

Data Width:数据宽度,这里是32bits

并且点击任意一个数据,可以直接修改stm32中的数据。

选项字节配置

点击Target - Option Core,打开选项字节配置页面,包括读保护,用户配置,自定义两个字节和写保护。

需要使用的相关函数在文件stm32f10x_flash.c 和 stm32f10x_flash.h中

2.2  MyFLASH.c

  1. #include "stm32f10x.h" // Device header
  2. /**
  3. * 函 数:FLASH读取一个32位的字
  4. * 参 数:Address 要读取数据的字地址
  5. * 返 回 值:指定地址下的数据
  6. */
  7. uint32_t MyFLASH_ReadWord(uint32_t Address)
  8. {
  9. return *((__IO uint32_t *)(Address)); //使用指针访问指定地址下的数据并返回
  10. }
  11. /**
  12. * 函 数:FLASH读取一个16位的半字
  13. * 参 数:Address 要读取数据的半字地址
  14. * 返 回 值:指定地址下的数据
  15. */
  16. uint16_t MyFLASH_ReadHalfWord(uint32_t Address)
  17. {
  18. return *((__IO uint16_t *)(Address)); //使用指针访问指定地址下的数据并返回
  19. }
  20. /**
  21. * 函 数:FLASH读取一个8位的字节
  22. * 参 数:Address 要读取数据的字节地址
  23. * 返 回 值:指定地址下的数据
  24. */
  25. uint8_t MyFLASH_ReadByte(uint32_t Address)
  26. {
  27. return *((__IO uint8_t *)(Address)); //使用指针访问指定地址下的数据并返回
  28. }
  29. /**
  30. * 函 数:FLASH全擦除
  31. * 说 明:调用此函数后,FLASH的所有页都会被擦除,包括程序文件本身,擦除后,程序将不复存在
  32. */
  33. void MyFLASH_EraseAllPages(void)
  34. {
  35. FLASH_Unlock(); //解锁
  36. FLASH_EraseAllPages(); //全擦除
  37. FLASH_Lock(); //加锁
  38. }
  39. /**
  40. * 函 数:FLASH页擦除
  41. * 参 数:PageAddress 要擦除页的页地址
  42. */
  43. void MyFLASH_ErasePage(uint32_t PageAddress)
  44. {
  45. FLASH_Unlock(); //解锁
  46. FLASH_ErasePage(PageAddress); //页擦除
  47. FLASH_Lock(); //加锁
  48. }
  49. /**
  50. * 函 数:FLASH编程字
  51. * 参 数:Address 要写入数据的字地址
  52. * 参 数:Data 要写入的32位数据
  53. */
  54. void MyFLASH_ProgramWord(uint32_t Address, uint32_t Data)
  55. {
  56. FLASH_Unlock(); //解锁
  57. FLASH_ProgramWord(Address, Data); //编程字
  58. FLASH_Lock(); //加锁
  59. }
  60. /**
  61. * 函 数:FLASH编程半字
  62. * 参 数:Address 要写入数据的半字地址
  63. * 参 数:Data 要写入的16位数据
  64. */
  65. void MyFLASH_ProgramHalfWord(uint32_t Address, uint16_t Data)
  66. {
  67. FLASH_Unlock(); //解锁
  68. FLASH_ProgramHalfWord(Address, Data); //编程半字
  69. FLASH_Lock(); //加锁
  70. }

2.3  MyFLASH.h

  1. #ifndef __MYFLASH_H
  2. #define __MYFLASH_H
  3. uint32_t MyFLASH_ReadWord(uint32_t Address);
  4. uint16_t MyFLASH_ReadHalfWord(uint32_t Address);
  5. uint8_t MyFLASH_ReadByte(uint32_t Address);
  6. void MyFLASH_EraseAllPages(void);
  7. void MyFLASH_ErasePage(uint32_t PageAddress);
  8. void MyFLASH_ProgramWord(uint32_t Address, uint32_t Data);
  9. void MyFLASH_ProgramHalfWord(uint32_t Address, uint16_t Data);
  10. #endif

2.4 Store.c

  1. #include "stm32f10x.h" // Device header
  2. #include "MyFLASH.h"
  3. #define STORE_START_ADDRESS 0x0800FC00 //存储的起始地址
  4. #define STORE_COUNT 512 //存储数据的个数
  5. uint16_t Store_Data[STORE_COUNT]; //定义SRAM数组
  6. //参数存储模块初始化
  7. void Store_Init(void)
  8. {
  9. /*判断是不是第一次使用*/
  10. if (MyFLASH_ReadHalfWord(STORE_START_ADDRESS) != 0xA5A5) //读取第一个半字的标志位,if成立,则执行第一次使用的初始化
  11. {
  12. MyFLASH_ErasePage(STORE_START_ADDRESS); //擦除指定页
  13. MyFLASH_ProgramHalfWord(STORE_START_ADDRESS, 0xA5A5); //在第一个半字写入自己规定的标志位,用于判断是不是第一次使用
  14. for (uint16_t i = 1; i < STORE_COUNT; i ++) //循环STORE_COUNT次,除了第一个标志位
  15. {
  16. MyFLASH_ProgramHalfWord(STORE_START_ADDRESS + i * 2, 0x0000); //除了标志位的有效数据全部清0
  17. }
  18. }
  19. /*上电时,将闪存数据加载回SRAM数组,实现SRAM数组的掉电不丢失*/
  20. for (uint16_t i = 0; i < STORE_COUNT; i ++) //循环STORE_COUNT次,包括第一个标志位
  21. {
  22. Store_Data[i] = MyFLASH_ReadHalfWord(STORE_START_ADDRESS + i * 2); //将闪存的数据加载回SRAM数组
  23. }
  24. }
  25. //参数存储模块保存数据到闪存
  26. void Store_Save(void)
  27. {
  28. MyFLASH_ErasePage(STORE_START_ADDRESS); //擦除指定页
  29. for (uint16_t i = 0; i < STORE_COUNT; i ++) //循环STORE_COUNT次,包括第一个标志位
  30. {
  31. MyFLASH_ProgramHalfWord(STORE_START_ADDRESS + i * 2, Store_Data[i]); //将SRAM数组的数据备份保存到闪存
  32. }
  33. }
  34. //参数存储模块将所有有效数据清0
  35. void Store_Clear(void)
  36. {
  37. for (uint16_t i = 1; i < STORE_COUNT; i ++) //循环STORE_COUNT次,除了第一个标志位
  38. {
  39. Store_Data[i] = 0x0000; //SRAM数组有效数据清0
  40. }
  41. Store_Save(); //保存数据到闪存
  42. }

2.5 Store.h

  1. #ifndef __STORE_H
  2. #define __STORE_H
  3. extern uint16_t Store_Data[];
  4. void Store_Init(void);
  5. void Store_Save(void);
  6. void Store_Clear(void);
  7. #endif

2.6 main.c

  • 模块初始化

    • 初始化OLED显示屏。
    • 初始化按键模块。
    • 初始化参数存储模块,并在上电时将闪存中的数据加载回 Store_Data
  • 显示静态字符串

    • 在OLED显示屏上显示静态字符串“Flag:”和“Data:”。
  • 主循环

    • 获取按键键码。
    • 根据按键键码执行不同操作:
      • 如果按键1按下,更新 Store_Data 中的数据,并将数据备份保存到闪存中。
      • 如果按键2按下,清除 Store_Data 中的所有数据。
    • 显示 Store_Data 中的数据。
  1. #include "stm32f10x.h" // Device header
  2. #include "Delay.h"
  3. #include "OLED.h"
  4. #include "Store.h"
  5. #include "Key.h"
  6. uint8_t KeyNum; //定义用于接收按键键码的变量
  7. int main(void)
  8. {
  9. /*模块初始化*/
  10. OLED_Init(); //OLED初始化
  11. Key_Init(); //按键初始化
  12. Store_Init(); //参数存储模块初始化,在上电的时候将闪存的数据加载回Store_Data,实现掉电不丢失
  13. /*显示静态字符串*/
  14. OLED_ShowString(1, 1, "Flag:");
  15. OLED_ShowString(2, 1, "Data:");
  16. while (1)
  17. {
  18. KeyNum = Key_GetNum(); //获取按键键码
  19. if (KeyNum == 1) //按键1按下
  20. {
  21. Store_Data[1] ++; //变换测试数据
  22. Store_Data[2] += 2;
  23. Store_Data[3] += 3;
  24. Store_Data[4] += 4;
  25. Store_Save(); //将Store_Data的数据备份保存到闪存,实现掉电不丢失
  26. }
  27. if (KeyNum == 2) //按键2按下
  28. {
  29. Store_Clear(); //将Store_Data的数据全部清0
  30. }
  31. OLED_ShowHexNum(1, 6, Store_Data[0], 4); //显示Store_Data的第一位标志位
  32. OLED_ShowHexNum(3, 1, Store_Data[1], 4); //显示Store_Data的有效存储数据
  33. OLED_ShowHexNum(3, 6, Store_Data[2], 4);
  34. OLED_ShowHexNum(4, 1, Store_Data[3], 4);
  35. OLED_ShowHexNum(4, 6, Store_Data[4], 4);
  36. }
  37. }

3. 读取芯片ID

这个代码可以实现读取闪存容量和身份标识。

3.1 main.c

  1. #include "stm32f10x.h" // Device header
  2. #include "Delay.h"
  3. #include "OLED.h"
  4. int main(void)
  5. {
  6. OLED_Init(); //OLED初始化
  7. OLED_ShowString(1, 1, "F_SIZE:"); //显示静态字符串
  8. OLED_ShowHexNum(1, 8, *((__IO uint16_t *)(0x1FFFF7E0)), 4); //使用指针读取指定地址下的闪存容量寄存器
  9. OLED_ShowString(2, 1, "U_ID:"); //显示静态字符串
  10. OLED_ShowHexNum(2, 6, *((__IO uint16_t *)(0x1FFFF7E8)), 4); //使用指针读取指定地址下的产品唯一身份标识寄存器
  11. OLED_ShowHexNum(2, 11, *((__IO uint16_t *)(0x1FFFF7E8 + 0x02)), 4);
  12. OLED_ShowHexNum(3, 1, *((__IO uint32_t *)(0x1FFFF7E8 + 0x04)), 8);
  13. OLED_ShowHexNum(4, 1, *((__IO uint32_t *)(0x1FFFF7E8 + 0x08)), 8);
  14. while (1)
  15. {
  16. }
  17. }

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/771252
推荐阅读
相关标签
  

闽ICP备14008679号