打印
[应用相关]

STM32:SPI-FLASH

[复制链接]
112|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tpgf|  楼主 | 2024-4-15 10:25 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
正文
W25Q64指令集





SPI硬件相关宏定义,bsp_spi.h

#define Dummy_Byte                              0xFF

#define W25X_WriteEnable                                0x06
#define W25X_WriteDisable                                0x04
#define W25X_ReadStatusReg1                                0x05
#define W25X_WriteStatusReg                                0x01
#define W25X_ReadData                                        0x03
#define W25X_FastReadData                                0x0B
#define W25X_FastReadDual                                0x3B
#define W25X_PageProgram                                0x02
#define W25X_BlockErase                                        0xD8
#define W25X_SectorErase                                0x20
#define W25X_ChipErase                          0xC7
#define W25X_PowerDown                                        0xB9
#define W25X_ReleasePowerDown                        0xAB
#define W25X_DeviceID                                        0xAB
#define W25X_ManufactDeviceID                       0x90
#define W25X_JedecDeviceID                                0x9F

#define FLASH_PAGE_SIZE                         256



读取Flash ID

uint32_t BSP_Flash_ID(void)
{
    uint32_t flash_id;
    BSP_SPIx_NSS_Enable;

    BSP_SPI_SendByte(W25X_JedecDeviceID);
    flash_id = BSP_SPI_ReceiveByte();
    flash_id <<= 8;
    flash_id |= BSP_SPI_ReceiveByte();
    flash_id <<= 8;
    flash_id |= BSP_SPI_ReceiveByte();

    BSP_SPIx_NSS_Disable;
    return flash_id;
}




读使能

void BSP_Flash_Write_Enable(void)
{
    BSP_SPIx_NSS_Enable;
    BSP_SPI_SendByte(W25X_WriteEnable);
    BSP_SPIx_NSS_Disable;
}


等待FLASH空闲状态

void BSP_Flash_WaitStandByState(void)
{
    uint8_t Flash_Status = 0;
    BSP_SPIx_NSS_Enable;
    BSP_SPI_SendByte(W25X_ReadStatusReg1);
    do{
        Flash_Status = BSP_SPI_ReceiveByte();
    }while((Flash_Status & 0x01) == SET);
    BSP_SPIx_NSS_Disable;
}


擦除扇区,需要注意Seator擦除操作需要输入地址对齐4KB

void BSP_Flash_EraseSector(uint32_t SectorAddr)
{
    BSP_Flash_Write_Enable();
    BSP_Flash_WaitStandByState();

    BSP_SPIx_NSS_Enable;
    BSP_SPI_SendByte(W25X_SectorErase);
    BSP_SPI_SendByte((SectorAddr & 0xff0000)>>16);
    BSP_SPI_SendByte((SectorAddr & 0xff00)>>8);
    BSP_SPI_SendByte(SectorAddr & 0xff);
    BSP_SPIx_NSS_Disable;

    BSP_Flash_WaitStandByState();
}


擦除块,需要注意Block擦除操作需要输入地址对齐64KB

void BSP_Flash_EraseBlock(uint32_t BlockAddr)
{
    BSP_Flash_Write_Enable();
    BSP_Flash_WaitStandByState();

    BSP_SPIx_NSS_Enable;
    BSP_SPI_SendByte(W25X_BlockErase);
    BSP_SPI_SendByte((BlockAddr & 0xff0000)>>16);
    BSP_SPI_SendByte((BlockAddr & 0xff00)>>8);
    BSP_SPI_SendByte(BlockAddr & 0xff);
    BSP_SPIx_NSS_Disable;

    BSP_Flash_WaitStandByState();
}



擦除芯片

void BSP_Flash_EraseChip(void)
{
    BSP_Flash_Write_Enable();
    BSP_Flash_WaitStandByState();

    BSP_SPIx_NSS_Enable;
    BSP_SPI_SendByte(W25X_ChipErase);
    BSP_SPIx_NSS_Disable;

    BSP_Flash_WaitStandByState();
}


页写入,Page写入支持的最大字节为256Byte,需要考虑

void BSP_Flash_PageWrite(uint8_t *pBuffer,uint32_t WriteAddr,uint16_t NumBytetoWrite)
{
    BSP_Flash_Write_Enable();
    BSP_Flash_WaitStandByState();

    BSP_SPIx_NSS_Enable;

   BSP_SPI_SendByte(W25X_PageProgram);

    BSP_SPI_SendByte((WriteAddr & 0xff0000)>>16);
    BSP_SPI_SendByte((WriteAddr & 0xff00)>>8);
    BSP_SPI_SendByte(WriteAddr & 0xff);

    if(NumBytetoWrite > FLASH_PAGE_SIZE)
    {
        NumBytetoWrite = FLASH_PAGE_SIZE;
        DEBUG_INFO("FLASH Page Program OverSize\r\n");
    }

    while(NumBytetoWrite--)
    {
        BSP_SPI_SendByte(*pBuffer);
        pBuffer++;
    }
    BSP_SPIx_NSS_Disable;
    BSP_Flash_WaitStandByState();
}



不定长字节写入,没有页写入的最大字节256Byte限制

void BSP_Flash_BufferWrite(uint8_t *pBuffer,uint32_t WriteAddr,uint16_t NumBytetoWrite)
{
    uint8_t NumofPage = 0,NumofSingle = 0,Addr = 0,Addr_Cnt = 0,Addr_Temp = 0;

    Addr = WriteAddr % FLASH_PAGE_SIZE;
    Addr_Cnt = FLASH_PAGE_SIZE - Addr;
    NumofSingle = NumBytetoWrite % FLASH_PAGE_SIZE;
    NumofPage = NumBytetoWrite / FLASH_PAGE_SIZE;

    if(Addr == 0){
        if(NumofPage == 0)
            BSP_Flash_PageWrite(pBuffer,WriteAddr,NumofSingle);
        else{
            while(NumofPage--){
                BSP_Flash_PageWrite(pBuffer,WriteAddr,FLASH_PAGE_SIZE);
                WriteAddr += FLASH_PAGE_SIZE;
                pBuffer += FLASH_PAGE_SIZE;
            }
            if(NumofSingle != 0)
                BSP_Flash_PageWrite(pBuffer,WriteAddr,NumofSingle);
        }   
    }
    else{
        if(NumofPage == 0){
            if(NumofSingle > Addr_Cnt){
                Addr_Temp = NumofSingle - Addr_Cnt;
                BSP_Flash_PageWrite(pBuffer,WriteAddr,Addr_Cnt);
                WriteAddr += Addr_Cnt;
                pBuffer += Addr_Cnt;

                BSP_Flash_PageWrite(pBuffer,WriteAddr,Addr_Temp);
            }
            else
                BSP_Flash_PageWrite(pBuffer,WriteAddr,NumBytetoWrite);
        }
        else{
            NumBytetoWrite -= Addr_Cnt;
            NumofPage = NumBytetoWrite  / EE_PAGE_SIZE;
            NumofSingle = NumBytetoWrite % EE_PAGE_SIZE;
            if(Addr_Cnt != 0){
                BSP_Flash_PageWrite(pBuffer,WriteAddr,Addr_Cnt);
                WriteAddr += Addr_Cnt;;
                pBuffer += Addr_Cnt;
            }
            while(NumofPage--){
                BSP_Flash_PageWrite(pBuffer,WriteAddr,Addr_Cnt);
                WriteAddr += FLASH_PAGE_SIZE;
                pBuffer += FLASH_PAGE_SIZE;

            }
            if(NumofSingle != 0)
                BSP_Flash_PageWrite(pBuffer,WriteAddr,NumofSingle);
        }
    }
}



上述代码主要分为以下几种情况。

写入的数据的首地址页对齐。
数据长度没有超过一页的大小(256Byte),则直接写入。
数据长度超过一页的大小(256Byte),先按页写入,再将多余的写入新的一页。
写入的数据的首地址并不是页对齐。
数据长度没有超过一页的大小(256Byte)
数据首地址距离页尾的空间不足以放下整个数据,则先补全该页,再将剩余的数据写到下一页。
数据首地址距离页尾的空间足以放下整个数据,则直接写入。
数据长度超过一页的大小(256Byte)
先补全该页,再按页写入,再将剩余的数据写到下一页。
void BSP_Flash_BufferRead(uint8_t *pBuffer,uint32_t ReadAddr,uint16_t NumBytetoRead)
{
    BSP_SPIx_NSS_Enable;

    BSP_SPI_SendByte(W25X_ReadData);

    BSP_SPI_SendByte((ReadAddr & 0xff0000)>>16);
    BSP_SPI_SendByte((ReadAddr & 0xff00)>>8);
    BSP_SPI_SendByte(ReadAddr & 0xff);


    while(NumBytetoRead--)
    {
        *pBuffer = BSP_SPI_ReceiveByte();
        pBuffer++;
    }

    BSP_SPIx_NSS_Disable;
}

————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/ZipingPan/article/details/137365086

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1362

主题

13992

帖子

8

粉丝