STM32中flash的读写详解

一:对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;
    }
}