我认为要理解硬件SPI通信协议,要理解三个关键点:
第一,要明白SPI的读写操作主要是依靠读取判断SPI_SR状态寄存器TXE位和RXNE位实现的。
第二,要明白芯片的各个指令,比如说W25Q128写使能的指令是#define W25X_WriteEnable 0x06
第三,要明白芯片的存储结构,比如说W25Q128存储容量为128M bit,其中又分为256个块,每个块又分为16个扇区,每个扇区又分为16个页,每个页又分为256个字节,也就是说W25Q128有256*16*16*256个地址(也就是能存储这么多个字节,因为一个字节对应一个地址)
SPI的读写操作是很重要的,但是又是很简单的一个过程:
(SPI_SR状态寄存器)
通过读取状态寄存器的TXE位(发送缓冲区状态位),置一表示发送缓冲区为空,此时,就可以向发送缓冲区写入数据(也就是说此时可以向从设备发送数据);
通过读取状态寄存器的RXNE位(发送缓冲区状态位),置一表示接收缓冲区非空,此时,就可以读取接收缓冲区的数据(也就是说此时成功接收从设备的数据,可以向主机返回接收到的数据);
具体实现代码如下:
//SPIx 读写一个字节 //TxData:要写入的字节 //返回值:读取到的字节 u8 SPI2_ReadWriteByte(u8 TxData) { u8 retry=0; while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位 { retry++; if(retry>200)return 0; } SPI_I2S_SendData(SPI2, TxData); //通过外设SPIx发送一个数据 retry=0; while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET) //检查指定的SPI标志位设置与否:接受缓存非空标志位 { retry++; if(retry>200)return 0; } return SPI_I2S_ReceiveData(SPI2); //返回通过SPIx最近接收的数据 //接收成功,读取接收的数据 }
对于芯片的各个指令的理解,我们可以根据芯片,查看对应的芯片数据手册:
比如说W25Q128的数据手册:
对于芯片的存储结构的理解,我们同样也可以根据芯片,查看对应的芯片数据手册:
比如说W25Q128的数据手册: