0%

STM32实现W25Q16芯片的擦除、读和写

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_Transmit(&hspi1, &D05, 1, 1000);
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,不同容量的芯片可能时间不同。

  • 擦除前的读取数据(第二行):
  • image-20220108130401292
  • 擦除后的读取数据
  • image-20220108130417022
  • 可见擦除成功

写使能函数

void writeEnable()
{
uint8_t D06 = 0x06;
EnCS(0);
HAL_SPI_Transmit(&hspi1, &D06, 1, 1000);
EnCS(1);
}

禁止写函数与写使能函数类似,将命令替换为0x04即可

读取函数

image-20220108125308657

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被置为高电平终止指令,严格的讲从发送的地址开始,可以只发送一次读取指令便读取到芯片的末尾存储空间

写数据函数

image-20220108133158219

写函数的执行逻辑是:

  • 发送一个写使能信号
  • 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);
  • 结果
  • image-20220108133835422
  • 可见已经成功写入