×
单片机 > 单片机程序设计 > 详情

stm32 SPI-FLASH W25Q64

发布时间:2020-08-27 发布时间:
|

W25Q64



SPI配置步骤

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



举例





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_Speed_50MHz,

GPIO_Mode_Out_PP

};


GPIO_InitTypeDef gpiog13 = 

{

GPIO_Pin_13,

GPIO_Speed_50MHz,

GPIO_Mode_Out_PP

};


GPIO_InitTypeDef gpiog14 = 

{

GPIO_Pin_13,

GPIO_Speed_50MHz,

GPIO_Mode_Out_PP

};


GPIO_InitTypeDef gpiof = 

{

GPIO_Pin_9,

GPIO_Speed_50MHz,

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;

}


void EN25Q64_read_unique_id(u8 *id)

{

int i = 0;


FLASH_CS = 0;


SPI_read_write(0x4B);

SPI_read_write(0); //dummy

SPI_read_write(0);

SPI_read_write(0);

SPI_read_write(0);


for(i = 0; i < 8; i++)

{

id[i] = SPI_read_write(0xFF);

}


    FLASH_CS = 1;

}


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, u32 addr, 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, u32 addr, 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, u32 addr, 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, pos * 4096, 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);

}


关键字:stm32  SPI-FLASH  W25Q64 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
浅谈AVR中定时器几种工作模式