无名飞控的FLASH

在看无名的Flash之前先看一下如何操作Flash


STM32 FLASH操作步骤

1. FLASH解锁
在对 FLASH 进行写操作前必须先解锁,固件库函数实现很简单:

FLASH_Unlock();//解锁
2. 清除相关的标志位
FLASH_ClearFlag(FLASH_FLAG_BSY|FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);//清除标志位
3. 擦除函数

固件库提供三个 FLASH 擦除函数:

FLASH_Status FLASH_ErasePage(uint32_t Page_Address);
FLASH_Status FLASH_EraseAllPages(void); 
FLASH_Status FLASH_EraseOptionBytes(void);

这三个函数可以顾名思义了,非常简单。

4. 写操作函数

固件库提供了三个 FLASH 写函数:

FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data); 
FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data); 
FLASH_Status FLASH_ProgramOptionByteData(uint32_t Address, uint8_t Data);

顾名思义分别为: FLASH_ProgramWord 为 32 位字写入函数, 其他分别为 16 位半字写入和 8位字节写入函数。这里需要说明, 32 位字节写入实际上是写入的两次 16 位数据,写完第一次后地址+2。 写入 8 位实际也是占用的两个地址了,跟写入 16 位基本上没啥区别。

5. 锁定函数
在对 FLASH 写操作完成之后,我们要锁定 FLASH,使用的库函数是:

void FLASH_Lock(void);
而飞控里面在Parameter_Init函数里面调用了ReadFlashThreeFloat

定义:

uint8_t ReadFlashThreeFloat(uint32_t ReadAddress,
                         float *WriteData1,
                         float *WriteData2,
                         float *WriteData3)
{
    uint8_t buf[12];
    uint16_t i=0;
    uint8_t flag=0x00;
    ReadAddress = (uint32_t)STARTADDR + ReadAddress;
    *WriteData1=*(float *)(ReadAddress);
    *WriteData2=*(float *)(ReadAddress+4);
    *WriteData3=*(float *)(ReadAddress+8);
    FLASH_LockBank1();
    
    for(i=0;i<12;i++)//单字节数据
    {
        *(buf+i)=*(__IO uint8_t*) ReadAddress++;
    }
    if((buf[0]==0xff&&buf[1]==0xff&&buf[2]==0xff&&buf[3]==0xff))
       flag=flag|0x01;
    if((buf[4]==0xff&&buf[5]==0xff&&buf[6]==0xff&&buf[7]==0xff))
       flag=flag|0x02;
    if((buf[8]==0xff&&buf[9]==0xff&&buf[10]==0xff&&buf[11]==0xff))
       flag=flag|0x04;
    return flag;
} 
一次读三个字节,并将值赋给输入参数

对于函数:

Parameter_Flag Parameter_Read_Flag;

bool Parameter_Init(void)
{
    bool success=true; 
   /************加速度计零偏与标度值*******/
    Parameter_Read_Flag.accel_off=ReadFlashThreeFloat(Accel_Offset_Address,
                         &Accel_Offset_Read.x,
                         &Accel_Offset_Read.y,
                         &Accel_Offset_Read.z);
     
    Parameter_Read_Flag.accel_scale=ReadFlashThreeFloat(Accel_Scale_Address,
                         &Accel_Scale_Read.x,
                         &Accel_Scale_Read.y,
                         &Accel_Scale_Read.z);
    /************磁力计零偏****************/
    Parameter_Read_Flag.mag=ReadFlashThreeFloat(Mag_Offset_Address,
                         &Mag_Offset_Read.x,
                         &Mag_Offset_Read.y,
                         &Mag_Offset_Read.z);
    // sanity check scale
    if(ABS(Accel_Scale_Read.x-1.0f)>0.2f 
         || ABS(Accel_Scale_Read.y-1.0f)>0.2f 
           || ABS(Accel_Scale_Read.z-1.0f)>0.2f) 
    {
        success = false;
    }
    // sanity check offsets (3.5 is roughly 3/10th of a G, 5.0 is roughly half a G)
    if(ABS(Accel_Offset_Read.x) > 3.5f 
         || ABS(Accel_Offset_Read.y) > 3.5f 
           || ABS(Accel_Offset_Read.z) > 3.5f) 
    {
        success = false;
    }
    
   
   if(success==true
      &&Parameter_Read_Flag.accel_off!=0x07
       &&Parameter_Read_Flag.accel_scale!=0x07)//Flash内数据正常,更新加速度校正值
   {
    B[0]=Accel_Offset_Read.x*One_G_TO_Accel;
    B[1]=Accel_Offset_Read.y*One_G_TO_Accel;
    B[2]=Accel_Offset_Read.z*One_G_TO_Accel;
    K[0]=Accel_Scale_Read.x;
    K[1]=Accel_Scale_Read.y;
    K[2]=Accel_Scale_Read.z;            
   }
   /**********磁力计中心偏执获取************/
   if(Parameter_Read_Flag.mag!=0x07)
   {
   Mag_Offset[0]=(int16_t)(Mag_Offset_Read.x);
   Mag_Offset[1]=(int16_t)(Mag_Offset_Read.y);
   Mag_Offset[2]=(int16_t)(Mag_Offset_Read.z); 
   }
   return success;
}
它首先定义了一个结构体,

Parameter_Flag Parameter_Read_Flag;
结构体内部:

typedef struct 
{
uint8_t accel_off;
uint8_t accel_scale;
uint8_t mag;
}Parameter_Flag;
首先应有三个结构体定义:

Mag_Unit Mag_Offset_Read={
  0,0,0,
};
Acce_Unit Accel_Offset_Read={
  0,0,0,
};
Acce_Unit Accel_Scale_Read={
  0,0,0,
};

其中:typedef struct
{
 float x;
 float y;
 float z;
}Acce_Unit;类外一个类似

整个函数的过程就是将读取的数据赋给Mag_Offset_Read,Accel_Scale_Read,Accel_Offset_Read结构体里面,并返回是否读取到数据的标志

得到的数组B[3],K[3],Mag_Offset[3],





  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值