STM32F103FLASH进行跨页读写操作实验

 Flash的读写基本操作过程:

1.unlock  FLASH 解锁

2.擦除指定的页(查看工程空间分布,以防擦除程序本身)

3.写入数据

4.读出数据效验

5:注意FLASH_ProgramWord(uint32_t Address, uint32_t Data);  写入32位数据,4个字节,每页2048/4=512,地址每次+4写入读出

6:注意FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data);写入16为数据,2个字节,每页2048/2=1024地址每次+2写入读出,还需留意把32位数据强制转化为vu16*(地址)写入读出,简单表述就是把32位分成了两个16位分别写入.

7:注意定义数组和运行代码在RAM存储中的空间,占用空间过多,就会导致溢满提醒

u16 STMFLASH_BUF[STM_SECTOR_SIZE / 2];

u32 FLASH_BUFDATA[STM_SECTOR_SIZE];

uint32_t FLASH_DATASIZE[STM_SECTOR_SIZE/4];

单页32位数据写入

/*单页32位数据写入*/
int InternalFlsah_Test(void)
{
    uint32_t *p;
    uint32_t EraseCounter = 0x00;          //记录擦除的页数   
    uint32_t Address = 0x00;               //记录写入的地址
    uint32_t Data = 0x3210ABCD;            //记录写入的数据
    uint32_t NbrOfPage = 0x00;             //记录写入的页数

    FLASH_Status   FLASH_Status = FLASH_COMPLETE;     //记录擦除的结果
    TestStatus     MemoryProgramStatus   = PASSED;
     
    //解锁
    FLASH_Unlock();
    //计算要擦除的页数
    NbrOfPage = (WRITE_END_ADDR - WRITE_START_ADDR) / FLASH_PAGE_SIZE;
    //清楚所有标志位
    FLASH_ClearFlag(FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR | FLASH_FLAG_EOP);
    //按页擦除
    for(EraseCounter = 0; (EraseCounter < NbrOfPage) && (FLASH_Status == FLASH_COMPLETE);EraseCounter++)
    {
        FLASH_Status = FLASH_ErasePage(WRITE_START_ADDR + (FLASH_PAGE_SIZE * EraseCounter)); 
    }

    //向FLASH内部写入数据
    Address = WRITE_START_ADDR;
    while ((Address < WRITE_END_ADDR) && (FLASH_Status == FLASH_COMPLETE)) 
    {
        FLASH_Status = FLASH_ProgramWord(Address, Data);
        Address = Address + 4;
    }
    FLASH_Lock();

    //写入检查
    Address =  WRITE_START_ADDR;
    while((Address < WRITE_END_ADDR) && (MemoryProgramStatus != FAILED))
    {

        if((*(__IO uint32_t*)Address) != Data)
        {
            MemoryProgramStatus = FAILED;
        }
        Address +=4;
        
    }
    return MemoryProgramStatus;
    
}

跨页16位数据写入FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data)

//读取指定地址的半字(16位数据)
//faddr:读地址(此地址必须为2的倍数!!)
//返回值:对应数据.
u16 STM32FLASH_ReadHalfWord(u32 faddr)
{
    return *(vu16*)faddr;
}

//从指定地址开始读出指定长度的数据
//ReadAddr:起始地址
//pBuffer:数据指针
//NumToRead:半字(16位)数
void STMFLASH_Read(u32 ReadAddr,u16 *pBuffer,u16 NumToRead)
{
    u16 i;
    for(i=0;i<NumToRead;i++)
    {
        pBuffer[i]= STM32FLASH_ReadHalfWord(ReadAddr);
        ReadAddr += 2;
    }


}

//WriteAddr:起始地址
//pBuffer:数据指针
//NumToWrite:半字(16位)数   

void  STMFLASH_Write_NoCheck(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite)
{
    u16 i;
    for(i=0;i<NumToWrite;i++)
    {
        FLASH_ProgramHalfWord(WriteAddr,pBuffer[i]);
        WriteAddr+=2;
    }
}

//从指定地址开始写入指定长度的数据
//WriteAddr:起始地址(此地址必须为2的倍数!!)
//pBuffer:数据指针
//NumToWrite:半字(16位)数(就是要写入的16位数据的个数.)
void STMFLASH_Write(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite)
{
    
    u32  secpos;        //第几页
    u16  secoff;        //页内偏移地址
    u16  secremain;     //页内剩余地址
    u16  i;
    u32  offaddr;       //相对flash基地址0x08000000偏移了地址量
    if((WriteAddr < STM32_FLASJ_BASE) || (WriteAddr>=(STM32_FLASJ_BASE + 1024*STM32_FLASH_SIZE)))return; //非法地址
    //解锁
    FLASH_Unlock();

    offaddr = WriteAddr - STM32_FLASJ_BASE;      //flash基地址偏移了多少地址
    secpos = offaddr / STM_SECTOR_SIZE;          //所在起始页
    secoff = (offaddr % STM_SECTOR_SIZE) / 2;    //在该页内偏移地址 即是在第几个u16 数据上(2 是读取和写入的字节是u16)
    secremain = FLASH_PAGE_SIZE /2 - secoff;     //该页内剩余的空间大小
    if(NumToWrite <= secremain)secremain=NumToWrite;//写入的数据没超过当前页内剩余的空间
    while(1)
    {
        STMFLASH_Read(secpos*STM_SECTOR_SIZE+STM32_FLASJ_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);//读出整页
        for(i=0;i<secremain;i++)   //判断是否需要擦除
        {
            if(STMFLASH_BUF[secoff+i]!=0xFFFF)  break;
        }
        if(i<secremain)           //需要擦除
        {
            FLASH_ErasePage(secpos*STM_SECTOR_SIZE+STM32_FLASJ_BASE);
            for(i=0;i<secremain;i++)
            {
                STMFLASH_BUF[i+secoff] = pBuffer[i];
            } 
             STMFLASH_Write_NoCheck(secpos*STM_SECTOR_SIZE+STM32_FLASJ_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);
        }
        else //不需要擦除
       {
             STMFLASH_Write_NoCheck(WriteAddr,pBuffer,secremain);
       }
       if(NumToWrite == secremain) //没有跨页写入
       {
           break;//写入结束跳出循环
       }
       else  //有跨页写入,增加新页
       {
            secpos++;          //页地址加1
            secoff = 0;        //页内偏移地址为0 
            pBuffer+=secremain;//指针偏移
            WriteAddr+=secremain;//写地址偏移
            NumToWrite -= secremain;//剩余要写入的字节(16位)数递减
            if(NumToWrite>(STM_SECTOR_SIZE / 2))
            {
               secremain=STM_SECTOR_SIZE / 2;  //新页还是写不完
            }
            else
            {
                secremain = NumToWrite;    //新页可以写完了
            }

       }

    }     
      FLASH_Lock();       
} 

跨页32位写入数据_FLASH_ProgramWord(uint32_t Address, uint32_t Data)

void   ARMFLASH_READ(uint32_t Address,uint32_t *pData,uint32_t Flsah_Number)
{
     uint32_t i; 
     uint32_t *pz;
     for(i = 0; i<Flsah_Number;i++)
     {    
			pz = (uint32_t *)Address; 
            pData[i]  =  *pz;
            Address+=4;
     } 
}
void  Internal_FLASH(uint32_t Address,uint32_t *Data,uint32_t Number)
{
            u32 i ;
            uint32_t *p;
            uint32_t Page_setoff;    //页内偏移地址
            uint32_t Page_Residue;   //页内剩余地址
            uint32_t Page_Num;       //页数(第几页)
           // uint32_t Flash_setoff;   //相比较Flash偏移地址
            uint32_t Write_Address;
            Page_setoff =( (Address - STM32_FLASJ_BASE) %STM_SECTOR_SIZE)/4;
            Page_Residue =STM32_FLASH_SIZE - Page_setoff ;
            Page_Num  = (Address - STM32_FLASJ_BASE) / STM_SECTOR_SIZE;
            if(Address<STM32_FLASJ_BASE || Address > (STM_SECTOR_SIZE*STM32_FLASH_SIZE+STM32_FLASJ_BASE))return;
            FLASH_Unlock();
            if(Page_Residue > Number) Page_Residue = Number;
        while (1)
        {            
            ARMFLASH_READ(Page_Num*STM_SECTOR_SIZE+STM32_FLASJ_BASE ,FLASH_DATASIZE,STM_SECTOR_SIZE/4);
			for ( i = 0; i < Page_Residue; i++)
			{
				if(FLASH_DATASIZE[Page_setoff+i]!=0xFFFF)
				{
					break;
				}
           }    
				if(i<Page_Residue)
				{    
					FLASH_ErasePage(Page_Num*STM_SECTOR_SIZE+STM32_FLASJ_BASE );
					Write_Address = Page_Num*STM_SECTOR_SIZE+STM32_FLASJ_BASE; 
					for(i=0;i<Page_Residue;i++)
					{   
						FLASH_ProgramWord(Write_Address,Data[i]);
						p = (uint32_t *)Write_Address;
						Write_Address+=4 ;
																										 
					}
				}
				else
				{
                    for(i=0;i<Page_Residue;i++)
					 { 
                         Write_Address = Page_Num*STM_SECTOR_SIZE+STM32_FLASJ_BASE;
                         FLASH_ProgramWord(Address,Data[i]);
                         Write_Address+=4;   
                     }
				}
                if(Number == Page_Residue)
                {
                    break;
                }
                else
                {
                    Page_Num++;
                    Page_setoff = 0;
                    Data += Page_Residue;
                    Address += Page_Residue; 
                    Number -= Page_Residue;
                    if(Number>(STM_SECTOR_SIZE/4))
                    {
                        Page_Residue = STM_SECTOR_SIZE/4;   //新页未完
                    }
                    else
                    {
                        Page_Residue = Number;            //新页写完
                    }                      
                }
        }					
	FLASH_Lock();
    
				
}

主程序

u32  flash_rx_buff[5000];//读取flash内容存放到该数组
u32  flash_rx_len =5000;
u32  flash_tx_buff[5000];//读取flash内容存放到该数组
u32  flash_tx_len =5000;

u16  flash1_rx_buff[5000];//读取flash内容存放到该数组
u16  flash1_rx_len = 5000;
u16  flash1_tx_buff[5000];//读取flash内容存放到该数组
u16  flash1_tx_len = 5000;

int main(void)
{     
	        uint32_t *p;
	        u32 x = 0x01;
	        u32  t = 0;
		    uint32_t Address123;
			delay_init();	    	 //延时函数初始化	  
			NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	 //设置中断优先级组
			uart_init(115200);	 	//串口初始化为115200	 	
			for(t=0;t<flash_tx_len;t++)
			{  					
					flash_tx_buff[t] = x; 
					x++;
			}		
			Internal_FLASH(WRITE_START_ADDR1,flash_tx_buff,flash_tx_len);
			Address123 =WRITE_START_ADDR1;
			for(t=0;t<flash_tx_len;t++)
			{				
				p = (uint32_t *)Address123;
				Address123+=4;
				printf("%0x: ",*p);
			}
		while(1)
		{     
			    	
	  }
}

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值