一、W25QXX芯片介绍
本次以W25Q32为主介绍,其他如W25Q64,W25Q16等只是在存储大小上有区别。
W25Q32有16384个可编程页,每页有256个字节;在页擦除时可以按照16页为一组擦除(即4KB扇区擦除)、128页为一组擦除(即32KB块擦除)、256页为一组擦除(即64KB块擦除)或者整个芯片擦除。
块、扇区、页的大小:
块(block) | 64KB |
扇区(sector) | 4KB |
页(page) | 256byte |
W25Q32有64block = 64*16sector = 64*16*(4*1024/256)page = 16384page
二、状态寄存器
BUSY(忙位):BUSY位是一个只读位,位于状态寄存器中的S0,当器件在执行“页编程”、“扇区擦除”、“跨擦除”、“芯片擦除”、“写状态寄存器或擦除/程序安全寄存器”指令时,该位自动置为1,这是除了“读状态寄存器”指令,其他指令都忽略。当指令执行完毕后,该位自动置为0,表示芯片接收其他指令。
WEL位:写使能锁存(WEL)是状态寄存器(S1)中的一个只读位,在执行写使能指令后被设置为1。当设备禁止写时,WEL状态位清零。写禁用状态发生在上电或以下任何指令之后:写禁用、页程序、四页程序、扇区擦除、块擦除、芯片擦除、写状态寄存器、擦除安全寄存器和程序安全寄存器。
三、指令介绍
3.1 Manufacturer/Device ID
读取制造厂商/设备ID。不同的芯片制造厂商/设备ID是不同的,具体是多少要查看对应的手册。
指令最后得到的是MF7-MF0 ID7-ID0,所以得到的是EF15
代码编写过程:
1、先将CS拉低
2、发送8位指令
3、发送24位的地址
4、接收8位的制造商ID和8位的设备ID
5、CS拉高
uint16_t readID()
{
unsigned char command = W25X_ManufactDeviceID;
W25QXX_CS_L;
HAL_SPI_Transmit(&hspi1,&command,1,0xff);
unsigned char data = 0x00;
HAL_SPI_Transmit(&hspi1,&data,1,0xff);
HAL_SPI_Transmit(&hspi1,&data,1,0xff);
HAL_SPI_Transmit(&hspi1,&data,1,0xff);
uint16_t ID = 0x00;
uint8_t temp = 0xff;
HAL_SPI_Receive(&hspi1,&temp,1,0xff);
ID = temp;
// printf("0x%2x",temp);
ID = ID<<8;
HAL_SPI_Receive(&hspi1,&temp,1,0xff);
ID = ID|temp;
//printf("0x%2x",temp);
W25QXX_CS_H;
return ID;
}
3.2 JEDEC ID
返回的正确结果是EF4016
//读取JEDEC ID =0xEF4016
uint32_t JEDEC_ID()
{
unsigned char command = W25X_JedecDeviceID;
W25QXX_CS_L;
HAL_SPI_Transmit(&hspi1,&command,1,0xff);
uint32_t JEDEC_ID = 0x00;
uint8_t temp1 = 0xff;
uint8_t temp2 = 0xff;
uint8_t temp3 = 0xff;
HAL_SPI_Receive(&hspi1,&temp1,1,0xff);
HAL_SPI_Receive(&hspi1,&temp2,1,0xff);
HAL_SPI_Receive(&hspi1,&temp3,1,0xff);
JEDEC_ID = temp1<<16 | temp2<<8 | temp3;
W25QXX_CS_H;
return JEDEC_ID;
}