关于SPI的时序,麻烦就麻烦在它的极性和相位可以选择,所以我们这个时候就没有一个确定的空闲状态和采样边缘,可能是上升沿也可能是下降沿,这就使得我们没有办法像写IIC的时序一样,确定好每个时间点CLK的状态,从而来决定在什么时候给数据线赋值。
IIC发送数据的例子:
由于有四种状态,如果在发送数据的时候加入4种判断,务必会使得代码非常的长,过程很麻烦,在写的过程中,发现了一些简便的方法,可以很轻松的解决这些问题。
SPI在发送数据的过程中,就只有两个状态,一是空闲,二就是发送状态,所以,要通过CPOL来改变空闲时SCLK的值,只需要在空闲状态下的执行语句里面,直接将CPOL的值赋值给SCLK就可以,并且,在进入发送状态后,开始不要对SCLK重新赋值。则可以保证SCLK的电平由CPOL来决定。
关于CPHA的功能的实现,这里有一种简单的方法:不把CPOL看作是决定第几个时钟采样,而是由CPHA来判断,正式传输数据之前,SCLK需不需要发生一次电平的反转,而正式的数据传送,还是发生在正式开始传送的SCLK电平第一次发生反转处。即CPHA=0时,一到达发送状态,则电平反转一次,CPHA等于0时,电平不反转。然后后面就都是在SCLK处传输数据。(由于这里不确定是上升沿还是下降沿,因为都有可能,所以数据的传输都发生在SCLK电平第一次反转处,即可解决此问题)。
代码如下:
这里在进入发送状态的时候,time_count的值会一直是0的,用判断time_count[0],是因为第一个周期需要把cs拉低,所以得第二个时钟下再来反转或者不反转。
仿真结果:
(虽然这个可能很简单,但是我也是写到一半突然发现自己竟然能这么设计,觉得比较巧妙,所以想和大家分享一下,我不确定之前有没有人是跟这一样的方法(我觉得应该是有的),但是我可以保证我自己是独立完成,没有参考其他的,若非要我证明,那实在也没有办法。也望大佬勿喷,真的只是想分享一下方法给可能有需要的人,绝对不是在你们面前班门弄斧)