加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

stm32 SPI-FLASH W25Q64

发布时间:2020-12-15 19:52:49 所属栏目:百科 来源:网络整理
导读:The W25Q64BV array is organized into 32,768 programmable pages of 256-bytes each. Up to 256 bytes can be programmed at a time. Pages can be erased in groups of 16 (sector erase),groups of 128 (32KB block erase),groups of 256 (64KB block er

The W25Q64BV array is organized into 32,768 programmable pages of 256-bytes each. Up to 256 bytes can be programmed at a time. Pages can be erased in groups of 16 (sector erase),groups of 128 (32KB block erase),groups of 256 (64KB block erase) or the entire chip (chip erase)

BUSY is a read only bit in the status register (S0) that is set to a 1 state when the device is executing a Page Program,Sector Erase,Block Erase,Chip Erase or Write Status Register instruction

W25Q64

1

2

3

SPI配置步骤

1.使能SPI时钟
2.使能GPIO端口时钟
3.初始化GPIO,配置引脚模式
4.初始化SPI
5.使能SPI
6.SPI读写数据
7.查看SPI传输状态

举例

1


2


3

1


2

3

typedef struct
{
    uint16_t SPI_Direction;
    uint16_t SPI_Mode; 
    uint16_t SPI_DataSize; //数据帧格式
    uint16_t SPI_CPOL; //时钟极性
    uint16_t SPI_CPHA; //时钟相位
    uint16_t SPI_NSS; //软件从设备管理
    uint16_t SPI_BaudRatePrescaler; //波特率控制
    uint16_t SPI_FirstBit; //帧格式 
    uint16_t SPI_CRCPolynomial; //CRC多项式寄存器
}SPI_InitTypeDef;

#define EN25X_WriteEnable 0x06
#define EN25X_WriteDisable 0x04 
#define EN25X_ReadStatusReg 0x05 
#define EN25X_WriteStatusReg 0x01 
#define EN25X_ReadData 0x03 
#define EN25X_FastReadData 0x0B 
#define EN25X_FastReadDual 0x3B 
#define EN25X_PageProgram 0x02 
#define EN25X_BlockErase 0xD8 
#define EN25X_SectorErase 0x20 
#define EN25X_ChipErase 0xC7 
#define EN25X_PowerDown 0xB9 
#define EN25X_Continue_Read 0xFF 
#define EN25X_ReleasePowerDown 0xAB 
#define EN25X_DeviceID 0xAB 
#define EN25X_ManufactDeviceID 0x90 
#define EN25X_JedecDeviceID 0x9F 

void SPI_init()
{
    GPIO_InitTypeDef gpio = 
    {
        GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15,GPIO_Speed_50MHz,GPIO_Mode_AF_PP
    };  

    SPI_InitTypeDef spi = 
    {
        SPI_Direction_2Lines_FullDuplex,SPI_Mode_Master,//0x0104
        SPI_DataSize_8b,SPI_CPOL_High,SPI_CPHA_2Edge,SPI_NSS_Soft,SPI_BaudRatePrescaler_256,SPI_FirstBit_MSB,7
    };

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE); //使能SPI时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //使能GPIO端口时钟

    GPIO_Init(GPIOB,&gpio); //初始化GPIO,配置引脚模式

    SPI_Init(SPI2,&spi); //初始化SPI

    SPI_Cmd(SPI2,ENABLE); //使能SPI
}

void SPI2_SetSpeed(u8 rate)
{
    SPI2->CR1 &= 0xFFC7;
    SPI2->CR1 |= rate;
    SPI_Cmd(SPI2,ENABLE);
} 

void EN25Q64_init()
{
    GPIO_InitTypeDef gpiob = 
    {
        GPIO_Pin_12,GPIO_Mode_Out_PP
    };  

    GPIO_InitTypeDef gpiog13 = 
    {
        GPIO_Pin_13,GPIO_Mode_Out_PP
    };  

    GPIO_InitTypeDef gpiog14 = 
    {
        GPIO_Pin_13,GPIO_Mode_Out_PP
    };

    GPIO_InitTypeDef gpiof = 
    {
        GPIO_Pin_9,GPIO_Mode_Out_PP
    };  

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOG | RCC_APB2Periph_GPIOF,ENABLE);

    GPIO_Init(GPIOB,&gpiob);
    SPI2_NSS = 1; //以太网模块片选(拉高,防止干扰)

    GPIO_Init(GPIOG,&gpiog13);
    FLASH_CS = 1; //FLASH片选

    GPIO_Init(GPIOG,&gpiog14);
    SD_CS = 1; //SD卡模块片选

    GPIO_Init(GPIOF,&gpiof);
    TUB_4 = 1; //NRF24L01模块片选

    SPI_init();
}   

u8 SPI_read_write(u16 d) //SPI读写数据
{
    while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_TXE) != SET);

    SPI_I2S_SendData(SPI2,d);

    while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_RXNE) != SET);

    return SPI_I2S_ReceiveData(SPI2);
}

u16 EN25Q64_read_id()
{
    u16 r;

    FLASH_CS = 0;

    SPI_read_write(EN25X_ManufactDeviceID);
    SPI_read_write(0); //dummy
    SPI_read_write(0);
    SPI_read_write(0);

    r = SPI_read_write(EN25X_Continue_Read) << 8;
    r = SPI_read_write(EN25X_Continue_Read);

    FLASH_CS = 1;

    return r;
}

u8 EN25Q64_read_status()
{
    u8 r;

    FLASH_CS = 0;

    SPI_read_write(EN25X_ReadStatusReg);
    r = SPI_read_write(EN25X_Continue_Read);

    FLASH_CS = 1;

    return r;
}

void EN25Q64_read(u8 *buf,u32 addr,u16 num)
{
    u16 i = 0;

    FLASH_CS = 0;

    SPI_read_write(EN25X_ReadData); 
    SPI_read_write((u8)(addr) >> 16); //24bit地址
    SPI_read_write((u8)(addr) >> 8);
    SPI_read_write((u8)addr);

    for(i = 0; i < num; i++)
    {
        buf[i] = SPI_read_write(EN25X_Continue_Read);
    }

    FLASH_CS = 1;
}

void EN25Q64_write_enable()
{   
    FLASH_CS = 0;

    SPI_read_write(EN25X_WriteEnable);

    FLASH_CS = 1;
}

void EN25Q64_write_disable()
{   
    FLASH_CS = 0;

    SPI_read_write(EN25X_WriteEnable);

    FLASH_CS = 1;
}

void EN25Q64_write_status(u8 s)
{   
    FLASH_CS = 0;

    SPI_read_write(EN25X_WriteDisable);
    SPI_read_write(s);

    FLASH_CS = 1;
}

void EN25Q64_is_busy()
{
    while((EN25Q64_read_status() & 0x01) == 0x01); //BUSY
}

void EN25Q64_write_page(u8 *buf,u16 num) //页写
{   
    u16 i = 0;

    EN25Q64_write_enable();

    FLASH_CS = 0;

    SPI_read_write(EN25X_PageProgram);  //Page Program
    SPI_read_write(addr >> 16);
    SPI_read_write(addr >> 8);
    SPI_read_write(addr);

    for(i = 0; i < num; i++)
    {
        SPI_read_write(buf[i]);
    }

    FLASH_CS = 1;

    EN25Q64_is_busy();
}

void EN25Q64_write_nocheck(u8 *buf,u16 num)
{
    u8 *b = buf;
    u32 a = addr;
    u16 n = num;

    n = 256 - (num % 256); //写满一页

    while(1)
    {   
        EN25Q64_write_page(b,a,n);

        if(n == num) 
        {
            break;
        }

        b += n;
        a += n;
        num -= n;

        if(num > 256) 
        {
            n = 256;
        }
        else
        {
            n = num;
        }
    }
}

void EN25Q64_sector_erase(u32 a)
{
    EN25Q64_write_enable();
    EN25Q64_is_busy();

    FLASH_CS = 0;

    SPI_read_write(EN25X_SectorErase);  
    SPI_read_write((u8)a >> 16);    
    SPI_read_write((u8)a >> 8);     
    SPI_read_write(a);      

    FLASH_CS = 1;

    EN25Q64_is_busy();
}

u8 EN25QXX_BUF[4096];
void EN25Q64_write(u8 *buf,u16 num)
{
    u16 i;
    u32 pos;
    u16 offset;
    u16 n;
    u8 *b = buf;

    pos = addr / 4096; //扇区位置
    offset = addr % 4096;
    n = 4096 - offset ; //写满扇区

    if(num <= n)
    {
        n = num;
    }

    while(1) 
    {
        EN25Q64_read(EN25QXX_BUF,pos * 4096,4096); //读出整个扇区

        EN25Q64_sector_erase(pos); //擦除整个扇区

        for(i = 0; i < n; i++)
        {
            EN25QXX_BUF[i + offset] = b[i];
        }

        EN25Q64_write_nocheck(EN25QXX_BUF,4096); //写入整个扇区

        if(n == num)
        {
            break;
        }

        pos++;
        num -= n;
        offset = 0;
        b += n; 
        if(num > 4096)
        {
            n = 4096;
        }
        else
        {
            n = num;
        }
    }   
}

void EN25Q64_chip_erase()
{   
    EN25Q64_write_enable();
    EN25Q64_is_busy();

    FLASH_CS = 0;

    SPI_read_write(EN25X_ChipErase);    

    FLASH_CS = 1;

    EN25Q64_is_busy();
}

void EN25Q64_power_down()
{
    FLASH_CS = 0;

    SPI_read_write(EN25X_PowerDown);    

    FLASH_CS = 1;

    delay_us(3);
}

void EN25Q64_release_power_down()
{
    FLASH_CS = 0;

    SPI_read_write(EN25X_ReleasePowerDown); 

    FLASH_CS = 1;

    delay_us(3);
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读