声明:我是跟着B站江科大的视频的学习过程中记录下来作者的文案,记录下来是为了方便自己日后复习。如果你也是跟着江科大的视频学习的,可以一起学习
接软件SPI读写W25Q64(上)
STM32--软件SPI读写W25Q64(上)-CSDN博客
由于指令比较多,每个指令都对应一个指令码,如果直接在程序里写一个数字,那意义就不太明显,可读性不高。所以像上一节MPU6050一样,将每个指令码用宏定义来替换一下。由于指令比较多,所以在Hardware下单独建一个W25Q64_Ins.h头文件。
先include头文件,再进行改写。
规定:SPI起始之后的第一个字节都是指令码。
写使能之后不需要跟任何数据,所以发送完写使能指令之后,直接stop即可。
只要调用一次这个函数,就可以向W25Q64发送一次写使能指令。
下一条指令的就是读状态寄存器,这个主要用途就是判断芯片是不是忙状态。
这是状态寄存器每一位的定义。我们要读取他的最低位BUSY,1表示芯片还在忙,0表示芯片不忙了。
起始之后,先发送指令码,再接收状态寄存器,之后如果时序不停,还要继续接收的话,这个芯片会把状态寄存器最新的状态发送过来。状态寄存器可以被连续读出,这个连续读出就方便我们执行连续等待的功能。
下一个写页编程的函数,先发送一个指令码02h,在连续发送3个字节的地址,最后,发送数据。
()表示是接收数据的。所以这个页编程的最后一个(D7-D0)是错的,应该没有括号。
最大发送是DataByte256,如果继续写,超过这个,就会覆盖掉之前的DataByte1。
页编程一次性写入数据的范围是0~256,所以是16位的,如果这个Count是uint8_t的话,只能存0~255,这样当我们写256个数据时,就会出现问题。
由于指定的地址是24位的,所以用32位数据。
假如Address是0x123456,右移8位就是0x001234,再加上MySPI_SwapByte()只能接收8位数据,高位设计,所以只能发送0x34。
这里SPI高位发送是指一个字节里的8个位是从最高位开始,并不是指0x123456的最高位0x12开始发送。
调用这个函数,给要写入的起始地址,要写入的数组和数量,就可以帮我们写入数据了。
要执行扇区擦除,需要先发送指令20h,再发送3个字节的地址即可。这样指定地址所在的整个扇区就会被擦除。
要记住擦除完之后需要等待BUSY置0,但这是在主函数main里写的,这些不需要管。
这些dummy是无用数据,接收的也是无用数据,这些数据就是用来延时的,相当于有一段延时。作者推测这写dummy时序是给内部电路产生一些额外的时钟,可以做些准备工作。
最后一个指令,读取数据,流程是先发送一个指令,在发送3个字节的地址,再转入接收,就可以依次接收数据了。
读取没有256字节限制,可以跨页,一直连续读。
在每次交换读取之后,存储器内部的地址指针自动自增。依次返回指定地址开始,往后线性区域地址下的数据。
涉及写入操作的时序有扇区擦除和页编程,既然在每次写入之前都必须写使能,那可以直接在函数里自带一个写使能。
这样再调用写入的函数,就不用再额外调用写使能了。
上一节讲过,写使能仅对之后跟随的一条时序有效,一条时序结束后,会顺手关闭。所以在每次写入之前,都加一条写使能,写完之后就不用再写失能了。
还有一个就是写入操作之后,芯片就会进入忙状态,不响应新的读写操作。所以可以在每次写操作之后调用一下WaitBusy()。
我们可以选择在每次写入后,都等BUSY清零了,再退出函数。这样比较保险,等不忙了,再退出。或者事前等待,就是等不忙了,再写入。区别是,事后等待保险,在函数之外的地方,肯定是不忙的状态;事前等待,效率会高一点,因为写完之后不等,程序可以执行其他代码,在执行其他代码期间,来消耗等待的时间,说不定下一次事前等待的时候,时间已经被耗过去了。
还有一个区别:事后等待只需在写入操作结束后调用;事前等待需要在写入操作和读取操作之前都进行调用,因为忙的时候读取也是不行的。
擦除和写入数据操作都配置为事后等待。
头文件声明