最近在做关于SPI通讯方面的工作,在网上查找了很多资料,但发现很多都语焉不详或者牛头不对马嘴,终于最后找到了一篇说得比较明白易懂的SPI解答文章,转载过来供大家一起参考,并总结下SPI通讯方式。
原文链接地址:http://blog.sina.com.cn/s/blog_4f09c0b50101368f.html
最近在用W25Q32BV的FLASH存储器,为了搞明白他的工作原理。上网查阅了资料,发现网上有部分错误的地方。
一、技术性能
SPI接口是Motorola 首先提出的全双工三线同步串行外围接口,采用主从模式(Master Slave)架构;支持多slave模式应用,一般仅支持单Master。
时钟由Master控制,在时钟移位脉冲下,数据按位传输,高位在前,低位在后(MSB first);SPI接口有2根单向数据线,为全双工通信,目前应用中的数据速率可达几Mbps的水平。
二、接口定义
SPI接口共有4根信号线,分别是:设备选择线、时钟线、串行输出数据线、串行输入数据线。
(1)MOSI:主器件数据输出,从器件数据输入
(2)MISO:主器件数据输入,从器件数据输出
(3)SCLK :时钟信号,由主器件产生
(4)/SS:从器件使能信号,由主器件控制
三、内部结构
四、传输时序
SPI接口在内部硬件实际上是两个简单的移位寄存器,传输的数据为8位,在主器件产生的从器件使能信号和移位脉冲下,按位传输,高位在前,低位在后。如下图所示,在SCLK的下降沿上数据改变,上升沿一位数据被存入移位寄存器。
SPI接口没有指定的流控制,没有应答机制确认是否接收到数据。
SPI是一个环形总线结构,由ss(cs)、sck、sdi(MISO)、sdo(MOSI)构成,其时序其实很简单,主要是在sck的控制下,两个双向移位寄存器进行数据交换。
假设主机和从机初始化就绪:并且主机的sbuff=0xaa,从机的sbuff=0x55,下面将分步对spi的8个时钟周期的数据情况演示一遍:假设上升沿发送数据
void SPI_Init()
{
}
void IO_Send_Byte(uint8 dataout)
{
}
uint8 IO_Send_Byte()
{
uint8 val=0;
}
void SPI_End()
{
}
最后自己对于SPI的使用做一个如下的总结和笔记。
1、SPI硬件电路:三线或四线制:MISO,MOSI,SCLK,SS.设计的时候必须首先保证两通信模块的对应管脚连接正确。两个不同的设备上:主:MISO(MI)<--->从:MISO(SO) 主:MOSI(MO)<--->从:MOSI(SI)主:SCLK<----->从:SCLK.即一一对应关系。
2、SPI通讯设置:由时钟极性和时钟相位两个因素决定。这里一定要明白SPI的硬件工作原理:即由同一时钟驱动的两个环形交叉移位寄存器。其硬件工作原理决定了:对同一个设备的SPI端口而言:数据输出和输入不能同时(同一个时钟沿)进行,所以才会有很多芯片手册上介绍的第一个(或第二个)时钟沿输出数据,第二个(或第一个)时钟沿采样输入数据。由此更要理解第二点,输出的数据是在第一个时钟沿(或第二个时钟沿)被准备好了的,在第二个(或第一个时钟沿)被对方端口采样并保存的。SLCK一个周期只有两个时钟跳变,而非三个。所以查看芯片的SPI时序时,仅需要明白,该SPI端口平时不工作时的电平,通信时是首先输出数据还是首先输入数据。
3、SPI数据收发:MSB First.读写数据是同时进行的,当向SPI数据缓冲区写好数据后,当数据传输完后,对接收数据缓冲区即可获得读取的数据了。所以在一个函数内即可实现SPI读和SPI写,区别于UART读、写函数分开的方式。