关于SPI的知识

 关于SPI接口的知识

  在SPI通信中,主机掌握着主动权,数据都是由主机发出的,从机回数据时,也是需要主机在MOSI线上(主出从入)发送数据,从机才同时在MISO(主入从出)线上返回数据,从机总是被被动操作的,不需要从机返回数据时,由于通信时从机仍然会返回数据,但这些数据主机是不需要的,此时,可以忽略他们。

  另外,我想补充一点,可能有人要问了,那从机那边就是有数据急着要发送给主机怎么办?说的不负责任点的话,这个问题,还真没办法,不过一般是采用其它方法的,比如NRF24L01模块,它是SPI接口的,实际应用中,不可能只有发送,没有接收的,那模块接收到的数据如何发送给主控芯片呢?要知道前面还说SPI接口里面,从机不能主动给主机发送数据的,其实这时候,模块的设计者都考虑到这些问题了,NRF24L01模块上有IRQ中断脚,有数据时,会通过这个中断脚触发主控芯片,告诉他,这边有数据需要交给你,主控相应中断后,开始操作SPI,也就是继续一边发送数据,一边接收从机的数据,不过这时主机发送的数据都是一些没用的东西,因为要想接收数据,必须得同时发送数据,所以随便发点,关键是要通过发送,来接收到从机的数据。

  SPI时钟线"SCK":一个时钟线,这个时钟是通信的基准,两边设备通过时钟线的跳边沿来操作没一位数据的发送和接收,在STM32F103系列中,SPI最高时钟是18MHz,时钟频率可由PCLK分频取得,在“SPI->CR1”寄存器中,由三个位来确定分频,可进行2/4/8/16/32/64/128/256分频;

  时钟极性:时钟极性(CPOL)对传输协议没有重大的影响,如果CPOL=0,串行同步时钟的空闲状态为低电平;如果CPOL=1,串行同步时钟的空闲状态为高电平。

  时钟相位:时钟相位(CPHA)能够配置用于选择两种不同的传输协议之一进行数据传输,如果 CPHA=0,在串行同步时钟的第一个跳变沿(上升或下降)数据被采样;如果CPHA=1,在串行同步时钟的第二个跳变沿(上升或下降)数据被采样。 

  关于时钟相位:

    相位,对应着数据采样是在第几个边沿(edge),是第一个边沿还是第二个边沿,0对应着第一个边沿,1对应着第二个边沿。

    对于:

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

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

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

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

    对于CPOL=0,空闲时候的是低电平,第二个边沿就是从高变到低,所以是下降沿;

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

    其实,如果学过其它通信接口的,比如说我,这里面还有个小小的疑问,如果不看上面这样的说明,这个疑问会更加明显,那就是,为什么SPI通信里面,不说上升/下降沿采集/发送,而是说第一/第二个下降/上升沿采集/发送,因为有些通信接口是靠上升下降沿来区分数据位的,看到这里,疑问就清楚了,因为SPI里面上升下降沿是可以不同设置的,如果人家只是说,上升/下降沿采集/发送,那就片面了,这样说是错的,因为上升下降是可以设置的,所以用第一/第二来说明才正确。

  关于时钟极性和相位的图:

 

  这个图是,这个图中,其实有4中组合,也就是SPI通信的4种不同方式,分别是:极性0,相位1;极性1,相位0;极性1,相位0;极性1,相位1;

看懂这个图,基本上SPI的通信时序就差不多明白了。

  最后,记一下编程思路:

  拿STM32举例:

  第一步,不用问,先使能SPI的时钟,设置通信所需管脚,将这些管脚设为第二功能,记得管脚时钟也要打开;

  第二步:设置分频,为SPI时钟线设置波特率;

  第三步:STM32手册里面好像还要设置一个"SS输出使能",不知道不设置行不行,在手册SPI->CR2寄存器里面;

  第4步:SPI使能;

  SPI数据发送和接收:

  还是拿STM32的程序说明下,SPI接口发送的时候,还会有接收,所以发送和接收是写到一块的,如:

  

u8 Spi1ReadWriteByte(u8 txData)
{                     
    while((SPI1->SR & (1<<1))==0);    //等待发送区空
    SPI1->DR = txData;                   //发送一个byte
    while((SPI1->SR & (1<<0))==0);    //等待接收完一个byte
     return SPI1->DR;                  //返回收到的数据
}

   关于这个程序中,其实我还有个疑问,但是后来看到一篇文章后想明白了,疑问大概是这样:上面我们知道,程序发送之前,等待发送区为空,程序接收之前,等待接收完成标志,这两个标志其实都是“上次发送/接收”的完成标志,好了,先说到这。疑问具体是什么呢?我们知道SPI通信里面,发送和接收是同时进行的,主机通过MOSI发送一位,同时又从MISO接收一位,而上面程序中,明显是发送了一整个字节,然后才又去接收一整个字节,而SPI发送与接收是同时按位进行的,应该是每发送一个位,就要等待接收一个位才对,其实不是这么回事,这个程序是实用的STM32的硬件SPI,其实上面说的那些繁杂的过程硬件层面上都已经做好了,这里的“等待发送区空”和“等待接收完”其实更多的是出于保险起见,说保险起见还是有点不对,应该说是就该这么写,这两个标志是STM32硬件里面操作的,不是“SPI通信”本身的东西,是我们在使用STM32进行通信时,需要每次都对这两个标志进行判断的。

  又想到一点,关于时钟问题,SPI通信里面主机与从机的时钟是不需要可以的设置为完全一致的,更多的是按照主机发出的频率进行数据采集读写操作的,换句话说,主机的SCK线上的频率,就是这个SPI通信的主频,但是需要注意的是,主机发出的频率不能高出从机所能接受的频率,别从机明明只能接受8M,但主机来个16M,那就不行了。

原文地址:https://www.cnblogs.com/data-base-of-ssy/p/6677520.html