SPI 是一个环形总线结构,由 ss(cs),sck,sdi,sdo 构成,其时序其实很简单,主要是在 sck 的控制下,两个双向移位寄存器进行数据交换.
SPI 总线是 Motorola 公司推出的三线同步接口,同步串行 3 线方式进行通信: 一条时钟线 SCK,一条数据输入线 MOSI,一条数据输出线 MISO; 用于 CPU 与各种外围器件进行全双工,同步串行通讯.SPI 主要特点有: 可以同时发出和接收串行数据; 可以当作主机或从机工作; 提供频率可编程时钟; 发送结束 中断标志; 写冲突保护; 总线竞争保护等.
SPI 总线有四种工作方式(SP0, SP1, SP2, SP3),其中使用的最为广泛的是 SPI0 和 SPI3 方式.
SPI 模块为了和外设进行数据交换,根据外设工作要求,其输出串行同步时钟极性和相位可以进行配置,时钟极性 (CPOL) 对传输协议没有重大的影响.如果 CPOL=0,串行同步时钟的空闲状态为低电平;如果 CPOL=1,串行同步时钟的空闲状态为高电平.时钟相位 (CPHA) 能够配置用于选择两种不同的传 输协议之一进行数据传输.如果 CPHA=0,在串行同步时钟的第一个跳变沿 (上升或下降) 数据被采样;如果 CPHA=1,在串行同步时钟的第二个跳变沿 (上升或下降) 数据被采样. SPI 主模块和与之通信的外设音时钟相位和极性应该一致.
SPI 接口在模式 0 下输出第一位数据的时刻,SPI 接口有四种不同的数据传输时序,取决于 CPOL 和 CPHL 这两位的组合.图 1 中表现了这四种时序,时序与 CPOL,CPHL 的关系也可以从图中看出.
图 1
CPOL 是用来决定 SCK 时钟信号空闲时的电平,CPOL=0,空闲电平为低电平,CPOL=1 时,空闲电平为高电平.CPHA 是用来决定采样时刻的,CPHA=0,在每个周期的第一个时钟沿采样,CPHA=1,在每个周期的第二个时钟沿采样.
由于我使用的器件工作在模式 0 这种时序(CPOL=0,CPHA=0),所以将图 1 简化为图 2,只关注模式 0 的时序.
图 2
我们来关注 SCK 的第一个时钟周期,在时钟的前沿采样数据(上升沿,第一个时钟沿),在时钟的后沿输出数据(下降沿,第二个时钟沿).首先来看主器件,主器件的输出口(MOSI)输出的数据 bit1,在时钟的前沿被从器件采样,那主器件是在何时刻输出 bit1 的呢?bit1 的输出时刻实际上在 SCK 信号有效以前,比 SCK 的上升沿还要早半个时钟周期.bit1 的输出时刻与 SSEL 信号没有关系.再来看从器件,主器件的输入口 MISO 同样是在时钟的前沿采样从器件输出的 bit1 的,那从器件又是在何时刻输出 bit1 的呢.从器件是在 SSEL 信号有效后,立即输出 bit1,尽管此时 SCK 信号还没有起效.关于上面的主器件和从器件输出 bit1 位的时刻,可以从图 3,4 中得到验证.
图 3
注意图 3 中,CS 信号有效后(低电平有效,注意 CS 下降沿后发生的情况),故意用延时程序延时了一段时间,之后再向数据寄存器写入了要发送的数据,来观察主器件输出 bit1 的情况(MOSI).可以看出,bit1(值为 1)是在 SCK 信号有效之前的半个时钟周期的时刻开始输出的(与 CS 信号无关),到了 SCK 的第一个时钟周期的上升沿正好被从器件采样.
图 4
图 4 中,注意看 CS 和 MISO 信号.我们可以看出,CS 信号有效后,从器件立刻输出了 bit1(值为 1).通常我们进行的 spi 操作都是 16 位的.图 5 记录了第一个字节和第二个字节间的相互衔接的过程.第一个字节的最后一位在 SCK 的上升沿被采样,随后的 SCK 下降沿,从器件就输出了第二个字节的第一位.
图 5
来源: http://lib.csdn.net/article/embeddeddevelopment/36847