一:对STM32内部FLASH写进行编程操做,须要遵循如下流程: 1.FLASH解锁 2.清除相关标志位 3.擦除FLASH(先擦除后写入的缘由是为了工业上制做方便,即物理实现方便) 4.写入FLASH 5.锁定FLASH (1)获取状态:FLASH_Status FLASH_GetStatus(void); 返回值是经过枚举类型定义的。 typedef enum { FLASH_BUSY = 1, //忙 FLASH_ERROR_PG, //编程错误 FLASH_ERROR_WRP, //写保护错误 FLASH_COMPLETE, //操做完成 FLASH_TIMEOUT //操做超时 }FLASH_Status; (2)FLASH_Unlock();//解锁函数(在对flash进行写操做前必须解锁) (3)FLASH_ClearFlag();//清除全部已有标志 (4)擦除函数有3个: FLASH_Status FLASH_ErasePage(uint32_t Page_Address); FLASH_Status FLASH_EraseAllPages(void); FLASH_Status FLASH_EraseOptionBytes(void); (5)写函数: FLASHStatus FLASH_ProgramWord(uint32_t Address,uint32_t Data);//32位字写入函数 FLASHStatus FLASH_ProgramHalfWord(uint32_t Address,uint32_t Data);//16位半字写入 FLASHStatus FLASH_ProgramOptionByteData(uint32_t Address,uint32_t Data);//用户字节写入 int write_flash(u32 StartAddr,u16 *buf,u16 len) { volatile FLASH_Status FLASHStatus; u32 FlashAddr; len=(len+1)/2; FLASH_Unlock();//1.解锁函数(在对flash进行写操做前必须解锁) FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPERR);//2.清除全部已有标志 FlashAddr=StartAddr; FLASH_ErasePage(StartAddr);//3.擦除一个flash页面 while(len--) { //FLASH_ProgramHalfWord为写入函数,返回值是flash的状态(5种) FLASHStatus = FLASH_ProgramHalfWord(FlashAddr,*buf++); if (FLASHStatus != FLASH_COMPLETE) //FLASH_COMPLETE表示闪存完成 { //printf("FLSH :Error %08X\n\r",FLASHStatus); return -1; } FlashAddr += 2; } FLASH_Lock(); return 0; } 二:FLASH 读取方法 *(uint32_t *)0x8000000;//读一个字 *(uint8_t *)0x8000000;//读一个字节; *(uint16_t *)0x8000000;//读半字; 举例: uint8_t data; data = *(uint8_t *)0x8000000;//就是读取FLASH中地址0x8000000处的数据 int read_flash(u32 StartAddr,u32 *buf,u16 len) //一次读一个字4字节 { len=(len+3)/4; while(len--) { *buf=*(__IO uint32_t *)StartAddr; StartAddr=StartAddr+4; buf++; } return 0; } 三:几个有用的子函数 /* 功能:向指定地址写入数据 参数说明:addr: 写入的FLASH页的地址 p: 被写入变量的地址(数组中的必须是uint8_t类型,元素个数必须是偶数) Byte_Num: 被写入变量的字节数(必须是偶数) */ void FLASH_WriteByte(uint32_t addr , uint8_t *p , uint16_t Byte_Num) { uint32_t HalfWord; Byte_Num = Byte_Num/2; FLASH_Unlock(); FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR); FLASH_ErasePage(addr); while(Byte_Num --) { HalfWord=*(p++); HalfWord|=*(p++)<<8; FLASH_ProgramHalfWord(addr, HalfWord); addr += 2; } FLASH_Lock(); } 例: uint8_t data[100]; FLASH_WriteByte(0x8000000 , data , 100);/*数组data的数据被写入FLASH中*/ /* 功能:从指定地址读取数据 参数说明:addr 从FLASH中读取的地址 p 读取后要存入变量的地址(数组中的必须是uint8_t类型) Byte_Num 要读出的字节数 */ void FLASH_ReadByte(uint32_t addr , uint8_t *p , uint16_t Byte_Num) { while(Byte_Num--) { *(p++)=*((uint8_t*)addr++); } } 例: uint8_t data[101]; FLASH_ReadByte(0x8000001 , data , 101);/*FLASH中的数据被读入数组data中*/
hardware_conf.h中: //64 flash #define ADDRESS_START_ADDR ((u32)0x0800EC00)//59:存储域名和端口号 #define TIME_START_ADDR ((u32)0x0800F000)//60:存储时间 #define KEYS_START_ADDR ((u32)0x0800F400)//61:存储各类key #define MACHINEID_START_ADDR ((u32)0x0800F800)//62:存储机器码 #define VERSION_START_ADDR ((u32)0x0800FC00)//63:存储版本号 main()中: //获取flash内容 void getFlash() { /*读取机器码*/ u8 machineId[19]=""; read_flash(MACHINEID_START_ADDR, (u32 *) machineId, 19); strncpy(MachineID_Default, machineId, 18); /*读取时间*/ u8 times[20]=""; read_flash(TIME_START_ADDR, (u32 *) times, 20); char timeKey[2]=""; strncpy(timeKey, times, 1); /*读取keys*/ u8 out_data[220]; read_flash(KEYS_START_ADDR, (u32 *) out_data, 220); } //写各类key到flash int getAllMessage() { char in_data[220]; //下面是falsh须要存储的变量 sprintf(in_data, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s",isFisrt,community_code,address,swipe,code_overtime,myKey1,Private_Key,check_pw); if(strlen(in_data)==96&&in_data[0]=='N' &&in_data[1]=='\n'&&in_data[63]=='\n'&&in_data[65]=='\n'&&in_data[69]=='\n'&&in_data[75]=='\n'&&in_data[82]=='\n'&&in_data[89]=='\n') { write_flash(KEYS_START_ADDR, (u16 *) in_data, 220); ACCLOG("write keys success\n"); return 1; }else{ ACCLOG("write keys fail...\n"); return 0; } }