SPI协议详解( 三 )


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
SPI协议详解文章插图
我们知道, 在每个时钟周期内, 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
SPI协议详解文章插图
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个时钟周期的数据情况演示一遍:假设上升沿发送数据
SPI协议详解文章插图
这样就完成了两个寄存器8位的交换 , 上面的上表示上升沿、下表示下降沿 , sdi、sdo相对于主机而言的 。 已经很接近理解了 , 下一步就是把 上面的过程转为动画
SPI协议详解文章插图
SPI协议详解文章插图
SPI协议详解文章插图
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,/*!