FLASH简介STM32F1系列的Flash包含程序存储器、系统存储器和选项字节三个部分通过闪存存储器接口外设可以对程序存储器和选项字节进行擦除和编程读写Flash的用途利用程序存储器的剩余空间来保存掉电不丢失的用户数据通过在程序中编程IAP实现程序的自我更新**在线编程In-Circuit Programming ICP**用于更新程序存储器的全部内容它通过JTAG、SWD协议或系统加载程序Bootloader下载程序**在程序中编程In-Application ProgrammingIAP**可以使用对微控制器支持的任意一种通信接口下载程序FLASH基本结构FLASH解锁闪存存储器接口FPEC有三个键值RDPRT键 0x0000 00A5KEY1 0x4567 0123KEY2 0xCDEFv89AB解锁复位后FPEC被保护不能写入FLASH_CR在FLASH_KEYR先写入KEY1再写入KEY2解锁错误的操作序列会在下次复位之前锁死FPEC和FLASH_CR加锁设置FLASH_CR中的LOCK位锁住FPEC和FLASH_CR使用指针访问存储器程序存储器全擦除程序存储器页擦除程序存储器写入选项字节RDP写入RDPRT0x0000 00A5后解除读保护USER配置硬件看门狗和进入停机/待机模式是否产生复位Data0/1用户可自定义使用WrP0/1/2/3配置写保护每一个位对应保护4个存储页中容量nRPD与RDP互为反码写入时由硬件自动完成选项字节擦除检查FLASH_SR的BSY位以确认没有其他正在进行的闪存操作解锁FLASH_CR的OPTWRE位设置FLASH_CR的OPTER位为1设置FLASH_CR的STRT位为1等待BSY位变为0读出被擦除的选项字节并做验证选项字节编程检查FLASH_SR的BSY位以确认没有其他正在进行的编程操作解锁FLASH_CR的OPTWRE位设置FLASH_CR的OPTPG位为1写入要编程的半字到指定的地址等待BSY位变为0读出写入的地址并验证数据器件电子签名电子签名存放在闪存存储器模块的系统存储区域包含的芯片识别信息再出厂时编写不可更改使用指针读指定地址下的存储器可以获取电子签名闪存容量寄存器基地址0x1FFF F7E0大小16位产品唯一身份标识寄存器基地址0x1FFF F7E8大小96位读写内部FLASH两个底层模块MyFLASH实现对闪存的三个基本操作读取、擦除和编程Store实现参数数据的读写和存储管理// MyFLASH.c#includestm32f10x.h// Device header// FLASH读取字uint32_tMyFLASH_ReadWord(uint32_tAddress){return*((__IOuint32_t*)(Address));}// FLASH读取半字uint16_tMyFLASH_ReadHalfWord(uint32_tAddress){return*((__IOuint16_t*)(Address));}// FLASH读取字节uint8_tMyFLASH_ReadByte(uint32_tAddress){return*((__IOuint8_t*)(Address));}// FLASH全擦除voidMyFLASH_EraseAllPages(void){// 先解锁再擦除最后上锁FLASH_Unlock();FLASH_EraseAllPages();FLASH_Lock();}// FLASH擦除页voidMyFLASH_ErasePage(uint32_tPage_Address){// 先解锁再擦除最后上锁FLASH_Unlock();FLASH_ErasePage(Page_Address);FLASH_Lock();}// 页编程页写入写入字voidMyFLASH_ProgramWord(uint32_tAddress,uint32_tData){FLASH_Unlock();FLASH_ProgramWord(Address,Data);FLASH_Lock();}// 页编程页写入写入半字voidMyFLASH_ProgramHalfWord(uint32_tAddress,uint16_tData){FLASH_Unlock();FLASH_ProgramHalfWord(Address,Data);FLASH_Lock();}// 写入字节操作比较麻烦暂时不用实现// Store.c#includestm32f10x.h// Device header#includeMyFLASH.h#defineSTORE_START_ADDRESS0x0800FC00#defineSTORE_COUNT512uint16_tStore_Data[STORE_COUNT];voidStore_Init(void){// 使用FLASH最后一页第一个半字做标志位如果不是0xA5A5说明是第一次使用if(MyFLASH_ReadHalfWord(STORE_START_ADDRESS)!0xA5A5){MyFLASH_ErasePage(STORE_START_ADDRESS);MyFLASH_ProgramHalfWord(STORE_START_ADDRESS,0xA5A5);for(uint16_ti1;iSTORE_COUNT;i){MyFLASH_ProgramHalfWord(STORE_START_ADDRESSi*2,0x0000);}}// 把闪存备份的数据恢复到SRAM里for(uint16_ti0;iSTORE_COUNT;i){Store_Data[i]MyFLASH_ReadHalfWord(STORE_START_ADDRESSi*2);}}voidStore_Save(void){MyFLASH_ErasePage(STORE_START_ADDRESS);// 把闪存备份的数据恢复到SRAM里for(uint16_ti0;iSTORE_COUNT;i){MyFLASH_ProgramHalfWord(STORE_START_ADDRESSi*2,Store_Data[i]);}}voidStore_Clear(void){for(uint16_ti1;iSTORE_COUNT;i){Store_Data[i]0x0000;}Store_Save();}// main.c#includestm32f10x.h// Device header#includeOLED_Software.h#includeStore.h#includeButton.huint8_tButtonVal1;uint8_tButtonVal2;intmain(void){OLED_Init();Button_Init();Store_Init();OLED_ShowString(1,1,Flag:);OLED_ShowString(2,1,Data:);while(1){ButtonVal1Button_Read(Pin_11);ButtonVal2Button_Read(Pin_12);if(ButtonVal11){Store_Data[1];Store_Data[2]2;Store_Data[3]3;Store_Data[4]4;Store_Save();}if(ButtonVal21){Store_Clear();}OLED_ShowHexNum(1,6,Store_Data[0],4);OLED_ShowHexNum(3,1,Store_Data[1],4);OLED_ShowHexNum(3,6,Store_Data[2],4);OLED_ShowHexNum(4,1,Store_Data[3],4);OLED_ShowHexNum(4,6,Store_Data[4],4);}}读取芯片ID#includestm32f10x.h// Device header#includeOLED_Software.hintmain(void){OLED_Init();OLED_ShowString(1,1,F_Size:);OLED_ShowHexNum(1,8,*((__IOuint16_t*)(0x1FFFF7E0)),4);OLED_ShowString(2,1,U_ID:);OLED_ShowHexNum(2,6,*((__IOuint16_t*)(0x1FFFF7E8)),4);OLED_ShowHexNum(2,11,*((__IOuint16_t*)(0x1FFFF7E80x02)),4);OLED_ShowHexNum(3,1,*((__IOuint32_t*)(0x1FFFF7E80x04)),8);OLED_ShowHexNum(4,1,*((__IOuint32_t*)(0x1FFFF7E80x08)),8);while(1){}}
[STM32]Day15读写FLASH+读取ID
发布时间:2026/6/12 19:37:28
FLASH简介STM32F1系列的Flash包含程序存储器、系统存储器和选项字节三个部分通过闪存存储器接口外设可以对程序存储器和选项字节进行擦除和编程读写Flash的用途利用程序存储器的剩余空间来保存掉电不丢失的用户数据通过在程序中编程IAP实现程序的自我更新**在线编程In-Circuit Programming ICP**用于更新程序存储器的全部内容它通过JTAG、SWD协议或系统加载程序Bootloader下载程序**在程序中编程In-Application ProgrammingIAP**可以使用对微控制器支持的任意一种通信接口下载程序FLASH基本结构FLASH解锁闪存存储器接口FPEC有三个键值RDPRT键 0x0000 00A5KEY1 0x4567 0123KEY2 0xCDEFv89AB解锁复位后FPEC被保护不能写入FLASH_CR在FLASH_KEYR先写入KEY1再写入KEY2解锁错误的操作序列会在下次复位之前锁死FPEC和FLASH_CR加锁设置FLASH_CR中的LOCK位锁住FPEC和FLASH_CR使用指针访问存储器程序存储器全擦除程序存储器页擦除程序存储器写入选项字节RDP写入RDPRT0x0000 00A5后解除读保护USER配置硬件看门狗和进入停机/待机模式是否产生复位Data0/1用户可自定义使用WrP0/1/2/3配置写保护每一个位对应保护4个存储页中容量nRPD与RDP互为反码写入时由硬件自动完成选项字节擦除检查FLASH_SR的BSY位以确认没有其他正在进行的闪存操作解锁FLASH_CR的OPTWRE位设置FLASH_CR的OPTER位为1设置FLASH_CR的STRT位为1等待BSY位变为0读出被擦除的选项字节并做验证选项字节编程检查FLASH_SR的BSY位以确认没有其他正在进行的编程操作解锁FLASH_CR的OPTWRE位设置FLASH_CR的OPTPG位为1写入要编程的半字到指定的地址等待BSY位变为0读出写入的地址并验证数据器件电子签名电子签名存放在闪存存储器模块的系统存储区域包含的芯片识别信息再出厂时编写不可更改使用指针读指定地址下的存储器可以获取电子签名闪存容量寄存器基地址0x1FFF F7E0大小16位产品唯一身份标识寄存器基地址0x1FFF F7E8大小96位读写内部FLASH两个底层模块MyFLASH实现对闪存的三个基本操作读取、擦除和编程Store实现参数数据的读写和存储管理// MyFLASH.c#includestm32f10x.h// Device header// FLASH读取字uint32_tMyFLASH_ReadWord(uint32_tAddress){return*((__IOuint32_t*)(Address));}// FLASH读取半字uint16_tMyFLASH_ReadHalfWord(uint32_tAddress){return*((__IOuint16_t*)(Address));}// FLASH读取字节uint8_tMyFLASH_ReadByte(uint32_tAddress){return*((__IOuint8_t*)(Address));}// FLASH全擦除voidMyFLASH_EraseAllPages(void){// 先解锁再擦除最后上锁FLASH_Unlock();FLASH_EraseAllPages();FLASH_Lock();}// FLASH擦除页voidMyFLASH_ErasePage(uint32_tPage_Address){// 先解锁再擦除最后上锁FLASH_Unlock();FLASH_ErasePage(Page_Address);FLASH_Lock();}// 页编程页写入写入字voidMyFLASH_ProgramWord(uint32_tAddress,uint32_tData){FLASH_Unlock();FLASH_ProgramWord(Address,Data);FLASH_Lock();}// 页编程页写入写入半字voidMyFLASH_ProgramHalfWord(uint32_tAddress,uint16_tData){FLASH_Unlock();FLASH_ProgramHalfWord(Address,Data);FLASH_Lock();}// 写入字节操作比较麻烦暂时不用实现// Store.c#includestm32f10x.h// Device header#includeMyFLASH.h#defineSTORE_START_ADDRESS0x0800FC00#defineSTORE_COUNT512uint16_tStore_Data[STORE_COUNT];voidStore_Init(void){// 使用FLASH最后一页第一个半字做标志位如果不是0xA5A5说明是第一次使用if(MyFLASH_ReadHalfWord(STORE_START_ADDRESS)!0xA5A5){MyFLASH_ErasePage(STORE_START_ADDRESS);MyFLASH_ProgramHalfWord(STORE_START_ADDRESS,0xA5A5);for(uint16_ti1;iSTORE_COUNT;i){MyFLASH_ProgramHalfWord(STORE_START_ADDRESSi*2,0x0000);}}// 把闪存备份的数据恢复到SRAM里for(uint16_ti0;iSTORE_COUNT;i){Store_Data[i]MyFLASH_ReadHalfWord(STORE_START_ADDRESSi*2);}}voidStore_Save(void){MyFLASH_ErasePage(STORE_START_ADDRESS);// 把闪存备份的数据恢复到SRAM里for(uint16_ti0;iSTORE_COUNT;i){MyFLASH_ProgramHalfWord(STORE_START_ADDRESSi*2,Store_Data[i]);}}voidStore_Clear(void){for(uint16_ti1;iSTORE_COUNT;i){Store_Data[i]0x0000;}Store_Save();}// main.c#includestm32f10x.h// Device header#includeOLED_Software.h#includeStore.h#includeButton.huint8_tButtonVal1;uint8_tButtonVal2;intmain(void){OLED_Init();Button_Init();Store_Init();OLED_ShowString(1,1,Flag:);OLED_ShowString(2,1,Data:);while(1){ButtonVal1Button_Read(Pin_11);ButtonVal2Button_Read(Pin_12);if(ButtonVal11){Store_Data[1];Store_Data[2]2;Store_Data[3]3;Store_Data[4]4;Store_Save();}if(ButtonVal21){Store_Clear();}OLED_ShowHexNum(1,6,Store_Data[0],4);OLED_ShowHexNum(3,1,Store_Data[1],4);OLED_ShowHexNum(3,6,Store_Data[2],4);OLED_ShowHexNum(4,1,Store_Data[3],4);OLED_ShowHexNum(4,6,Store_Data[4],4);}}读取芯片ID#includestm32f10x.h// Device header#includeOLED_Software.hintmain(void){OLED_Init();OLED_ShowString(1,1,F_Size:);OLED_ShowHexNum(1,8,*((__IOuint16_t*)(0x1FFFF7E0)),4);OLED_ShowString(2,1,U_ID:);OLED_ShowHexNum(2,6,*((__IOuint16_t*)(0x1FFFF7E8)),4);OLED_ShowHexNum(2,11,*((__IOuint16_t*)(0x1FFFF7E80x02)),4);OLED_ShowHexNum(3,1,*((__IOuint32_t*)(0x1FFFF7E80x04)),8);OLED_ShowHexNum(4,1,*((__IOuint32_t*)(0x1FFFF7E80x08)),8);while(1){}}