STM32实现W25Q16芯片的擦除、读和写
封装等待函数(通过读取状态寄存器)
void delayBusy() { uint8_t D05 = 0x05; uint8_t result; EnCS(0); HAL_SPI_Transmit(&hspi1, &D05, 1, 1000); HAL_SPI_Receive(&hspi1, &result, 1, 1000); while((result&0x01) == 1) { HAL_SPI_Receive(&hspi1, &result, 1, 1000); } EnCS(1); }
|
注意,手册上说明此处的状态寄存器可以连续读取,也就是在指令开始的时候发送一次0x05即可,之后循环读取,通过将片选信号CS置为高电平停止
擦除函数
void EraseChip() { uint8_t D60 = 0x60; writeEnable(); EnCS(0); HAL_SPI_Transmit(&hspi1, &D60, 1 ,1000); EnCS(1); delayBusy(); }
|
注意,将芯片内容擦除之前需要先发送一个使能写的命令,在下面的函数中会封装这个功能
然后在函数的最后增加等待芯片空闲的函数,该芯片的擦除时间大概1-2s,不同容量的芯片可能时间不同。
- 擦除前的读取数据(第二行):

- 擦除后的读取数据

- 可见擦除成功
写使能函数
void writeEnable() { uint8_t D06 = 0x06; EnCS(0); HAL_SPI_Transmit(&hspi1, &D06, 1, 1000); EnCS(1); }
|
禁止写函数与写使能函数类似,将命令替换为0x04即可
读取函数

void readChip(uint32_t addr, int32_t length) { uint8_t D03 = 0x03; int32_t count = length-1; uint8_t Haddr; uint8_t Maddr; uint8_t Laddr; Haddr = addr/256/256; Maddr = (addr/256)&0xff; Laddr = addr&0xff; EnCS(0); HAL_SPI_Transmit(&hspi1, &D03, 1, 1000); HAL_SPI_Transmit(&hspi1, &Haddr, 1, 1000); HAL_SPI_Transmit(&hspi1, &Maddr, 1, 1000); HAL_SPI_Transmit(&hspi1, &Laddr, 1, 1000); for(count = length-1; count>=0;count--) { HAL_SPI_Receive(&hspi1, recBuff+count, 1, 1000); } EnCS(1); }
|
其中的recBuff是一个大小与length相同的byte数组
注意,与上面类似的是,此处在发送一次读指令之后,芯片会从指定的地址开始自动向前串行发送往后的数据直到CS被置为高电平终止指令,严格的讲从发送的地址开始,可以只发送一次读取指令便读取到芯片的末尾存储空间。
写数据函数

写函数的执行逻辑是:
- 发送一个写使能信号
- CS置为低电平
- 发送0x02
- 发送24位地址
- 连续发送写入的数据(1-256个,一次最多不超过256个,否则超出的会从头部开始覆盖)
- CS置为高电平
- 等待芯片写完
- 发送禁止写命令
void writeChip(uint32_t addr, uint16_t length) { uint8_t D02 = 0x02; int32_t count = 0; uint8_t Haddr; uint8_t Maddr; uint8_t Laddr; Haddr = addr/256/256; Maddr = (addr/256)&0xff; Laddr = addr&0xff; writeEnable(); EnCS(0); HAL_SPI_Transmit(&hspi1, &D02, 1, 1000); HAL_SPI_Transmit(&hspi1, &Haddr, 1, 1000); HAL_SPI_Transmit(&hspi1, &Maddr, 1, 1000); HAL_SPI_Transmit(&hspi1, &Laddr, 1, 1000); for(count = 0; count<length;count++) { HAL_SPI_Transmit(&hspi1, writeBuff+count, 1, 1000); } EnCS(1); delayBusy(); writeDisable(); }
|
writeBuff是一个长度为length的字节数组
注意:
- 假如一次写256个字节的话,地址的最后8位务必是0,假如不是的话会导致超出的部分从头部开始覆盖
- 写入的字节数不能超出从地址位置开始剩余的字节量(比如地址后8位是0的话,剩余的字节就是256)
- 注意在写完最后一个数据之后,比如将片选信号CS置为高电平,此时芯片会开始写入数据,写入的时候查询BUSY寄存器会得到1,所以使用等待函数等待
执行效果
- 发送buff定义为
uint8_t writeBuff[] = {1,2,3,4,5,6,7,8};注意数组初始化不要漏写[]
- 发送函数和读取函数
writeChip(0x01,8); readChip(0x01, 8);
|
- 结果

- 可见已经成功写入