赞
踩
对于FLASH闪存的详细解析可以看下面这篇文章:
代码中My实现闪存的读取,擦除和编程功能,store实现参数数据的读写和储存管理。最终实现任意读写参数,参数掉电不丢失。
使用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中
- #include "stm32f10x.h" // Device header
-
- /**
- * 函 数:FLASH读取一个32位的字
- * 参 数:Address 要读取数据的字地址
- * 返 回 值:指定地址下的数据
- */
- uint32_t MyFLASH_ReadWord(uint32_t Address)
- {
- return *((__IO uint32_t *)(Address)); //使用指针访问指定地址下的数据并返回
- }
-
- /**
- * 函 数:FLASH读取一个16位的半字
- * 参 数:Address 要读取数据的半字地址
- * 返 回 值:指定地址下的数据
- */
- uint16_t MyFLASH_ReadHalfWord(uint32_t Address)
- {
- return *((__IO uint16_t *)(Address)); //使用指针访问指定地址下的数据并返回
- }
-
- /**
- * 函 数:FLASH读取一个8位的字节
- * 参 数:Address 要读取数据的字节地址
- * 返 回 值:指定地址下的数据
- */
- uint8_t MyFLASH_ReadByte(uint32_t Address)
- {
- return *((__IO uint8_t *)(Address)); //使用指针访问指定地址下的数据并返回
- }
-
- /**
- * 函 数:FLASH全擦除
- * 说 明:调用此函数后,FLASH的所有页都会被擦除,包括程序文件本身,擦除后,程序将不复存在
- */
- void MyFLASH_EraseAllPages(void)
- {
- FLASH_Unlock(); //解锁
- FLASH_EraseAllPages(); //全擦除
- FLASH_Lock(); //加锁
- }
-
- /**
- * 函 数:FLASH页擦除
- * 参 数:PageAddress 要擦除页的页地址
- */
- void MyFLASH_ErasePage(uint32_t PageAddress)
- {
- FLASH_Unlock(); //解锁
- FLASH_ErasePage(PageAddress); //页擦除
- FLASH_Lock(); //加锁
- }
-
- /**
- * 函 数:FLASH编程字
- * 参 数:Address 要写入数据的字地址
- * 参 数:Data 要写入的32位数据
- */
- void MyFLASH_ProgramWord(uint32_t Address, uint32_t Data)
- {
- FLASH_Unlock(); //解锁
- FLASH_ProgramWord(Address, Data); //编程字
- FLASH_Lock(); //加锁
- }
-
- /**
- * 函 数:FLASH编程半字
- * 参 数:Address 要写入数据的半字地址
- * 参 数:Data 要写入的16位数据
- */
- void MyFLASH_ProgramHalfWord(uint32_t Address, uint16_t Data)
- {
- FLASH_Unlock(); //解锁
- FLASH_ProgramHalfWord(Address, Data); //编程半字
- FLASH_Lock(); //加锁
- }
- #ifndef __MYFLASH_H
- #define __MYFLASH_H
-
- uint32_t MyFLASH_ReadWord(uint32_t Address);
- uint16_t MyFLASH_ReadHalfWord(uint32_t Address);
- uint8_t MyFLASH_ReadByte(uint32_t Address);
-
- void MyFLASH_EraseAllPages(void);
- void MyFLASH_ErasePage(uint32_t PageAddress);
-
- void MyFLASH_ProgramWord(uint32_t Address, uint32_t Data);
- void MyFLASH_ProgramHalfWord(uint32_t Address, uint16_t Data);
-
- #endif
- #include "stm32f10x.h" // Device header
- #include "MyFLASH.h"
-
- #define STORE_START_ADDRESS 0x0800FC00 //存储的起始地址
- #define STORE_COUNT 512 //存储数据的个数
-
- uint16_t Store_Data[STORE_COUNT]; //定义SRAM数组
-
- //参数存储模块初始化
- void Store_Init(void)
- {
- /*判断是不是第一次使用*/
- if (MyFLASH_ReadHalfWord(STORE_START_ADDRESS) != 0xA5A5) //读取第一个半字的标志位,if成立,则执行第一次使用的初始化
- {
- MyFLASH_ErasePage(STORE_START_ADDRESS); //擦除指定页
- MyFLASH_ProgramHalfWord(STORE_START_ADDRESS, 0xA5A5); //在第一个半字写入自己规定的标志位,用于判断是不是第一次使用
- for (uint16_t i = 1; i < STORE_COUNT; i ++) //循环STORE_COUNT次,除了第一个标志位
- {
- MyFLASH_ProgramHalfWord(STORE_START_ADDRESS + i * 2, 0x0000); //除了标志位的有效数据全部清0
- }
- }
-
- /*上电时,将闪存数据加载回SRAM数组,实现SRAM数组的掉电不丢失*/
- for (uint16_t i = 0; i < STORE_COUNT; i ++) //循环STORE_COUNT次,包括第一个标志位
- {
- Store_Data[i] = MyFLASH_ReadHalfWord(STORE_START_ADDRESS + i * 2); //将闪存的数据加载回SRAM数组
- }
- }
-
- //参数存储模块保存数据到闪存
- void Store_Save(void)
- {
- MyFLASH_ErasePage(STORE_START_ADDRESS); //擦除指定页
- for (uint16_t i = 0; i < STORE_COUNT; i ++) //循环STORE_COUNT次,包括第一个标志位
- {
- MyFLASH_ProgramHalfWord(STORE_START_ADDRESS + i * 2, Store_Data[i]); //将SRAM数组的数据备份保存到闪存
- }
- }
-
- //参数存储模块将所有有效数据清0
- void Store_Clear(void)
- {
- for (uint16_t i = 1; i < STORE_COUNT; i ++) //循环STORE_COUNT次,除了第一个标志位
- {
- Store_Data[i] = 0x0000; //SRAM数组有效数据清0
- }
- Store_Save(); //保存数据到闪存
- }
- #ifndef __STORE_H
- #define __STORE_H
-
- extern uint16_t Store_Data[];
-
- void Store_Init(void);
- void Store_Save(void);
- void Store_Clear(void);
-
- #endif
模块初始化:
Store_Data
。显示静态字符串:
主循环:
Store_Data
中的数据,并将数据备份保存到闪存中。Store_Data
中的所有数据。Store_Data
中的数据。- #include "stm32f10x.h" // Device header
- #include "Delay.h"
- #include "OLED.h"
- #include "Store.h"
- #include "Key.h"
-
- uint8_t KeyNum; //定义用于接收按键键码的变量
-
- int main(void)
- {
- /*模块初始化*/
- OLED_Init(); //OLED初始化
- Key_Init(); //按键初始化
- Store_Init(); //参数存储模块初始化,在上电的时候将闪存的数据加载回Store_Data,实现掉电不丢失
-
- /*显示静态字符串*/
- OLED_ShowString(1, 1, "Flag:");
- OLED_ShowString(2, 1, "Data:");
-
- while (1)
- {
- KeyNum = Key_GetNum(); //获取按键键码
-
- if (KeyNum == 1) //按键1按下
- {
- Store_Data[1] ++; //变换测试数据
- Store_Data[2] += 2;
- Store_Data[3] += 3;
- Store_Data[4] += 4;
- Store_Save(); //将Store_Data的数据备份保存到闪存,实现掉电不丢失
- }
-
- if (KeyNum == 2) //按键2按下
- {
- Store_Clear(); //将Store_Data的数据全部清0
- }
-
- OLED_ShowHexNum(1, 6, Store_Data[0], 4); //显示Store_Data的第一位标志位
- OLED_ShowHexNum(3, 1, Store_Data[1], 4); //显示Store_Data的有效存储数据
- OLED_ShowHexNum(3, 6, Store_Data[2], 4);
- OLED_ShowHexNum(4, 1, Store_Data[3], 4);
- OLED_ShowHexNum(4, 6, Store_Data[4], 4);
- }
- }
这个代码可以实现读取闪存容量和身份标识。
- #include "stm32f10x.h" // Device header
- #include "Delay.h"
- #include "OLED.h"
-
- int main(void)
- {
- OLED_Init(); //OLED初始化
-
- OLED_ShowString(1, 1, "F_SIZE:"); //显示静态字符串
- OLED_ShowHexNum(1, 8, *((__IO uint16_t *)(0x1FFFF7E0)), 4); //使用指针读取指定地址下的闪存容量寄存器
-
- OLED_ShowString(2, 1, "U_ID:"); //显示静态字符串
- OLED_ShowHexNum(2, 6, *((__IO uint16_t *)(0x1FFFF7E8)), 4); //使用指针读取指定地址下的产品唯一身份标识寄存器
- OLED_ShowHexNum(2, 11, *((__IO uint16_t *)(0x1FFFF7E8 + 0x02)), 4);
- OLED_ShowHexNum(3, 1, *((__IO uint32_t *)(0x1FFFF7E8 + 0x04)), 8);
- OLED_ShowHexNum(4, 1, *((__IO uint32_t *)(0x1FFFF7E8 + 0x08)), 8);
-
- while (1)
- {
-
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。