关于SPI协议及驱动开发

SPI的概述(部分内容摘自百度百科)

SPI是英文Serial Peripheral Interface的缩写,中文意思是串行外围设备接口,SPIMotorola公司推出的一种同步串行通讯方式,是一种三线同步总线,因其硬件功能很强,与SPI有关的软件就相当简单,使CPU有更多的时间处理其他事务。

SPIMotorola首先在其MC68HCXX系列处理器上定义的。SPI接口主要应用在 EEPROMFLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议。

       SPI总线系统是一种同步串行外设接口,它可以使MCU与各种外围设备以串行方式进行通信以交换信息。该接口一般使用4条线:串行时钟线(SCLK)、主机输入/从机输出数据线MISO、主机输出/从机输入数据线MOSI和低电平有效的从机选择线SS(有的SPI接口芯片带有中断信号线INTINT、有的SPI接口芯片没有主机输出/从机输入数据线MOSI)

       SPI的通信原理很简单,它以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4根线,事实上3根也可以(单向传输时)它们是SDI(数据输入),SDO(数据输出),SCLK(时钟),CS(片选信号)。

(1)   SDO – 主设备数据输出,从设备数据输入

(2)   SDI – 主设备数据输入,从设备数据输出

(3)   SCLK – 时钟信号,主设备产生

(4)   CS – 从设备使能信号,主设备控制

其中CS是控制芯片是否被选中的,也就是说只有片选信号为预先规定的使能信号时(高电位或低电位),对此芯片的操作才有效。这就允许在同一总线上连接多个SPI设备成为可能。

 

SPI的工作方式

       SPI CPU与外部设备之间传输1-bit串行数据,SPI允许CPUDMA访问传输和接受FIFOs,并且支持两个方向的同时传输,即全双工。SPI有两个channelTX channelRX channelTX channelTX FIFO到外部设备,RX channel 从外部设备到RX FIFO

       CPUDMA可以将数据写到SPI_TX_DATA寄存器上,再由寄存器自动的将数据移到TX FIFOs,如果从RX FIFOs中读数据的话,CPUDMA可以访问SPI_RX_DATA, RX FIFOs中的数据会自动送到SPI_RX_DATA中。

       SPI有两种工作模式,masterslave,在master方式下,SPICLK由主设备产生并传送到外部设备。SS(低电平有效)信号用来选择slave,在一对多的工作模式下,可以使能不同的slave设备。SPI支持DMA,中断和轮询工作方式。

       SPI支持四种工作格式,根据CPOL(时钟极性)CPHA(时钟相位)来定义四种格式。

SPI 模块为了和外设进行数据交换,根据外设工作要求,其输出串行同步时钟极性和相位可以进行配置,时钟极性(CPOL)对传输协议没有重大的影响。如果 CPOL=0,串行同步时钟的空闲状态为低电平;如果CPOL=1,串行同步时钟的空闲状态为高电平。时钟相位(CPHA)能够配置用于选择两种不同的传输协议之一进行数据传输。如果CPHA=0,在串行同步时钟的第一个跳变沿(上升或下降)数据被采样;如果CPHA=1,在串行同步时钟的第二个跳变沿(上升或下降)数据被采样。SPI主模块和与之通信的外设备时钟相位和极性应该一致。

 

结合datasheet,需要顺序的设置功能寄存器。

SPI驱动

由于SPI协议比较简单,所以驱动可以做成Build-in的流驱动,根据流驱动的规范,这样可以实现DllEntry SPI_InitSPI_OpenSPI_ReadSPI_WriteSPI_IOControlSPI_PowerDownSPI_PowerUpSPI_DeinitSPI_CloseSPI_Seek等接口函数,其中SPI_SeekSPI_Close可以不用实现。当驱动被加载的时候,就需要去初始化系统资源,创建一些线程,并且关联一些中断,如SPI中断,DMA中断等。在整个驱动里,支持DMA,中断和轮询等工作方式。创建多个初始化就运行的线程,如ThreadForTxThreadForRxThreadForSpiThreadForRxDmaDoneThreadForTxDmaDone。通过与硬件中断关联的事件和软件中断来配合实现数据的收发。例如,应用程序可以通过CreateFile打开驱动句柄,并通过DeviceIoControl进行配置,此时SPI将被调用,当调用SPI_Read时,可以通过设置事件来使能ThreadForRx,使其被唤醒并根据所设置的工作方式进行读取数据,当 工作结束时,就可以通知SPI_Read,整个读取过程结束。

整个过程相对简单,但是如果要很好的工作,就需要slavemaster设置一致。驱动尽可能做的与外部设备无关。因为工作中,时间有限,只要调试成功,能够正常工作,就很少再去考虑驱动的完善。这是目前自己比较欠缺的。希望在工作中不断加深认识,学习协议,多看源码。

点滴记录自己的成长历程,如有认识错误,敬请指出。

你可能感兴趣的:(关于SPI协议及驱动开发)