14、FLASH读写之四

因为关于STM32的Flash相关的知识点比较多,所以该内容的学习我们分为以下4个部分

1、RAM和ROM的一些基本概念 —— STM32学习笔记:FLASH读写之一

2、STM32的Flash寄存器及介绍 —— STM32学习笔记:FLASH读写之二

3、STM32的Flash读写相关函数 —— STM32学习笔记:FLASH读写之三

4、STM32的Flash自己编辑函数 —— STM32学习笔记:FLASH读写之

上一篇文章我们介绍了标准库函数中的一些Flash读写函数。这篇文章我们将自行编写一些关于Flash读写的函数。

目录

0x01、标识符常量参数与变量定义

0x02、从指定地址开始读出指定长度的数据

0x03、从指定地址开始写入指定长度的数据

0x04、源程序下载地址


0x01、标识符常量参数与变量定义

为了方便代码的移植,首先我们使用标识符常量来设定一些参数。我们还需要定义一个半字(16位元素)数组来存放从Flash中读取的数据

/* 用户根据自己所选的芯片设置 */
#define STM32_FLASH_SIZE 256            //所选STM32的FLASH容量大小(单位为K)

/* FLASH起始地址 */
#define STM32_FLASH_BASE 0x08000000     //STM32 FLASH的起始地址

/* 小容量和中容量产品每页1K字节(1024 Byte)、大容量每页2K字节(2048 Byte)*/
#if STM32_FLASH_SIZE < 256
#define STM_SECTOR_SIZE 1024
#else 
#define STM_SECTOR_SIZE 2048
#endif

/* 最多是2K字节 这里除以2是因为STM_SECTOR_SIZE是字节数,STMFLASH_BUF数组是半字数组 */
uint16_t  STMFLASH_BUF[STM_SECTOR_SIZE/2];  

0x02、从指定地址开始读出指定长度的数据

上一篇文章中我们自己定义了一个读取半字flash的函数uint16_t STMFLASH_ReadHalfWord(uint32_t faddr),这里我们利用该函数编写一个从指定地址读取指定长度数据的函数,以便日后使用。

函数名称:STMFLASH_ReadMultipleBytes

函数功能:从指定地址读取多个字节数据

     参数1:uint32_t ReadAddr        —> 从指定地址开始读出指定长度的数据

     参数2:uint16_t  *pBuffer          —> 数据指针

     参数3:uint16_t  NumToRead   —> 半字(16位)数

    返回值:无(通过参数2,传递参数来存储返回的数据)

/**
*@brief     从指定地址开始读出指定长度的数据
*@param     ReadAddr  : 起始地址
*           pBuffer   : 数据指针
*           NumToWrite: 半字(16位)数
*@return    无
*/
void STMFLASH_ReadMultipleBytes(uint32_t ReadAddr,uint16_t  *pBuffer,uint16_t  NumToRead)      
{
    uint16_t  i;
    for(i = 0;i < NumToRead;i++)
    {
        pBuffer[i] = STMFLASH_ReadHalfWord(ReadAddr);         // 读取2个字节.
        ReadAddr += 2;                                        // 偏移2个字节. 
    }
}

0x03、从指定地址开始写入指定长度的数据

首先我们定义一个无校验写Flash的函数,以供最终写函数调用

函数名称:STMFLASH_Write_NoCheck

函数功能:从指定地址开始写入指定长度的数据

     参数1:uint32_t WriteAddr        —> 起始地址(此地址必须为2的倍数!!)

     参数2:uint16_t  *pBuffer          —> 数据指针

     参数3:uint16_t  NumToWrite   —> 半字(16位)数(就是要写入的16位数据的个数.)

    返回值:无

/**
*@brief   无校验写入(该函数不校验Flash地址是否可写,是否需要擦除,所以不能直接用于写操作)
*@param   WriteAddr : 起始地址
*         pBuffer   : 数据指针
*         NumToWrite: 半字(16位)数   
*@return  无
*/
void STMFLASH_Write_NoCheck(uint32_t WriteAddr,uint16_t  *pBuffer,uint16_t  NumToWrite)   
{                    
    uint16_t  i;
    for(i = 0;i < NumToWrite;i++)
    {
        FLASH_ProgramHalfWord(WriteAddr,pBuffer[i]);
        WriteAddr += 2;                              // 地址增加2.
    }  
} 

函数名称:STMFLASH_WriteMultipleBytes

函数功能:从指定地址开始写入指定长度的数据

     参数1:uint32_t WriteAddr        —> 起始地址(此地址必须为2的倍数!!)

     参数2:uint16_t  *pBuffer          —> 数据指针

     参数3:uint16_t  NumToWrite   —> 半字(16位)数(就是要写入的16位数据的个数.)

    返回值:无

函数,不过该函数对写入地址是有要求的,必须保证以下两点:

1、该地址必须是用户代码区以外的地址。

2、该地址必须是 2 的倍数。STM32 FLASH 的要求,每次必须写入 16 位,如果你写的地址不是 2 的倍数,那么写入的数据,可能就不是写在你要写的地址了。

另外,该函数的STMFLASH_BUF 数组,也是根据所用 STM32 的 FLASH 容量来确定的,

/**
*@brief     从指定地址开始写入指定长度的数据
*@param     WriteAddr : 起始地址(此地址必须为2的倍数!!)
*           pBuffer   : 数据指针
*           NumToWrite: 半字(16位)数(就是要写入的16位数据的个数.)
*@return    无
*/
void STMFLASH_WriteMultipleBytes(uint32_t WriteAddr,uint16_t  *pBuffer,uint16_t  NumToWrite)
{
    uint32_t  PageAddr;                                                                                            // Flash页地址
    uint16_t  WordAddr;                                                                                            // 要写入的地址在Flash页中的位置(16位字计算)
    uint16_t  WordRemainder;                                                                                       // Flash页中的剩余地址(16位字计算)
    uint32_t  ShiftingAddr;                                                                                        // 去掉0X08000000后的地址
    uint16_t  i;    
    
    /* 当指定起始地址小于STM32_FLASH_BASE (0x0800000) 或者大于芯片本身的Flash容量时,写入地址无效,跳出函数 */
    if(WriteAddr < STM32_FLASH_BASE || (WriteAddr >= (STM32_FLASH_BASE + 1024 * STM32_FLASH_SIZE)))
    {
        return;                                                                                                    // 非法地址
    }
    FLASH_Unlock();                                                                                                // 解锁

    ShiftingAddr  = WriteAddr - STM32_FLASH_BASE;                                                                  // 实际偏移地址.要写入数据起始地址的位置
    PageAddr      =  ShiftingAddr / FLASH_PAGE_SIZE;                                                               // 要写入的地址所在的Flash页(0~256)
    WordAddr      = (ShiftingAddr % FLASH_PAGE_SIZE) / 2;                                                          // 在Flash页内的偏移(2个字节为基本单位.)
    WordRemainder = FLASH_PAGE_SIZE/2 - WordAddr;                                                                  // Flash页剩余空间大小
    if(NumToWrite <= WordRemainder)
    {
        WordRemainder = NumToWrite;                                                                                // 不大于该Flash页范围
    }

    while(1) 
    {
        STMFLASH_ReadMultipleBytes(PageAddr*FLASH_PAGE_SIZE + STM32_FLASH_BASE,STMFLASH_BUF,FLASH_PAGE_SIZE/2);    // 读出整个Flash页的内容存放到STMFLASH_BUF中
        
        /* 查验数据,看flash页是否需要擦除 */
        for(i = 0;i < WordRemainder;i++)                                                                           // 校验数据
        {
            if(STMFLASH_BUF[WordAddr + i] != 0XFFFF)
            {
                break;                                                                                             // 需要擦除
            }     
        }
        /* 如果要写入数据的Flash页面上,所有的字都等于0XFFFF,那么在上面的循环之后,i = WordRemainder*/
        if(i < WordRemainder)                                                                                      // 需要擦除
        {
            FLASH_ErasePage(PageAddr*FLASH_PAGE_SIZE + STM32_FLASH_BASE);                                      // 擦除这个Flash页
            for(i = 0;i < WordRemainder;i++)                                                                       // 复制
            {
                STMFLASH_BUF[i + WordAddr] = pBuffer[i];
            }
            STMFLASH_Write_NoCheck(PageAddr*FLASH_PAGE_SIZE + STM32_FLASH_BASE,STMFLASH_BUF,FLASH_PAGE_SIZE/2);    // 写入整个页
        }
        /* i = WordRemainder */
        else
        {
            STMFLASH_Write_NoCheck(WriteAddr,pBuffer,WordRemainder);                                               // 写已经擦除了的,直接写入扇区剩余区间. 
        }

        if(NumToWrite == WordRemainder)
        {
            break;                                                                                                 // 写入结束了
        }
        else                                                                                                       // 写入未结束
        {
            PageAddr++;                                                                                            // 页地址增加1
            WordAddr    = 0;                                                                                       // 偏移位置为0     
            pBuffer    += WordRemainder;                                                                           // 指针偏移
            WriteAddr  += WordRemainder*2;                                                                         // 写地址偏移(16位数据址,需要*2)
            NumToWrite -= WordRemainder;                                                                           // 字节(16位)数递减
            if(NumToWrite > (FLASH_PAGE_SIZE/2))
            {
                WordRemainder = FLASH_PAGE_SIZE/2;                                                                 // 下一个Flash页还是写不完
            }
            else WordRemainder = NumToWrite;                                                                       // 下一个Flash页可以写完了
        }    
    };  
    FLASH_Lock();                                                                                                  // 上锁
}

0x04、源程序下载地址

STM32Flash读写程序_stm32flashhal-硬件开发文档类资源-CSDN下载

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值