#include "stmflash.h" #include "delay.h" #include "stmflash.h" #define FLASH_SAVE_ADDR 0X0800E000 //设置FLASH 保存地址(必须为偶数,且其值要大于本代码所占用FLASH的大小+0X08000000) //解锁STM32的FLASH void STMFLASH_Unlock(void) { FLASH->KEYR=FLASH_KEY1;//写入解锁序列. FLASH->KEYR=FLASH_KEY2; } //flash上锁 void STMFLASH_Lock(void) { FLASH->CR|=1<<7;//上锁 } //得到FLASH状态 u8 STMFLASH_GetStatus(void) { u32 res; res=FLASH->SR; if(res&(1<<0))return 1; //忙 else if(res&(1<<2))return 2; //编程错误 else if(res&(1<<4))return 3; //写保护错误 return 0; //操作完成 } //等待操作完成 //time:要延时的长短 //返回值:状态. u8 STMFLASH_WaitDone(u16 time) { u8 res; do { res=STMFLASH_GetStatus(); if(res!=1)break;//非忙,无需等待了,直接退出. delay_us(1); time--; }while(time); if(time==0)res=0xff;//TIMEOUT return res; } //擦除页 //paddr:页地址 //返回值:执行情况 u8 STMFLASH_ErasePage(u32 paddr) { u8 res=0; res=STMFLASH_WaitDone(0X5FFF);//等待上次操作结束,>20ms if(res==0) { FLASH->CR|=1<<1;//页擦除 FLASH->AR=paddr;//设置页地址 FLASH->CR|=1<<6;//开始擦除 res=STMFLASH_WaitDone(0X5FFF);//等待操作结束,>20ms if(res!=1)//非忙 { FLASH->CR&=~(1<<1);//清除页擦除标志. } } return res; } //在FLASH指定地址写入半字 //faddr:指定地址(此地址必须为2的倍数!!) //dat:要写入的数据 //返回值:写入的情况 u8 STMFLASH_WriteHalfWord(u32 faddr, u16 dat) { u8 res; res=STMFLASH_WaitDone(0XFF); if(res==0)//OK { FLASH->CR|=1<<0;//编程使能 *(vu16*)faddr=dat;//写入数据 res=STMFLASH_WaitDone(0XFF);//等待操作完成 if(res!=1)//操作成功 { FLASH->CR&=~(1<<0);//清除PG位. } } return res; } //读取指定地址的半字(16位数据) //faddr:读地址 //返回值:对应数据. u16 STMFLASH_ReadHalfWord(u32 faddr) { return *(vu16*)faddr; } #if STM32_FLASH_WREN //如果使能了写 //不检查的写入 //WriteAddr:起始地址 //pBuffer:数据指针 //NumToWrite:半字(16位)数 void STMFLASH_Write_NoCheck(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite) { u16 i; for(i=0;i=(STM32_FLASH_BASE+1024*STM32_FLASH_SIZE)))return;//非法地址 STMFLASH_Unlock(); //解锁 offaddr=WriteAddr-STM32_FLASH_BASE; //实际偏移地址. secpos=offaddr/STM_SECTOR_SIZE; //扇区地址 0~127 for STM32F103RBT6 secoff=(offaddr%STM_SECTOR_SIZE)/2; //在扇区内的偏移(2个字节为基本单位.) secremain=STM_SECTOR_SIZE/2-secoff; //扇区剩余空间大小 if(NumToWrite<=secremain)secremain=NumToWrite;//不大于该扇区范围 while(1) { STMFLASH_Read(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);//读出整个扇区的内容 for(i=0;i(STM_SECTOR_SIZE/2))secremain=STM_SECTOR_SIZE/2;//下一个扇区还是写不完 else secremain=NumToWrite;//下一个扇区可以写完了 } }; STMFLASH_Lock();//上锁 } #endif //从指定地址开始读出指定长度的数据 //ReadAddr:起始地址 //pBuffer:数据指针 //NumToWrite:半字(16位)数 void STMFLASH_Read(u32 ReadAddr,u16 *pBuffer,u16 NumToRead) { u16 i; for(i=0;i