十四.SPI使用1——SPI基础和ICM20608的使用

在日常设备使用中,最常用通讯协议就是I2C和SPI了,前面过了一遍I2C,I2C接口速度最快能到400K,但是SPI能到几时兆。下面我们来实现SPI的使用。

SPI接口

SPI硬件定义

SPI和I2C一样属于一种串行通讯协议,但是I2C需要2根线实现通讯,这样就限制了传输的速度;SPI则需要4根线才能数据通信(如果是单向通讯的话可以只用3根线)这四根线的定义如下:

  1. CS/SS(Chip Select/Slave Select)片选信号,用来选择需要进行通讯的设备。I2C接口是通过主机发送从机地址来实现通讯的,SPI就不需要发送从机地址,通讯时直接将需要对设备对应的片选信号拉低就可以了。
  2. SCK(Serial Clock)串行时钟,和I2C的SCL一样用来提供通讯时钟。
  3. MOSI/SDO(Master Out Slave In/Serial Data Output)主机输出从机输入信号线,传输方向固定,用来从主机向从机发送数据。
  4. MISO/SDI(Master In Slave Out/Serial Data Input)和前面的信号线相反,由从机向主机发送数据。

SPI通信都是由主机发起,主机提供了通讯所需要的时钟,然后通过每个CS信号指定多个从机之间的某一个。硬件接口如下图

 

SPI工作模式

SPI有4种工作模式,通过串行时钟的极性(CPOL——Clock Polarity)和相位(CPHA——Clock Phase)的搭配来切换,主要就是描述了时钟在传输数据时的状态

CPOL=0:串行时钟空闲时为低电平

CPOL=1:串行时钟空闲时为高电平

CPHA=0:时钟的第一个跳变沿采集数据

CPHA=1:时钟的第二个跳变沿采集数据

不同模式下传输的时钟状态如下图(图截取自正点原子驱动开发指南)

 

 我们一般使用,都是按照第4种状态——CPOL=0,CPHA=0。

数据时序

我们按照前面CPOL和CPHA都为0时的时序图分析一下:

 

 因为SPI是全双工通讯的, 读和写可以同时完成,所以时序比区分读写时序的I2C要简单的多。上面的图中,由于,CPOL和CPHA都为0当CS信号拉低以后第一个时钟拉高的时候开始传输数据,MOSI数据线上数据为0b11010010,即主机发送0xD2给片选信号选中的设备,同时接收到MISO数据线上数据0b01100110(0x66)。整个数据传输过程就完成了。

IMX6ULL的SPI接口

I.MX6LL上的SPI全称叫做ECSPI(Enhanced Configureable Serial Perpheral Interface),具有64*32个接收FIFO(RXFIFO)和64*32个发送FIFO(TXFIFO)。整体架构如下:

 

具备如下特点:

  • 一共具备4组SPI接口
  • 全双工异步通讯
  • 主从状态可配置
  • 4个片选信号,支持多个从机
  • 发送和接收数据都带有一个32位64的FIFO 
  • 时钟、片选信号及CPOL和CPHA可设置
  • 支持DMA(Direct Memory Access)操作,直接操作寄存器

寄存器定义

I.MX6ULL提供了4组SPI接口,每组接口对应了10个寄存器来控制

 

我们一个个来看看这10个寄存器都是怎么用的

Receive Data Register(ECSPIx_RXDATA)

接收数据寄存器, 只读,由于我们每次传输数据都是一个一个字节进行的,所以一般情况只用到低8位。读取数据时要等到RR标志位有相应动作才能进行。

Transmit Data Register (ECSPIx_TXDATA)

发送数据寄存器,我们把数据写入到该寄存器,SPI控制器就会把数据发送出去。

Control Register (ECSPIx_CONREG)

控制寄存器。这是个重点,寄存器结构图如下

 

EN(bit[0])使能位,0时关闭SPI

HT(bit[1])Hardware Trigger 模式使能,IMX6UL不支持该功能,可以忽略

XCH(bit[2])master模式下起作用,为0时开启SPI突发访问

SMC(bit[3])开始模式控制,只能在master模式下起作用,设置为1时在我们向TXFIFO写入数据时马上开启SPI突发访问,发送数据。

CHANNEL_MODE(bit[7:4)设置SPI主从模式,由于有4个片选信号,每个接口可以接4个设备,4个bit对应4个接口,我们需要使用SS0片选,也就对应通道0,bit[4]要设置为1。

POST_DIVIDER(bit[11:8) 分频,SPI时钟第二步分频设置控制

PRE_DIVIDER(bit[15:12])SPI预分频,时钟分频设置第一步

DRCTL(bit[17:16])Data Ready Control信号控制,只在master模式下有用,主要用来确定突发访问的信号触发状态:00时不关心该信号,01时为边沿触发,10时为电平触发。

CHANNEL_SELECT(bit[19:18])选择通道,我们使用通道0,要将这两个bit设置为00。

BURST_LENGTH(bit[31:20])突发访问长度,12个bit,说明在一次SPI发送数据过程中最大可以发送2^12bit到数据,寄存器可以被设置0x0~0xFFF,如下表所示。

我们每次发送数据长度为1个字节,也就是8bit,可以将其设置为0x7。

Config Register (ECSPIx_CONFIGREG)

配置寄存器,结构如下表

 

每个控制单元都是4个bit,对应控制其下面对应的4个通道。

SCLK_PHA(bit[4:0]),时钟相位控制模式,4个bit控制4个通道,我们要将bit[0]设置为0,对应CPHA=0,即串行时钟第一个跳变沿开始采集数据

SCLK_POL(bit[7:4]),时钟极性控制模式,使用中要讲通道0的值设置为0(bit[4]=0),即空闲时为低电平

SS_CTL(bit[11:8]),片选信号控制,大概意思就是0时每次突发产生1个信号。我们设置为0。

SS_POL(bit[15:12]),片选信号极性设置,0时片选信号低电平有效,1时为高电平,设置为0

DATA_CTL(bit[19:16]) 数据空闲为状态,0时数据线为高电平

SCLK_CTL(bit[13:20]),时钟空闲状态,要和前面CPOL保持一致

HT_LENGTH(bit[21:28]),HT长度,我们不使用

Interrupt Control Register (ECSPIx_INTREG)

中断控制寄存器,只有低8位有效

 

 我们暂时不使用,只把说明放在下面

 

主要就是几个中断相关的控制位。

Status Register (ECSPIx_STATREG)

状态寄存器,低8位有效

 

不论在读写的过程中都要判断状态寄存器的状态

TE(bit[0]) TXFIFO Empty,1时说明TXFIFO为空,发送数据前要等到FIFO空了以后才可以写入新的数据。要在发送数据前检查该位是否为1

TDR(bit[1])TXFIFO Data Request,1时说明FIFO中有数据需求,即有效数据数量低于指定值。

TF(bit[2])TXFIFO Full,1时说明FIFO数据满

RR(bit[3])RXFIFO Ready,1时说明有至少存在1个数据(32位)在FIFO中等待读取。所以在接收数据的时候要等待这个位为1

RDR(bit[4])RXFIFO Data Request,效果同TDR

RF(bit[5])RXFIFO Full,读FIFO数据满

RO(bit[6])RXFIFO Overflow,1时表明RXFIFO溢出,写1清除

TC(bit[7])Transfer Completed,1时表明传输完成,写1清除

bit[7:6]两个应该是和中断相关的标志位。

Sample Period Control Register (ECSPIx_PERIODREG)

采样周期,SPI设备在连续数据传输过程中在完成了8个bit的数据传输后,可以设置一个等待时间,

 

中间这个Wait State的时间就由这个寄存器控制

 

 

根据官方建议,bit[14:0]设置为0x2000,bit[15]设置为0,即SPI时钟,bit[20:16]表示片选信号延时,我们设置为0。

最后两个寄存器我们暂时用不到,先不关注了。以后如果用到了再来完善

时钟设置

SPI的时钟从时钟树上可以查到

 

最终来自pll3_sw_clk=480MHz,经过8分频以后为60MHz。但是要设置CSCDR2寄存器ECSPI_CLK_SEL(bit18)=0,分频器CAN_CLK_PODF(bit24:19)设置为0表示1分频,所以最终进入SPI的时钟源为60MHz。

但是ECSPI模块的Control Register(bit[15:8])还会将进入的时钟源进行2级分频,其中bit[15:12]为前几分频,值为0-0xf,表示1-16分频,bit[11:8]为2级分频,设置为2^0~2^15分频,一定要注意这个二级分频的分频器跟1级是不同的

 

posted @ 2023-11-19 23:10  银色的音色  阅读(103)  评论(0编辑  收藏  举报