侵权投诉
订阅
纠错
加入自媒体

【硬见小百科】趣味SPI总线解析

2018-11-26 09:43
云创硬见
关注

什么是SPI?

SPI全称是串行外设接口(Serial Peripheral Interface),是由Motorola提出的一种全双工(全双工指可以同时(瞬时)进行信号的双向传输(A→B且B→A))同步串行通信接口,通信波特率可以高达5Mbps,但具体速度大小取决于SPI硬件。

SPI总线只需四条线就可以完成MCU与各种外围器件的通讯。

1)MOSI(SDI) – Master数据输出,Slave数据输入

2)MISO (SDO) – Master数据输入,Slave数据输出

3)SClK  – 时钟信号,由Master产生

4)/CS  – Slave使能信号,由Master控制。

Msater为主模式,Slave从模式。SPI通信就是采用这样的主从模式(Master-Slave)架构,一般为一个Master和多个Slave的应用模式。切记,谁为主,谁提供SCLK时钟信号。

在以上四根线中,CS是控制芯片是否被选中的,只有选信号为预先规定的使能信号时,对此芯片的操作才有效。这就允许主模式在同一总线上连接多个SPI设备成为可能。接下来再连接通讯的3根线就可以了。

SPI如何实现通讯

SPI也是串行通讯协议,是说数据是一位一位传输的。这是SCLK时钟线存在的原因,由SCLK提供时钟脉冲,SDI,SDO则基于此脉冲完成数据传输。操作时序很简单,如下:

看见时序图了,就知道怎么通讯了。SPI接口在Master控制下产生的从器件使能信号和时钟信号,两个双向移位寄存器按位传输进行数据交换,传输数据高位在前,低位在后(MSB first)。在SCK的下降沿上数据改变,上升沿一位数据被存入移位寄存器。

换个说法,SPI是一个环形总线结构,主要是在sck的控制下,两个双向移位寄存器进行数据交换。对于主机来说,上升沿发送、下降沿接收、高位先发送。

上升沿到来的时候,sdi上的电平将被发送到从设备的寄存器中。从M_Sbuff寄存器的7位,发送到S_Sbuff寄存器的0位;

下降沿到来的时候,sdi上的电平将被接收到主设备的寄存器中。从S_Sbuff寄存器的7位,发送到M_Sbuff寄存器的0位;

一个完整的传送周期是16位,即两个字节,因为,首先主机要发送命令过去,然后从机根据主机的命令准备数据,主机在下一个8位时钟周期才把数据读回来。

SPI总线比IIC总线传输数据省事。之前用过的IIC通讯,又有起始位,又有停止位的。SPI比较豪爽,对于主机来说,有上升沿就写一位,有下降沿就读一位。因为这样,SPI能够不等8位数据都传完就停止。没有了主机发出的SCLK脉冲,就不再有数据交换了。需要注意的是:我们的主设备能够控制时钟,因为我们的SPI通信并不像UART或者IIC通信那样有专门的通信周期,有专门的通信起始信号,有专门的通信结束信号;所以我们的SPI协议能够通过控制时钟信号线,当没有数据交流的时候我们的时钟线要么是保持高电平要么是保持低电平。

SPI注意事项与实现

SPI总线有四种工作方式(SPI0, SPI1, SPI2, SPI3),其中使用的最为广泛的是SPI0和SPI3方式。

时钟极性CPOL是用来配置SCLK的电平出于哪种状态时是空闲态或者有效态,时钟相位CPHA 是用来配置数据采样是在第几个边沿:

CPOL=0,表示当SCLK=0时处于空闲态,所以有效状态就是SCLK处于高电平时;

CPOL=1,表示当SCLK=1时处于空闲态,所以有效状态就是SCLK处于低电平时;

CPHA=0,表示数据采样是在第1个边沿,数据发送在第2个边沿;

CPHA=1,表示数据采样是在第2个边沿,数据发送在第1个边沿。

如上图,乃SPI四种模式的时序图。

CPOL=0,CPHA=0:此时空闲态时,SCLK处于低电平,数据采样是在第1个边沿,也就是SCLK由低电平到高电平的跳变,所以数据采样是在上升沿,数据发送是在下降沿。

CPOL=0,CPHA=1:此时空闲态时,SCLK处于低电平,数据发送是在第1个边沿,也就是SCLK由低电平到高电平的跳变,所以数据采样是在下降沿,数据发送是在上升沿。

CPOL=1,CPHA=0:此时空闲态时,SCLK处于高电平,数据采集是在第1个边沿,也就是SCLK由高电平到低电平的跳变,所以数据采集是在下降沿,数据发送是在上升沿。

CPOL=1,CPHA=1:此时空闲态时,SCLK处于高电平,数据发送是在第1个边沿,也就是SCLK由高电平到低电平的跳变,所以数据采集是在上升沿,数据发送是在下降沿。

如果要实现连接通讯,确定单片机(Master MCU1)为主模式,单片机(Slave MCU1)为从模式。各自也配置好了SLCK,MOSI,MISO和SCK的io引脚。选择了默认的SPI0模式。原理图如下:

按图连接好后,Master MCU1单片机发送1—10的数字给Slave MCU1单片机;Slave MCU1收到后,用流水灯作为回应。程序如下:

①:数据发送程序(主机仅发送)

#define    uchar  unsigned char

#define uint  unsigned int

#define ulong unsigned long

//---------------------------

#include

#include

//---------------------------

sbit   SPICLK =   P1^0;    //时钟信号

sbit   MOSI   =   P1^1;  //主器件数据输出,从器件数据输入

sbit   MISO   =   P1^2;  //主器件数据输入,从器件数据输出

sbit   SS     =   P1^3;  //从器件使能信号

void   Dat_Transmit(uchar dat)    //发送数据程序

uchar  i,datbuf;   //主机数据暂存寄存器

datbuf=dat;

SS=1;

while(SS){;}

for(i=0;i<8;i++)    //

while(SPICLK){;}

if(datbuf&0x80)

MISO=1;

else

MISO=0;

datbuf=(datbuf<<1);

while(~SPICLK){;}

void   main(void)

uchar i;

while(1)

for(i=0;i<10;i++)

Dat_Transmit(i);

②:数据接收程序(从机仅接收)

#define    uchar  unsigned char

#define uint  unsigned int

#define ulong     unsigned long

//---------------------------

#include

#include

//---------------------------

sbit   SPICLK =   P1^0;  //时钟信号

sbit   MOSI   =   P1^1;  //主器件数据输出,从器件数据输入

sbit   MISO   =   P1^2;  //主器件数据输入,从器件数据输出

sbit   SS     =   P1^3;  //从器件使能信号

//---------------------------

void   Nop(void)

void   Delay(uchar t)

while(t--){;}

uchar  Data_Receive(void)   //数据接收程序

uchar  i,dat=0,temp;

bit    bt;

SPICLK=1;

MISO=1;

SS=0;         //选中器件

Nop();

Nop();

for(i=0;i<8;i++)

SPICLK=1;

Nop();

Nop();

Nop();

SPICLK=0;

Nop();

Nop();

bt=MISO;

if(bt)

temp=0x01;

else   temp=0x00;

dat=(dat<<1);

dat=(dat|temp);

SS=1;

SPICLK=1;

return dat;

void   main(void)

uchar  exdat;

uchar  i=0;

uchar  code table[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,

0x7F,0x6F};

P2=0;

while(1)

exdat=Data_Receive();

P0=table[exdat];

for(i=0;i<200;i++)

Delay(200);

SPI总线注意点

1. Master配置SPI接口时钟的时候一定要考虑从设备的操作时序要求,因为Master这边的时钟极性和相位都是以Slave为基准的。因此在时钟极性的配置上一定要确定Slave是在SCK的下降沿还是上升沿输出数据,是在SCK的上升沿还是下降沿接收数据。

2. 当Slave时钟频率小于Master时钟频率时,如果Master的SCK的速率太快,会出现Slave接收到的数据不正确,而SPI接口又没有应答机制确认Slave是否接收到数据从而导致通信传输数据错误。

3. SPI总线系统是一种同步串行外设接口,它可以使MCU与各种外围设备以串行方式进行通信以交换信息。除了MCU,还有FLASHRAM、网络控制器、LCD显示驱动器和A/D转换器等外围设置。

4. 上面的代码所用指令是STC 89C51单片机所用如需用其它芯片请另行更改。

以上所有信息仅作为学习交流使用,不作为任何学习和商业标准。

若您对文中任何信息有异议,欢迎随时提出,谢谢!

声明: 本文由入驻维科号的作者撰写,观点仅代表作者本人,不代表OFweek立场。如有侵权或其他问题,请联系举报。

发表评论

0条评论,0人参与

请输入评论内容...

请输入评论/评论长度6~500个字

您提交的评论过于频繁,请输入验证码继续

暂无评论

暂无评论

    电子工程 猎头职位 更多
    扫码关注公众号
    OFweek电子工程网
    获取更多精彩内容
    文章纠错
    x
    *文字标题:
    *纠错内容:
    联系邮箱:
    *验 证 码:

    粤公网安备 44030502002758号