还记得第一次用spi设备的时候是大三暑假了,那时和队友一起买了无线模块,然后用单片机来无线传输,不过代码都不是自己写的,虽然实现了这个功能,但是当时还不知道什么spi的。大四了,学弟问我怎么用spi flash,顿感惭愧。后来他送我了一块flash,然后我用51参考网上的实现了下,才知道有这么个东西。之后公司里也渐渐用了些spi的设备,flash,codec,ads7843等,渐渐地也熟悉了这个东东。
其实,总线协议只是为了减少io口,人为定义的。我们也可以定义协议,只要按照这个时序来就可以了。
SPI(serial peripheral interface),就是串行外围设备接口。她是一种高速的,全双工,同步的通信总线,只有四根线。菜鸟嘛,高速应该好理解的,就是传输速率比较快,而对于什么全双工啊,同步啊的可能没什么概念。网上有举几个例子的,全双工是指在发送数据的同时也能够接收数据,两者同步进行,这好像我们平时打电话一样,说话的同时也能够听到对方的声音。半双工,所谓半双工就是指一个时间段内只有一个动作发生,举个简单例子,一条窄窄的马路,同时只能有一辆车通过,当目前有两辆车对开,这种情况下就只能一辆先过,等到头儿后另一辆再开。单工通信是指通信线路上的数据按单一方向传送,就像传呼机一样。同步传输是指通信双方有共同的时钟参考,能够通过时钟参考准确收发数据,通常这个时钟参考是同步时钟线或同一个时钟源。异步传输是指通信双方没有共同的时钟参考,通常每次收发数据时都需要有前导码进行速率同步。计算机的并口就是同步的,而RS-232串口和USB等就是异步的。
SPI是一个环形总线结构,由ss(cs)、sck、sdi、sdo四根线组成,就是在sck的控制下,两个移位寄存器进行数据交换。
上升沿发送,下降沿接收,高位先发送
上升沿到来的时候,sdo上的电平将被发送到从设备的寄存器中。
下降沿到来的时候,sdi上的电平将被接收到主设备的寄存器中。
假设主机和从机初始化就绪:并且主机的 sbuff=0xaa (10101010),从机的 sbuff=0x55 (01010101),下面将分步对spi的8个时钟周期的数据情况演示一遍(假设上升沿发送数据)。
---------------------------------------------------
脉冲 主机 sbuff 从机sbuff sdi sdo
---------------------------------------------------
0 00-0 10101010 01010101 0 0
---------------------------------------------------
1 0--1 0101010x 10101011 0 1
1 1--0 01010100 10101011 0 1
---------------------------------------------------
2 0--1 1010100x 01010110 1 0
2 1--0 10101001 01010110 1 0
---------------------------------------------------
3 0--1 0101001x 10101101 0 1
3 1--0 01010010 10101101 0 1
---------------------------------------------------
4 0--1 1010010x 01011010 1 0
4 1--0 10100101 01011010 1 0
---------------------------------------------------
5 0--1 0100101x 10110101 0 1
5 1--0 01001010 10110101 0 1
---------------------------------------------------
6 0--1 1001010x 01101010 1 0
6 1--0 10010101 01101010 1 0
---------------------------------------------------
7 0--1 0010101x 11010101 0 1
7 1--0 00101010 11010101 0 1
---------------------------------------------------
8 0--1 0101010x 10101010 1 0
8 1--0 01010101 10101010 1 0
---------------------------------------------------
这样就完成了两个寄存器8位的交换,上面的0--1表示上升沿、1--0表示下降沿,sdi、 sdo相对于主机而言的。根据以上分析,一个完整的传送周期是16位,即两个字节,因为,首先主机要发送命令过去,然后从机根据主机的名准备数据,主机在下一个8位时钟周期才把数据读回来。
SPI总线是摩托罗拉公司推出的三线同步接口,同步串行3线方式进行通信:一条时钟SCK,一条数据输入线MOSI(master output slave input ),一条数据输出MISO(master input slave output)。SPI的主要特点有:可以同时发出和接收串行数据;可以当做主机或从机工作;提供频率可编程时钟;发送结束中断标志;写冲突保护;总线竞争保护等。
SPI总线有四种工作方式(SPI0、SPI1、SPI2、SPI3),一般我们用到的是SPI0和SPI3的方式。
SPI模块为了和外设进行数据交换,根据外设工作要求,其输出串行同步时钟极性和相位可以进行配置,时钟极性(CPOL)对传输协议没有重大的影响,如果CPOL=0,串行同步时钟的空闲状态为低电平;如果CPOL=1,串行同步时钟的空闲状态为高电平。时钟相位(CPHA)能够用于选择两种不同的传输协议之一进行数据传输。如果CPHA=0,在串行同步的第一个跳变沿(上升或下降)数据被采样,如果CPHA=1,在串行同步时钟的第二个跳变沿(上升或下降)数据被采样。
下面看一下网上有的图:
由上图很清晰明了地知道了CPOL分别为0、1的时候的时钟和CPHA分别为0,1时候的采样时间的区别了。
不过一般来说都是用模式0的,我用的这些都是模式0的。
就是上图这个时序了,当片选spi设备后,开始有数据在传输,一个时钟采样一个,就以这个传输数据了,总得来说还是挺简单的。
还是看看SPI内部的结构图吧
切记主机的输出是从机的输入,主机的输入是从机的输出。像串口一样的交叉连接。
OK,对于SPI的协议就记录下这些了,用于以后的驱动的实现也够用了。