精华内容
下载资源
问答
  • SPI 协议详解

    2015-05-19 17:40:40
    spi 协议详解
  • SPI协议详解

    万次阅读 多人点赞 2018-09-19 15:15:27
    1.SPI协议简介 1.1.SPI协议概括  SPI,是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口。是Motorola首先在其MC68HCXX系列处理器上定义的。SPI接口主要应用在 EEPROM,FLASH,实时时钟,...

    1.SPI协议简介

    1.1.SPI协议概括

      SPI,是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口。是Motorola首先在其MC68HCXX系列处理器上定义的。SPI接口主要应用在 EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议,比如AT91RM9200.

    SPI主从模式硬件连接如下图

      SPI的通信原理很简单,它以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4根线,事实上3根也可以(单向传输时)。也是所有基于SPI的设备共有的,它们是SDI(数据输入),SDO(数据输出),SCK(时钟),CS(片选)。

    • SDO     – 主设备数据输出,从设备数据输入 对应MOSI master output slave input
    • SDI      – 主设备数据输入,从设备数据输出  对应MISO master input slave output
    • SCLK   – 时钟信号,由主设备产生
    • CS        – 从设备使能信号,由主设备控制

      CS: 其中CS是控制芯片是否被选中的,也就是说只有片选信号为预先规定的使能信号时(高电位或低电位),对此芯片的操作才有效,这就允许在同一总线上连接多个SPI设备成为可能。

      SDI/SDO/SCLK: 通讯是通过数据交换完成的,这里先要知道SPI是串行通讯协议,也就是说数据是一位一位的传输的。这就是SCK时钟线存在的原因,由SCK提供时钟脉冲,SDI,SDO则基于此脉冲完成数据传输。数据输出通过 SDO线,数据在时钟上升沿或下降沿时改变,在紧接着的下降沿或上升沿被读取。完成一位数据传输,输入也使用同样原理。这样,在至少8次时钟信号的改变(上沿和下沿为一次),就可以完成8位数据的传输。

      要注意的是,SCK信号线只由主设备控制,从设备不能控制信号线。同样,在一个基于SPI的设备中,至少有一个主控设备。

    这样传输的特点:这样的传输方式有一个优点,与普通的串行通讯不同,普通的串行通讯一次连续传送至少8位数据,而SPI允许数据一位一位的传送,甚至允许暂停,因为SCK时钟线由主控设备控制,当没有时钟跳变时,从设备不采集或传送数据,也就是说,主设备通过对SCK时钟线的控制可以完成对通讯的控制。SPI还是一个数据交换协议:因为SPI的数据输入和输出线独立,所以允许同时完成数据的输入和输出。不同的SPI设备的实现方式不尽相同,主要是数据改变和采集的时间不同,在时钟信号上沿或下沿采集有不同定义,具体请参考相关器件的文档。

    在点对点的通信中,SPI接口不需要进行寻址操作,且为全双工通信,显得简单高效。在多个从设备的系统中,每个从设备需要独立的使能信号,硬件上比I2C系统要稍微复杂一些。

    最后,SPI接口的一个缺点:没有指定的流控制,没有应答机制确认是否接收到数据

    AT91RM9200的SPI接口主要由4个引脚构成:SPICLK、MOSI、MISO及 /SS,其中SPICLK是整个SPI总线的公用时钟,MOSI、MISO作为主机,从机的输入输出的标志,MOSI是主机的输出,从机的输入,MISO 是主机的输入,从机的输出。/SS是从机的标志管脚,在互相通信的两个SPI总线的器件,/SS管脚的电平低的是从机,相反/SS管脚的电平高的是主机。在一个SPI通信系统中,必须有主机。SPI总线可以配置成单主单从,单主多从,互为主从。

    SPI的片选可以扩充选择16个外设,这时PCS输出=NPCS,说NPCS0~3接4-16译码器,这个译码器是需要外接4-16译码器,译码器的输入为NPCS0~3,输出用于16个外设的选择。

    2.协议举例

    如下图,是SPI的简单收发时序图。

    SPI是一个环形总线结构,由ss(cs)、sck、sdi、sdo构成,其时序其实很简单,主要是在sck的控制下,两个双向移位寄存器进行数据交换。
           假设下面的8位寄存器装的是待发送的数据10101010,上升沿发送、下降沿接收、高位先发送。
           那么第一个上升沿来的时候 数据将会是sdo=1;寄存器=0101010x。下降沿到来的时候,sdi上的电平将锁存到寄存器中去,那么这时寄存器=0101010sdi,这样在 8个时钟脉冲以后,两个寄存器的内容互相交换一次。这样就完成里一个spi时序。 

    举例: 
           假设主机和从机初始化就绪:并且主机的sbuff=0xaa,从机的sbuff=0x55,下面将分步对spi的8个时钟周期的数据情况演示一遍:假设上升沿发送数据

    这样就完成了两个寄存器8位的交换,上面的上表示上升沿、下表示下降沿,sdi、sdo相对于主机而言的。其中ss引脚作为主机的时候,从机可以把它拉底被动选为从机,作为从机的是时候,可以作为片选脚用。根据以上分析,一个完整的传送周期是16位,即两个字节,因为,首先主机要发送命令过去,然后从机根据主机的命令准备数据,主机在下一个8位时钟周期才把数据读回来。

         

      SPI 总线是Motorola公司推出的三线同步接口,同步串行3线方式进行通信:一条时钟线SCK,一条数据输入线MOSI,一条数据输出线MISO;用于CPU与各种外围器件进行全双工、同步串行通讯。SPI主要特点有:可以同时发出和接收串行数据;可以当作主机或从机工作;提供频率可编程时钟;发送结束 中断标志;写冲突保护;总线竞争保护等。下图示出SPI总线工作的四种方式,其中使用的最为广泛的是SPI0和SPI3方式 (实线表示):                  

                                                        

    3. SPI总线四种工作方式

    SPI 模块为了和外设进行数据交换,根据外设工作要求,其输出串行同步时钟极性和相位可以进行配置,时钟极性(CPOL)对传输协议没有重大的影响。

           时序详解:

      CPOL:时钟极性选择,为0时SPI总线空闲为低电平,为1时SPI总线空闲为高电平

      CPHA:时钟相位选择,为0时在SCK第一个跳变沿采样,为1时在SCK第二个跳变沿采样

      工作方式1:

      当CPHA=0、CPOL=0时SPI总线工作在方式1。MISO引脚上的数据在第一个SPSCK沿跳变之前已经上线了,而为了保证正确传输,MOSI引脚的MSB位必须与SPSCK的第一个边沿同步,在SPI传输过程中,首先将数据上线,然后在同步时钟信号的上升沿时,SPI的接收方捕捉位信号,在时钟信号的一个周期结束时(下降沿),下一位数据信号上线,再重复上述过程,直到一个字节的8位信号传输结束。

      工作方式2:

      当CPHA=0、CPOL=1时SPI总线工作在方式2。与前者唯一不同之处只是在同步时钟信号的下降沿时捕捉位信号,上升沿时下一位数据上线。

      工作方式3:

      当CPHA=1、CPOL=0时SPI总线工作在方式3。MISO引脚和MOSI引脚上的数据的MSB位必须与SPSCK的第一个边沿同步,在SPI传输过程中,在同步时钟信号周期开始时(上升沿)数据上线,然后在同步时钟信号的下降沿时,SPI的接收方捕捉位信号,在时钟信号的一个周期结束时(上升沿),下一位数据信号上线,再重复上述过程,直到一个字节的8位信号传输结束。

      工作方式4:

      当CPHA=1、CPOL=1时SPI总线工作在方式4。与前者唯一不同之处只是在同步时钟信号的上升沿时捕捉位信号,下降沿时下一位数据上线。

    4种工作模式波形时序如下图:

    åç§å·¥ä½æ¹å¼æ¶åº

    4.协议心得

    SPI接口时钟配置心得:

      在主设备这边配置SPI接口时钟的时候一定要弄清楚从设备的时钟要求,因为主设备这边的时钟极性和相位都是以从设备为基准的。因此在时钟极性的配置上一定要搞清楚从设备是在时钟的上升沿还是下降沿接收数据,是在时钟的下降沿还是上升沿输出数据。但要注意的是,由于主设备的SDO连接从设备的SDI,从设备的SDO连接主设备的SDI,从设备SDI接收的数据是主设备的SDO发送过来的,主设备SDI接收的数据是从设备SDO发送过来的,所以主设备这边SPI时钟极性的配置(即SDO的配置)跟从设备的SDI接收数据的极性是相反的,跟从设备SDO发送数据的极性是相同的。下面这段话是Sychip Wlan8100 Module Spec上说的,充分说明了时钟极性是如何配置的:

    The 81xx module will always input data bits at the rising edge of the clock, and the host will always output data bits on the falling edge of the clock.

    意思是:主设备在时钟的下降沿发送数据,从设备在时钟的上升沿接收数据。因此主设备这边SPI时钟极性应该配置为下降沿有效。

    又如,下面这段话是摘自LCD Driver IC SSD1289:

    SDI is shifted into 8-bit shift register on every rising edge of SCK in the order of data bit 7, data bit 6 …… data bit 0.

    意思是:从设备SSD1289在时钟的上升沿接收数据,而且是按照从高位到地位的顺序接收数据的。因此主设备的SPI时钟极性同样应该配置为下降沿有效。

    时钟极性和相位配置正确后,数据才能够被准确的发送和接收, 因此应该对照从设备的SPI接口时序或者Spec文档说明来正确配置主设备的时钟。

    5.SPI协议软件模拟

    5.1.单片机软件模拟SPI接口—加深理解SPI总线协议

            现以 AT89C205l单片机模拟SPI总线操作串行EEPROM 93CA6为例,如图1所示,介绍利用单片机的I/O口通过软件模拟SPI总线的实现方法。在这里,仅介绍读命令的时序和应用子程序。 

    5.2.93C46存储器SPI总线的工作原理

              93CA6作为从设备,其SPI接口使用4条I/O口线:串行时钟线(SK)、输出数据线DO、输入数据线DI和高电平有效的从机选择线CS。其数据的传输格式是高位(MSB)在前,低位(LsB)在后。93C46的SPI总线接口读命令时序如图2所示。 

    5.3.软件模拟SPI接口的实现方法 

              对于不带SPI串行总线接口的AT89C2051单片 机来说,可以使用软件来模拟SPI的操作,图1所示 为AT89C2051单片机与串行EEPROM 93C46的硬件 连接图,其中,P1.0模拟SPI主设备的数据输出端 SDO,P1.2模拟SPI的时钟输出端SCK,P1.3模拟 SPI的从机选择端SCS,P1.1模拟SPI的数据输入 SDI。
             上电复位后首先先将P1.2(SCK)的初始状态设置为0(空闲状态)。
             读操作:AT89C2051首先通过P1.0口发送1位起始位(1),2位操作码(10),6位被读的数据地址(A5A4A3A2A1A0),然后通过P1.1口读1位空位(0),之后再读l6位数据(高位在前)。
             写操作:AT89C2051首先通过P1.0口发送1位起始位(1),2位操作码(01),6位被写的数据地址(A5A4A3A2A1A0),之后通过P1.0口发送被写的l6位数据(高位在前),写操作之前要发送写允许命令,写之后要发送写禁止命令。
             写允许操作(WEN)):写操作首先发送1位起始位(1),2位操作码(00),6位数据(11XXXX)。              

             写禁止操作(WDS)):写操作首先发送1位起始位(1),2位操作码(00),6位数据(00XXXX)。

            下面介绍用C51模拟SPI的子程序。

    /*例子1*/
    //首先定义好I/O口
    sbit SDO=P1^0;
    sbit SDI=P1^1;
    sbit SCK=P1^ 2;
    sbit SCS=P1^3;
    sbit ACC_7= ACC^7;
    unsigned int SpiRead(unsigned char add)
    {
        unsigned char i;
        unsigned int datal6;
        add&=0x3f;/*6位地址*/
        add |=0x80;/*读操作码l0*/
        SDO=1;/*发送1为起始位*/
        SCK=0;
        SCK=1;
        for(i=0;<8;i++)/*发送操作码和地址*/
        {
            if(add&0x80==1)
                SDO=1;
            else 
                SDO=0;
            SCK=0;/*从设备上升沿接收数据*/
            SCK=1;
            add<<= 1;
        }
        SCK=1;/*从设备时钟线下降沿后发送数据,空读1位数据*/
        SCK=0;
        datal6<<= 1;/*读16位数据*/
        for(i=0;<16;i++)
        {
            SCK= 1;
            _nop_();
            if(SDI==1)
                datal6|=0x01;
            SCK =0;
            datal6< < =1;
        }
        return datal6;
    }
        
    /*例子2*/
        #define SS      252                     //定义SS所对应的GPIO接口编号  
        #define SCLK    253                     //定义SCLK所对应的GPIO接口编号  
        #define MOSI    254                     //定义SCLK所对应的GPIO接口编号  
        #define MISO    255                     //定义MISO所对应的GPIO接口编号  
        #define OUTP    1                       //表示GPIO接口方向为输出  
        #define INP 0                           //表示GPIO接口方向为输入  
        
        /* SPI端口初始化 */  
        void spi_init()  
        {  
            set_gpio_direction(SS, OUTP);  
            set_gpio_direction(SCLK, OUTP);  
            set_gpio_direction(MOSI, OUTP);  
            set_gpio_direction(MISO, INP);  
            set_gpio_value(SCLK, 0);//CPOL=0 
            set_gpio_value(MOSI, 0);
        }  
        /*  
        从设备使能  
        enable:为1时,使能信号有效,SS低电平  
        为0时,使能信号无效,SS高电平  
        */  
        void ss_enable(int enable)  
        {  
            if (enable)  
                set_gpio_value(SS, 0);//SS低电平,从设备使能有效  
            else  
                set_gpio_value(SS, 1);//SS高电平,从设备使能无效  
        }  
        
        /* SPI字节写 */  
        void spi_write_byte(unsigned char b)  
        {  
            int i;  
            for (i=7; i>=0; i--) {  
                set_gpio_value(SCLK, 0);  
                set_gpio_value(MOSI, b&(1<<i));//从高位7到低位0进行串行写入  
                delay();//延时  
                set_gpio_value(SCLK, 1);// CPHA=1,在时钟的第一个跳变沿采样  
                delay();      
            }  
        }  
        /* SPI字节读 */  
        unsigned char spi_read_byte()  
        {  
            int i;  
            unsigned char r = 0;  
            for (i=0; i<8; i++) {  
                set_gpio_value(SCLK, 0);  
                delay();//延时  
                set_gpio_value(SCLK, 1);// CPHA=1,在时钟的第一个跳变沿采样  
                r = (r <<1) | get_gpio_value(MISO);//从高位7到低位0进行串行读出  
                delay();  
            }  
        }  
        /*  
            SPI写操作  
            buf:写缓冲区  
            len:写入字节的长度  
        */  
        void spi_write (unsigned char* buf, int len)  
        {  
            int i;  
            spi_init();//初始化GPIO接口  
            ss_enable(1);//从设备使能有效,通信开始  
            delay();//延时  
            //写入数据  
            for (i=0; i<len; i++)
                spi_write_byte(buf[i]);
            delay();
            ss_enable(0);//从设备使能无效,通信结束  
        }  
        /*  
        SPI读操作  
        buf:读缓冲区  
        len:读入字节的长度  
        */  
        void spi_read(unsigned char* buf, int len)  
        {  
            int i;  
            spi_init();//初始化GPIO接口  
            ss_enable(1);//从设备使能有效,通信开始  
            delay();//延时  
            //读入数据
            for (i=0; i<len; i++)
                buf[i] = spi_read_byte();
            delay();
            ss_enable(0);//从设备使能无效,通信结束  
        }

      对于不同的串行接口外围芯片,它们的时钟时序是不同的。上述子程序是针对在SCK的上升沿输入(接收)数据和在下降沿输出(发送)数据的器件。这些子程序也适用于在串行时钟)的上升沿输入和下降沿输出的其它各种串行外围接口芯片,只要在程序中改变P1.2(SCK)的输出电平顺序进行相应调整即可。

     

    6. Linux下的SPI源码

    链接:https://pan.baidu.com/s/1Jm_gDxj-to965ZH3I16dug 密码:c9ki

    加我微信,拉进微信技术讨论群

         喜欢的可以关注微信公众号-嵌入式Linux

     

    展开全文
  • spi协议详解

    千次阅读 2018-08-27 23:42:54
    SPI,是一种高速的,全双工(可以同时接收和发送数据),同步的通信总线(接收端和发送端必须在同一时刻接收和发送),并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,...

    1.概念

    SPI,是英语Serial Peripheral Interface的缩写,顾名思义就是串行外围设备接口。SPI,是一种高速的,全双工可以同时接收和发送数据,同步的通信总线接收端和发送端必须在同一时刻接收和发送,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议。

                                              

    2.总线结构
    SPI通讯使用 3 条总线及片选线,3条总线分别为 SCK、MOSI、MISO,片选线为 SS,它们的作用介绍如下: 
    (1) SS( Slave Select):从设备选择信号线,常称为片选信号线,也称为 NSS、CS,以下用 NSS表示。当有多个 SPI从设备与 SPI主机相连时,设备的其它信号线 SCK、MOSI及 MISO同时并联到相同的 SPI总线上,即无论有多少个从设备,都共同只使用这 3条总线;而每个从设备都有独立的这一条 NSS 信号线,本信号线独占主机的一个引脚,即有多少个从设备,就有多少条片选信号线。I2C 协议中通过设备地址来寻址、选中总线上的某个设备并与其进行通讯;而 SPI 协议中没有设备地址,它使用 NSS 信号线来寻址,当主机要选择从设备时,把该从设备的 NSS 信号线设置为低电平,该从设备即被选中,即片选有效,接着主机开始与被选中的从设备进行SPI通讯。所以SPI通讯以 NSS 线置低电平为开始信号,以 NSS线被拉高作为结束信号。 
    (2) SCK (Serial Clock):时钟信号线,用于通讯数据同步。它由通讯主机产生,决定了通讯的速率,不同的设备支持的最高时钟频率不一样,如 STM32 的 SPI 时钟频率最大为f pclk /2,两个设备之间通讯时,通讯速率受限于低速设备。 
    (3) MOSI (Master Output, Slave Input):主设备输出/从设备输入引脚。主机的数据从这条信号线输出,从机由这条信号线读入主机发送的数据,即这条线上数据的方向为主机到从机。 
    (4) MISO(Master Input,,Slave Output):主设备输入/从设备输出引脚。主机从这条信号线读入数据,从机的数据由这条信号线输出到主机,即在这条线上数据的方向为从机到主机。 

    4.协议相关

    1) 通讯的起始和停止信号 
    在图中的标号1处,NSS 信号线由高变低,是 SPI 通讯的起始信号。NSS 是每个从机各自独占的信号线,当从机在自己的 NSS 线检测到起始信号后,就知道自己被主机选中了,开始准备与主机通讯。在图中的标号†处,NSS 信号由低变高,是 SPI 通讯的停止信号,表示本次通讯结束,从机的选中状态被取消。 
    (2)数据有效性 
    SPI使用 MOSI及 MISO信号线来传输数据,使用 SCK信号线进行数据同步。MOSI及MISO 数据线在 SCK 的每个时钟周期传输一位数据,且数据输入输出是同时进行的。数据传输时,MSB 先行或 LSB 先行并没有作硬性规定,但要保证两个 SPI通讯设备之间使用同样的协定,一般都会采用图 中的 MSB先行模式。 
    观察图中的2345标号处,MOSI及 MISO的数据在 SCK的上升沿期间变化输出,在SCK 的下降沿时被采样。即在 SCK 的下降沿时刻,MOSI 及 MISO 的数据有效,高电平时表示数据“1”,为低电平时表示数据“0”。在其它时刻,数据无效,MOSI及 MISO为下一次表示数据做准备。 
    SPI每次数据传输可以 8 位或 16 位为单位,每次传输的单位数不受限制。 
    (3)CPOL/CPHA及通讯模式 
    上面讲述的图 中的时序只是 SPI 中的其中一种通讯模式,SPI 一共有四种通讯模式(SP0, SP1, SP2, SP3),其中使用的最为广泛的是SPI0和SPI3方式。它们的主要区别是总线空闲时 SCK 的时钟状态以及数据采样时刻。为方便说明,在此引入“时钟极性 CPOL”和“时钟相位CPHA”的概念。 
    时钟极性 CPOL 是指 SPI 通讯设备处于空闲状态时,SCK 信号线的电平信号(即 SPI 通讯开始前、 NSS 线为高电平时 SCK 的状态)。CPOL=0 时, SCK在空闲状态时为低电平,CPOL=1 时,则相反。 
    时钟相位 CPHA 是指数据的采样的时刻,当 CPHA=0 时,MOSI 或 MISO 数据线上的信号将会在 SCK 时钟线的“奇数边沿”被采样。当 CPHA=1 时,数据线在 SCK 的“偶数边沿”采样。

    工作方式

    CPOL

    CPHA

    SP0

    0

    0

    SP1

    0

    1

    SP2

    1

    0

    SP3

    1

    1

    SPI接口有四种不同的数据传输时序,取决于CPOL和CPHL这两位的组合。图表现了这四种时序,
    时序与CPOL、CPHL的关系也可以从图中看出。

                         

    下面以模式0为例简单说明spi的时序

                        

    我们来关注SCK的第一个时钟周期,在时钟的前沿采样数据(上升沿,第一个时钟沿),在时钟的后沿输出数据(下降沿,第二个时钟沿)。即:上升沿期间数据需要保持稳定,在下降沿期间可以转换电平

                        

     

     

    展开全文
  • [SPI]SPI协议详解

    2019-04-25 17:27:50
    1.SPI协议简介 1.1.SPI协议概括  SPI,是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口。是Motorola首先在其MC68HCXX系列处理器上定义的。SPI接口主要应用在 EEPROM,FLASH,实时时钟,...

    1.SPI协议简介

    1.1.SPI协议概括

      SPI,是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口。是Motorola首先在其MC68HCXX系列处理器上定义的。SPI接口主要应用在 EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议,比如AT91RM9200.

      SPI的通信原理很简单,它以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4根线,事实上3根也可以(单向传输时)。也是所有基于SPI的设备共有的,它们是SDI(数据输入),SDO(数据输出),SCK(时钟),CS(片选)。

    • SDO     – 主设备数据输出,从设备数据输入
    • SDI      – 主设备数据输入,从设备数据输出
    • SCLK   – 时钟信号,由主设备产生
    • CS        – 从设备使能信号,由主设备控制

      CS: 其中CS是控制芯片是否被选中的,也就是说只有片选信号为预先规定的使能信号时(高电位或低电位),对此芯片的操作才有效,这就允许在同一总线上连接多个SPI设备成为可能。

      SDI/SDO/SCLK: 通讯是通过数据交换完成的,这里先要知道SPI是串行通讯协议,也就是说数据是一位一位的传输的。这就是SCK时钟线存在的原因,由SCK提供时钟脉冲,SDI,SDO则基于此脉冲完成数据传输。数据输出通过 SDO线,数据在时钟上升沿或下降沿时改变,在紧接着的下降沿或上升沿被读取。完成一位数据传输,输入也使用同样原理。这样,在至少8次时钟信号的改变(上沿和下沿为一次),就可以完成8位数据的传输。

      要注意的是,SCK信号线只由主设备控制,从设备不能控制信号线。同样,在一个基于SPI的设备中,至少有一个主控设备。这样传输的特点:这样的传输方式有一个优点,与普通的串行通讯不同,普通的串行通讯一次连续传送至少8位数据,而SPI允许数据一位一位的传送,甚至允许暂停,因为SCK时钟线由主控设备控制,当没有时钟跳变时,从设备不采集或传送数据,也就是说,主设备通过对SCK时钟线的控制可以完成对通讯的控制。SPI还是一个数据交换协议:因为SPI的数据输入和输出线独立,所以允许同时完成数据的输入和输出。不同的SPI设备的实现方式不尽相同,主要是数据改变和采集的时间不同,在时钟信号上沿或下沿采集有不同定义,具体请参考相关器件的文档。

    在点对点的通信中,SPI接口不需要进行寻址操作,且为全双工通信,显得简单高效。在多个从设备的系统中,每个从设备需要独立的使能信号,硬件上比I2C系统要稍微复杂一些。

    最后,SPI接口的一个缺点:没有指定的流控制,没有应答机制确认是否接收到数据

    AT91RM9200的SPI接口主要由4个引脚构成:SPICLK、MOSI、MISO及 /SS,其中SPICLK是整个SPI总线的公用时钟,MOSI、MISO作为主机,从机的输入输出的标志,MOSI是主机的输出,从机的输入,MISO 是主机的输入,从机的输出。/SS是从机的标志管脚,在互相通信的两个SPI总线的器件,/SS管脚的电平低的是从机,相反/SS管脚的电平高的是主机。在一个SPI通信系统中,必须有主机。SPI总线可以配置成单主单从,单主多从,互为主从。

    SPI的片选可以扩充选择16个外设,这时PCS输出=NPCS,说NPCS0~3接4-16译码器,这个译码器是需要外接4-16译码器,译码器的输入为NPCS0~3,输出用于16个外设的选择。

    1.2.协议举例

    SPI是一个环形总线结构,由ss(cs)、sck、sdi、sdo构成,其时序其实很简单,主要是在sck的控制下,两个双向移位寄存器进行数据交换。
           假设下面的8位寄存器装的是待发送的数据10101010,上升沿发送、下降沿接收、高位先发送。
           那么第一个上升沿来的时候 数据将会是sdo=1;寄存器=0101010x。下降沿到来的时候,sdi上的电平将所存到寄存器中去,那么这时寄存器=0101010sdi,这样在 8个时钟脉冲以后,两个寄存器的内容互相交换一次。这样就完成里一个spi时序。 

    举例: 
           假设主机和从机初始化就绪:并且主机的sbuff=0xaa,从机的sbuff=0x55,下面将分步对spi的8个时钟周期的数据情况演示一遍:假设上升沿发送数据

    图片点击可在新窗口打开查看

    这样就完成了两个寄存器8位的交换,上面的上表示上升沿、下表示下降沿,sdi、sdo相对于主机而言的。其中ss引脚作为主机的时候,从机可以把它拉底被动选为从机,作为从机的是时候,可以作为片选脚用。根据以上分析,一个完整的传送周期是16位,即两个字节,因为,首先主机要发送命令过去,然后从机根据主机的命令准备数据,主机在下一个8位时钟周期才把数据读回来。

         

      SPI 总线是Motorola公司推出的三线同步接口,同步串行3线方式进行通信:一条时钟线SCK,一条数据输入线MOSI,一条数据输出线MISO;用于CPU与各种外围器件进行全双工、同步串行通讯。SPI主要特点有:可以同时发出和接收串行数据;可以当作主机或从机工作;提供频率可编程时钟;发送结束 中断标志;写冲突保护;总线竞争保护等。下图示出SPI总线工作的四种方式,其中使用的最为广泛的是SPI0和SPI3方式 (实线表示):                  

                                                        图片点击可在新窗口打开查看

                                                                                                   SPI总线四种工作方式

    SPI 模块为了和外设进行数据交换,根据外设工作要求,其输出串行同步时钟极性和相位可以进行配置,时钟极性(CPOL)对传输协议没有重大的影响。

    • 如果 CPOL=0,串行同步时钟的空闲状态为低电平;
    • 如果CPOL=1,串行同步时钟的空闲状态为高电平。时钟相位(CPHA)能够配置用于选择两种不同的传输协议之一进行数据传输。
    • 如果CPHA=0,在串行同步时钟的第一个跳变沿(上升或下降)数据被采样;
    • 如果CPHA=1,在串行同步时钟的第二个跳变沿(上升或下降)数据被采样。SPI主模块和与之通信的外设备时钟相位和极性应该一致。


    补充

    上文中最后一句话:SPI主模块和与之通信的外设备时钟相位和极性应该一致。个人理解这句话有2层意思:其一,主设备SPI时钟和极性的配置应该由外设来决定;其二,二者的配置应该保持一致,即主设备的SDO同从设备的SDO配置一致,主设备的SDI同从设备的SDI配置一致。因为主从设备是在SCLK的控制下,同时发送和接收数据,并通过2个双向移位寄存器来交换数据。工作原理演示如下图:

    图片点击可在新窗口打开查看

    上升沿主机SDO发送数据1,同时从设备SDO发送数据0;紧接着在SCLK的下降沿的时候从设备的SDI接收到了主机发送过来的数据1,同时主机也接收到了从设备发送过来的数据0.

    1.3.协议心得

    SPI接口时钟配置心得:

      在主设备这边配置SPI接口时钟的时候一定要弄清楚从设备的时钟要求,因为主设备这边的时钟极性和相位都是以从设备为基准的。因此在时钟极性的配置上一定要搞清楚从设备是在时钟的上升沿还是下降沿接收数据,是在时钟的下降沿还是上升沿输出数据。但要注意的是,由于主设备的SDO连接从设备的SDI,从设备的SDO连接主设备的SDI,从设备SDI接收的数据是主设备的SDO发送过来的,主设备SDI接收的数据是从设备SDO发送过来的,所以主设备这边SPI时钟极性的配置(即SDO的配置)跟从设备的SDI接收数据的极性是相反的,跟从设备SDO发送数据的极性是相同的。下面这段话是Sychip Wlan8100 Module Spec上说的,充分说明了时钟极性是如何配置的:

    The 81xx module will always input data bits at the rising edge of the clock, and the host will always output data bits on the falling edge of the clock.

    意思是:主设备在时钟的下降沿发送数据,从设备在时钟的上升沿接收数据。因此主设备这边SPI时钟极性应该配置为下降沿有效。

    又如,下面这段话是摘自LCD Driver IC SSD1289:

    SDI is shifted into 8-bit shift register on every rising edge of SCK in the order of data bit 7, data bit 6 …… data bit 0.

    意思是:从设备SSD1289在时钟的上升沿接收数据,而且是按照从高位到地位的顺序接收数据的。因此主设备的SPI时钟极性同样应该配置为下降沿有效。

    时钟极性和相位配置正确后,数据才能够被准确的发送和接收, 因此应该对照从设备的SPI接口时序或者Spec文档说明来正确配置主设备的时钟。

    2.SPI协议软件模拟

    2.1.单片机软件模拟SPI接口—加深理解SPI总线协议

              SPI(Serial Peripheral Interfacer 串行外设接口)是摩托罗拉公司推出的一种同步串行通讯接口,用于微处理器臌控制器和外围扩展芯片之间的串行连接,现已发展成为一种工业标准,目前,各半导体公司推出了大量的带有SPI接口的具有各种各样功能的芯片,如RAM,EEPROM,FlashROM,A/D转换器、D/A转换器、LED/LED显示驱动器、I/O接口芯片、实时时钟、UART收发器等等,为用户的外围扩展提供了极其灵活而价廉的选择。由于SPI总线接口只占用微处理器四个I/O口线,采用SPI总线接口可以简化电路没计,节省很多常规电路中的接口器件和I/O口线,提高设计的可靠性。

            现以 AT89C205l单片机模拟SPI总线操作串行EEPROM 93CA6为例,如图1所示,介绍利用单片机的I/O口通过软件模拟SPI总线的实现方法。在这里,仅介绍读命令的时序和应用子程序。 

    2.2.93C46存储器SPI总线的工作原理

              93CA6作为从设备,其SPI接口使用4条I/O口线:串行时钟线(SK)、输出数据线DO、输入数据线DI和高电平有效的从机选择线CS。其数据的传输格式是高位(MSB)在前,低位(LsB)在后。93C46的SPI总线接口读命令时序如图2所示。 

    2.3.软件模拟SPI接口的实现方法 

              对于不带SPI串行总线接口的AT89C2051单片 机来说,可以使用软件来模拟SPI的操作,图1所示 为AT89C2051单片机与串行EEPROM 93C46的硬件 连接图,其中,P1.0模拟SPI主设备的数据输出端 SDO,P1.2模拟SPI的时钟输出端SCK,P1.3模拟 SPI的从机选择端SCS,P1.1模拟SPI的数据输入 SDI。
             上电复位后首先先将P1.2(SCK)的初始状态设置为0(空闲状态)。
             读操作:AT89C2051首先通过P1.0口发送1位起始位(1),2位操作码(10),6位被读的数据地址(A5A4A3A2A1A0),然后通过P1.1口读1位空位(0),之后再读l6位数据(高位在前)。
             写操作:AT89C2051首先通过P1.0口发送1位起始位(1),2位操作码(01),6位被写的数据地址(A5A4A3A2A1A0),之后通过P1.0口发送被写的l6位数据(高位在前),写操作之前要发送写允许命令,写之后要发送写禁止命令。
             写允许操作(WEN)):写操作首先发送1位起始位(1),2位操作码(00),6位数据(11XXXX)。              

             写禁止操作(WDS)):写操作首先发送1位起始位(1),2位操作码(00),6位数据(00XXXX)。

            下面介绍用C51模拟SPI的子程序。

     

    复制代码

     1 //首先定义好I/O口
     2 sbit SDO=P1^0;
     3 sbit SDI=P1^1;
     4 sbit SCK=P1^ 2;
     5 sbit SCS=P1^3;
     6 sbit ACC_7= ACC^7;
     7 unsigned int SpiRead(unsigned char add)
     8 {
     9     unsigned char i;
    10     unsigned int datal6;
    11     add&=0x3f;/*6位地址*/
    12     add |=0x80;/*读操作码l0*/
    13     SDO=1;/*发送1为起始位*/
    14     SCK=0;
    15     SCK=1;
    16     for(i=0;<8;i++)/*发送操作码和地址*/
    17     {
    18         if(add&0x80==1)
    19             SDO=1;
    20         else 
    21             SDO=0;
    22         SCK=0;/*从设备上升沿接收数据*/
    23         SCK=1;
    24         add<<= 1;
    25     }
    26     SCK=1;/*从设备时钟线下降沿后发送数据,空读1位数据*/
    27     SCK=0;
    28     datal6<<= 1;/*读16位数据*/
    29     for(i=0;<16;i++)
    30     {
    31         SCK= 1;
    32         _nop_();
    33         if(SDI==1)
    34             datal6|=0x01;
    35         SCK =0;
    36         datal6< < =1;
    37     }
    38     return datal6;
    39 }

    复制代码

     

      对于不同的串行接口外围芯片,它们的时钟时序是不同的。上述子程序是针对在SCK的上升沿输入(接收)数据和在下降沿输出(发送)数据的器件。这些子程序也适用于在串行时钟)的上升沿输入和下降沿输出的其它各种串行外围接口芯片,只要在程序中改变P1.2(SCK)的输出电平顺序进行相应调整即可。

    展开全文
  • [SPI].SPI协议详解

    2020-06-21 18:21:05
    1、 SPI简介 SPI,是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口。是Motorola首先在其MC68HCXX系列处理器上定义的。SPI接口主要应用在 EEPROM,FLASH,实时时钟,AD转换器,还有数字信号...

     

    转自:http://www.sohu.com/a/211324861_468626

    1、 SPI简介

    SPI,是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口。是Motorola首先在其MC68HCXX系列处理器上定义的。SPI接口主要应用在 EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间。SPI是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议。

    2、 SPI特点

    2.1采用主-从模式(Master-Slave) 的控制方式

    SPI 规定了两个 SPI 设备之间通信必须由主设备 (Master) 来控制次设备 (Slave). 一个 Master 设备可以通过提供 Clock 以及对 Slave 设备进行片选 (Slave Select) 来控制多个 Slave 设备, SPI 协议还规定 Slave 设备的 Clock 由 Master 设备通过 SCK 管脚提供给 Slave 设备, Slave 设备本身不能产生或控制 Clock, 没有 Clock 则 Slave 设备不能正常工作

    2.2采用同步方式(Synchronous)传输数据

    Master 设备会根据将要交换的数据来产生相应的时钟脉冲(Clock Pulse), 时钟脉冲组成了时钟信号(Clock Signal) , 时钟信号通过时钟极性 (CPOL) 和 时钟相位 (CPHA) 控制着两个 SPI 设备间何时数据交换以及何时对接收到的数据进行采样, 来保证数据在两个设备之间是同步传输的.

    2.3数据交换(Data Exchanges)

    SPI 设备间的数据传输之所以又被称为数据交换是因为 SPI 协议规定一个 SPI 设备不能在数据通信过程中仅仅只充当一个 "发送者(Transmitter)" 或者 "接收者(Receiver)". 在每个 Clock 周期内, SPI 设备都会发送并接收一个 bit 大小的数据(不管主设备好还是从设备), 相当于该设备有一个 bit 大小的数据被交换了. 一个 Slave 设备要想能够接收到 Master 发过来的控制信号, 必须在此之前能够被 Master 设备进行访问 (Access). 所以, Master 设备必须首先通过 SS/CS pin 对 Slave 设备进行片选, 把想要访问的 Slave 设备选上. 在数据传输的过程中, 每次接收到的数据必须在下一次数据传输之前被采样. 如果之前接收到的数据没有被读取, 那么这些已经接收完成的数据将有可能会被丢弃, 导致 SPI 物理模块最终失效. 因此, 在程序中一般都会在 SPI 传输完数据后, 去读取 SPI 设备里的数据, 即使这些数据(Dummy Data)在我们的程序里是无用的(虽然发送后紧接着的读取是无意义的,但仍然需要从寄存器中读出来)

    2.4 SPI有四种传输模式

    上升沿、下降沿、前沿、后沿触发。当然也有MSB和LSB传输方式.

    2.5 SPI只有主模式和从模式之分。

    没有读和写的说法,因为实质上每次SPI是主从设备在交换数据。也就是说,你发一个数据必然会收到一个数据;你要收一个数据必须也要先发一个数据。

    3、 工作机制

    3.1概述

    上图只是对 SPI 设备间通信的一个简单的描述, 下面就来解释一下图中所示的几个组件(Module):

    • SSPBUF,Synchronous Serial Port Buffer, 泛指 SPI 设备里面的内部缓冲区, 一般在物理上是以 FIFO 的形式, 保存传输过程中的临时数据;
    • SSPSR, Synchronous Serial Port Register, 泛指 SPI 设备里面的移位寄存器(Shift Regitser), 它的作用是根据设置好的数据位宽(bit-width) 把数据移入或者移出 SSPBUF;
    • Controller, 泛指 SPI 设备里面的控制寄存器, 可以通过配置它们来设置 SPI 总线的传输模式。

    通常情况下, 我们只需要对上图所描述的四个管脚(pin) 进行编程即可控制整个 SPI 设备之间的数据通信:

    • SCK, Serial Clock, 主要的作用是 Master 设备往 Slave 设备传输时钟信号, 控制数据交换的时机以及速率;
    • SS/CS, Slave Select/Chip Select, 用于 Master 设备片选 Slave 设备, 使被选中的 Slave 设备能够被 Master 设备所访问;
    • SDO/MOSI, Serial Data Output/Master Out Slave In, 在 Master 上面也被称为 Tx-Channel, 作为数据的出口, 主要用于 SPI 设备发送数据;
    • SDI/MISO, Serial Data Input/Master In Slave Out, 在 Master 上面也被称为 Rx-Channel, 作为数据的入口, 主要用于SPI 设备接收数据;

    SPI 设备在进行通信的过程中, Master 设备和 Slave 设备之间会产生一个数据链路回环(Data Loop), 就像上图所画的那样, 通过 SDO 和 SDI 管脚, SSPSR 控制数据移入移出 SSPBUF, Controller 确定 SPI 总线的通信模式, SCK 传输时钟信号。

    3.2 Timing

    上图通过 Master 设备与 Slave 设备之间交换1 Byte 数据来说明 SPI 协议的工作机制.

    首先, 在这里解释一下相位和极性的概念

    3.2.1 SPI相关的缩写或说法

    SPI的极性Polarity和相位Phase,最常见的写法是CPOL和CPHA,不过也有一些其他写法,简单总结如下:

    1. CKPOL (Clock Polarity) = CPOL = POL = Polarity = (时钟)极性
    2. CKPHA (Clock Phase) = CPHA = PHA = Phase = (时钟)相位
    3. SCK=SCLK=SPI的时钟
    4. Edge=边沿,即时钟电平变化的时刻,即上升沿(rising edge)或者下降沿(falling edge)

    对于一个时钟周期内,有两个edge,分别称为:

    • Leading edge=前一个边沿=第一个边沿,对于开始电压是1,那么就是1变成0的时候,对于开始电压是0,那么就是0变成1的时候;
    • Trailing edge=后一个边沿=第二个边沿,对于开始电压是1,那么就是0变成1的时候(即在第一次1变成0之后,才可能有后面的0变成1),对于开始电压是0,那么就是1变成0的时候;

    3.2.2 SPI的相位和极性

    CPOL和CPHA,分别都可以是0或时1,对应的四种组合就是:

    • Mode 0 CPOL=0, CPHA=0
    • Mode 1 CPOL=0, CPHA=1
    • Mode 2 CPOL=1, CPHA=0
    • Mode 3 CPOL=1, CPHA=1

    3.2.3 CPOL极性

    先说什么是SCLK时钟的空闲时刻,其就是当SCLK在数发送8个bit比特数据之前和之后的状态,于此对应的,SCLK在发送数据的时候,就是正常的工作的时候,有效active的时刻了。

    先说英文,其精简解释为:Clock Polarity = IDLE state of SCK。

    再用中文详解:

    SPI的CPOL,表示当SCLK空闲idle的时候,其电平的值是低电平0还是高电平1:

    • CPOL=0,时钟空闲idle时候的电平是低电平,所以当SCLK有效的时候,就是高电平,就是所谓的active-high;
    • CPOL=1,时钟空闲idle时候的电平是高电平,所以当SCLK有效的时候,就是低电平,就是所谓的active-low;

    3.2.4 CPHA相位

    首先说明一点,capture strobe = latch = read = sample,都是表示数据采样,数据有效的时刻。相位,对应着数据采样是在第几个边沿(edge),是第一个边沿还是第二个边沿,0对应着第一个边沿,1对应着第二个边沿。

    对于:

    CPHA=0,表示第一个边沿:

    • 对于CPOL=0,idle时候的是低电平,第一个边沿就是从低变到高,所以是上升沿;
    • 对于CPOL=1,idle时候的是高电平,第一个边沿就是从高变到低,所以是下降沿;

    CPHA=1,表示第二个边沿:

    • 对于CPOL=0,idle时候的是低电平,第二个边沿就是从高变到低,所以是下降沿;
    • 对于CPOL=1,idle时候的是高电平,第一个边沿就是从低变到高,所以是上升沿;

    还是上图大家更容易看懂

    3.2.5 软件中如何设置SPI的极性和相位

    SPI分主设备和从设备,两者通过SPI协议通讯。

    而设置SPI的模式,是从设备的模式,决定了主设备的模式。

    所以要先去搞懂从设备的SPI是何种模式,然后再将主设备的SPI的模式,设置和从设备相同的模式,即可正常通讯。

    对于从设备的SPI是什么模式,有两种:

    3.2.5.1固定的,有SPI从设备硬件决定的

    SPI从设备,具体是什么模式,相关的datasheet中会有描述,需要自己去datasheet中找到相关的描述,即:

    关于SPI从设备,在空闲的时候,是高电平还是低电平,即决定了CPOL是0还是1;

    然后再找到关于设备是在上升沿还是下降沿去采样数据,这样就是,在定了CPOL的值的前提下,对应着可以推算出CPHA是0还是1了。

    3.2.5.2 可配置的,由软件自己设定

    从设备也是一个SPI控制器,4种模式都支持,此时只要自己设置为某种模式即可。

    然后知道了从设备的模式后,再去将SPI主设备的模式,设置为和从设备模式一样,即可。

    对于如何配置SPI的CPOL和CPHA的话,不多细说,多数都是直接去写对应的SPI控制器中对应寄存器中的CPOL和CPHA那两位,写0或写1即可。

    3.3 SSPSR

    SSPSR 是 SPI 设备内部的移位寄存器(Shift Register). 它的主要作用是根据 SPI 时钟信号状态, 往 SSPBUF 里移入或者移出数据, 每次移动的数据大小由 Bus-Width 以及 Channel-Width 所决定。

    Bus-Width 的作用是指定地址总线到 Master 设备之间数据传输的单位.

    例如, 我们想要往 Master 设备里面的 SSPBUF 写入 16 Byte 大小的数据: 首先, 给 Master 设备的配置寄存器设置 Bus-Width 为 Byte; 然后往 Master 设备的 Tx-Data 移位寄存器在地址总线的入口写入数据, 每次写入 1 Byte 大小的数据(使用 writeb 函数); 写完 1 Byte 数据之后, Master 设备里面的 Tx-Data 移位寄存器会自动把从地址总线传来的1 Byte 数据移入 SSPBUF 里; 上述动作一共需要重复执行 16 次.

    Channel-Width 的作用是指定 Master 设备与 Slave 设备之间数据传输的单位. 与 Bus-Width 相似, Master 设备内部的移位寄存器会依据 Channel-Width 自动地把数据从 Master-SSPBUF 里通过 Master-SDO 管脚搬运到 Slave 设备里的 Slave-SDI 引脚, Slave-SSPSR 再把每次接收的数据移入 Slave-SSPBUF里.通常情况下, Bus-Width 总是会大于或等于 Channel-Width, 这样能保证不会出现因 Master 与 Slave 之间数据交换的频率比地址总线与 Master 之间的数据交换频率要快, 导致 SSPBUF 里面存放的数据为无效数据这样的情况.

    3.4 SSPBUF

    我们知道, 在每个时钟周期内, Master 与 Slave 之间交换的数据其实都是 SPI 内部移位寄存器从 SSPBUF 里面拷贝的. 我们可以通过往 SSPBUF 对应的寄存器 (Tx-Data / Rx-Data register) 里读写数据, 间接地操控 SPI 设备内部的 SSPBUF.

    例如, 在发送数据之前, 我们应该先往 Master 的 Tx-Data 寄存器写入将要发送出去的数据, 这些数据会被 Master-SSPSR 移位寄存器根据 Bus-Width 自动移入 Master-SSPBUF 里, 然后这些数据又会被 Master-SSPSR 根据 Channel-Width 从 Master-SSPBUF 中移出, 通过 Master-SDO 管脚传给 Slave-SDI 管脚, Slave-SSPSR 则把从 Slave-SDI 接收到的数据移入 Slave-SSPBUF 里. 与此同时, Slave-SSPBUF 里面的数据根据每次接收数据的大小(Channel-Width), 通过 Slave-SDO 发往 Master-SDI, Master-SSPSR 再把从 Master-SDI 接收的数据移入 Master-SSPBUF.在单次数据传输完成之后, 用户程序可以通过从 Master 设备的 Rx-Data 寄存器读取 Master 设备数据交换得到的数据.

    3.5 Controller

    Master 设备里面的 Controller 主要通过时钟信号(Clock Signal)以及片选信号(Slave Select Signal)来控制 Slave 设备. Slave 设备会一直等待, 直到接收到 Master 设备发过来的片选信号, 然后根据时钟信号来工作.

    Master 设备的片选操作必须由程序所实现. 例如: 由程序把 SS/CS 管脚的时钟信号拉低电平, 完成 SPI 设备数据通信的前期工作; 当程序想让 SPI 设备结束数据通信时, 再把 SS/CS 管脚上的时钟信号拉高电平.

    4. SPI举例

    上面说了那么多,在这里我来举一个例子帮助大家理解。

    SPI是一个环形总线结构,由ss(cs)、sck、sdi、sdo构成,其时序其实很简单,主要是在sck的控制下,两个双向移位寄存器进行数据交换。

    假设下面的8位寄存器装的是待发送的数据10101010,上升沿发送、下降沿接收、高位先发送。

    那么第一个上升沿来的时候 数据将会是sdo=1;寄存器=0101010x。下降沿到来的时候,sdi上的电平将所存到寄存器中去,那么这时寄存器=0101010sdi,这样在 8个时钟脉冲以后,两个寄存器的内容互相交换一次。这样就完成里一个spi时序。

    举例:

    假设主机和从机初始化就绪:并且主机的sbuff=0xaa,从机的sbuff=0x55,下面将分步对spi的8个时钟周期的数据情况演示一遍:假设上升沿发送数据

    这样就完成了两个寄存器8位的交换,上面的上表示上升沿、下表示下降沿,sdi、sdo相对于主机而言的。已经很接近理解了,下一步就是把 上面的过程转为动画

    5、 STM32驱动

    STM32的spi较为简单,因为STM32的内部集成有SPI。

    5.1 SPI的初始化

    复制代码

    void SPIInit(void)
    {
        SPI_InitTypeDef SPI_InitStructure;
        //初始化SPI与GPIO口的连接
        FLASH_GPIO_Init();
        /*!< Deselect the FLASH: Chip Select high */
        CE_High();
        /*!< SPI configuration */
        SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
        SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
        SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
        SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
        SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
        SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
        SPI_InitStructure.SPI_BaudRatePrescaler =                 
        SPI_BaudRatePrescaler_8;
        SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
        SPI_InitStructure.SPI_CRCPolynomial = 7;
        SPI_Init(SPI1, &SPI_InitStructure);
        /*!< Enable the sFLASH_SPI */
        SPI_Cmd(SPI1, ENABLE);
    }    

    复制代码

    5.2 SPI写1个字节

    复制代码

    uint8 Send_Byte(uint8 data)
    {
        //发送不为空
        while(!(SPI1->SR & SPI_I2S_FLAG_TXE));
        SPI1->DR = data;
        //读取收到的数据
        while(!(SPI1->SR & SPI_I2S_FLAG_RXNE));
        return SPI1->DR;
    }    

    复制代码

    5.3 SPI读一个字节

    复制代码

    uint8 Get_Byte(void)
    {
        //发送不为空
        while(!(SPI1->SR & SPI_I2S_FLAG_TXE)); // 发送缓冲为空,跳出循环
        SPI1->DR = 0xFF; //
        //读取收到的数据
        while(!(SPI1->SR & SPI_I2S_FLAG_RXNE)); //接受缓冲非空,跳出循环
        return SPI1->DR;
    }

    复制代码

     

    展开全文
  • 2、SPI协议详解

    2020-10-13 09:49:56
    实际它并没有统一的协议规范,只是随之其广泛的应用,形成了习惯性的标准。具体的还是要参考特定的器件手册。 二、连接方式 SPI一对一 SPI用于在单个主控制器和一个或多个从设备之间交换数据。提供...
  • SPI协议详解(图文并茂+超详细)

    千次阅读 多人点赞 2020-11-03 01:23:31
    因为之前写过一篇UART,通用串行异步通讯协议,UART的相关资料 因为UART没有时钟信号,无法控制何时发送数据,也无法保证双发按照完全相同的速度接收数据。因此,双方以不同的速度进行数据接收和发送,就会出现问题...
  • 正是出于这种简单易用的特性,现在越来越多的芯片集成了SPI通信协议,如FLASH、AD转换器等。SPI的通信原理比较简单,它以主从方式工作,通常有一个主设备和一个或多个从设备。 二、SPI接口 SPI通信需要四根线,分别...
  • 第001节_SPI协议介绍 市面上的开发板很少接有SPI设备,但是SPI协议在工作中经常用到。我们开发了SPI模块,上面有SPI Flash和SPI OLED。OLED就是一块显示器。 我们裸板程序会涉及两部分: 用GPIO模拟SPI 用S3C...
  • 先说串口因为之前写过一篇UART,通用串行异步通讯协议,UART的相关资料因为UART没有时钟信号,无法控制何时发送数据,也无法保证双发按照完全相同的速度接收数据。因此,双方以不同的速度进行数据接收和发送,就会...

空空如也

空空如也

1 2 3 4 5 ... 14
收藏数 264
精华内容 105
关键字:

spi协议详解