最近在实现arm9上的驱动程序的编写,因为以前一直使用stm32的缘故,因此驱动代码的结构风格跟stm32一致。
一、spi的驱动只要实现时钟的打开、总线的打开、以及spi协议的一些配置(全双工、半双工、速率、主从模式、相位、极性),一般使用spi都是配置为全双工模式。
1、全双工
timeout = 0xFFFFF;
while (SPI_I2S_GetFlagStatus(SPI, SPI_I2S_FLAG_TXE) == RESET && --timeout > 0);
SPI_I2S_SendData(SPI, data);
timeout = 0xFFFFF;
while (SPI_I2S_GetFlagStatus(SPI, SPI_I2S_FLAG_RXNE) == RESET && --timeout > 0);
data = SPI_I2S_ReceiveData(SPI);
以上就是全双工的spi的代码片段,1)、查询发送是否为空,如果为空则发送数据。2)紧接着实现读操作,查询接收是否为非空,如果为非空则读取spi的数据。因为全双工是读、写同时进行的,发送数据的同时读回数据(即发送一个数据之后接收fifo里面肯定有数据,也就是RX非空),因此,无论是读、还是写都是先发送(即使发送的内容无效)然后,再读回数据。所以,发送和接收的是写在同一个函数里。
2、半双工。
int SPI_SendData(SPI_TypeDef* SPIx, uint8_t data)
{
int timeout;
SPIx->CTRL0 &= SPI_WRITE_OP;//write op
timeout = 0xfff;
while (SPI_GetFlagStatus(SPIx, SPI_FLAG_TXE) != SET && --timeout > 0);
SPIx->XFER = 1;// xfer count
SPIx->CTRL0_SET = SPI_RUN_OP;//run
SPIx->DATA = data;
timeout = 0xfff;
while (SPI_GetFlagStatus(SPIx, SPI_FLAG_BSY) != RESET && --timeout > 0);
return 0;
}
uint8_t SPI_ReceiveData(SPI_TypeDef* SPIx)
{
uint8_t data;
int timeout;
SPIx->XFER = 1;// xfer count
SPIx->CTRL0 |= SPI_READ_OP;
SPIx->CTRL0_SET = SPI_RUN_OP;//run
// timeout = 0xfff;
// while (QSPI_GetFlagStatus(SPIx, QSPI_FLAG_BSY) == RESET && --timeout > 0);
timeout = 0xfff;
while (SPI_GetFlagStatus(SPIx, SPI_FLAG_BSY) != RESET && --timeout > 0);
data = SPIx->DATA;
return data;
}
上面是半双工的代码,在半双工模式下收、发是可以分开的,也就是说可以单独的收(全双工是不行的),以上的代码还是有些问题的,接收没有查看RXNE(接收非空),而是查看的busy。
3、另外还有qspi模式,也就是CS 、CLOCK、IO0、IO1、IO2、IO3一般的时序图如下。
在使用qspi操作spiflash的时候要先将spiflash设置为qspi模式,具体设置为操作状态寄存器2的SR2的QE位,将该为置位1,然后发送进入qspi的命令(有的为0x38),使spiflash进入到qspi模式,我使用的是w25q128的芯片。一直没有调试成功,后续调通后会完善上来。其实,qspi对于驱动来说都是一样的,只是spi控制器会按qspi格式发送数据。