SPI通信协议

串行外设接口

I2C的缺点:由于I2C开漏外加上拉电阻的电路结构,使得通信线高电平的驱动能力比较弱,这就会导致通信线由低电平变到高电平的时候,上升沿的耗时比较长,会限制I2C的最大通信速度(半双工特性导致,频繁切换输入输出模式)。

SPI:SPI传输更快,SPI协议没有严格规定最大传输速度,设计简单,SPI的硬件开销比较大,通信线的个数比较多,并且在通信过程中,经常会有资源浪费的现象

SCK-----串行时钟线,MOSI-----主机输出从机输入,MISO-----主机输入从机输出,SS-----从机选择

SPI没有应答机制 

SPI所有通信线都是单端信号,它们的高低电平都是相对GND的电压差,所以所有的设备还需要共地。

SS线是低电平有效的,主机想指定谁,就把对应的SS输出线置低电平就行了 

当从机的SS引脚为高电平,也就是从机未被选中时,它的MISO引脚必须切换为高阻态,高阻态相当于引脚断开,不输出任何电平,这样就可以防止一条线有多个输出而导致的电平冲突问题;在SS为低电平时,MISO才允许变为推挽输出

SPI是高位先行, 每来一个时钟,移位寄存器都会向左进行移位。

移位寄存器的时钟源是由主机提供的,这里叫作波特率发生器,它产生的时钟驱动主机的移位寄存器进行移位,同时这个时钟也通过SCK引脚进行输出,接到从机的移位寄存器里。

波特率发生器时钟的上升沿,所有移位寄存器向左移动一位,移出去的位放到引脚上,波特率发生器时钟的下降沿,引脚上的位,采样输入到移位寄存器的最低位。

SS是低电平有效

SS下降沿时,立刻触发移位输出来提供第一个数据 

CPOL(Clock Polarity)时钟极性

CPHA(Clock Phase)时钟相位

还没开始通信时MISO一条直线表示为高阻态

SPI没有硬性规定MOSI的默认电平

模式0和模式1的区别就是模式0把数据变化的时机提前了

CPHA表示的是时钟相位,决定是第一个时钟采样移入还是第二个时钟采样移入,并不是规定上升沿采样还是下降沿采样的

SPI中通常采用的是指令码加读写数据的模型

SPI起始后,第一个交换发送给从机的数据,一般叫做指令码,在从机中,对应的会定义一个指令集

W25Q4芯片规定,写指令之后的字节,定义为地址高位

SPI有和I2C一样的地址指针,每读写一个字节,地址指针自动加1,如果发送一个字节之后不终止,继续发送的字节就会依次写入到后续的存储空间里

------------------------W25Q64BV介绍------------------------------------------------------------------------------- 

 易失性存储器一般就是SRAM、DRAM等,非易失性存储器一般就是EEPROM、Flash等,他们最主要的区别是存储的数据是否是掉电不丢失

双重SPI,在发的时候可以同时使用MOSI和MISO发送,在收的时候同时用MOSI和MISO接收,一次2位

四重SPI是多用了WP(写保护)和Hold引脚

CS,左边画了个斜杠,代表是低电平有效

WP(Write Protect),写保护,配合内部的寄存器配置,可以实现硬件的写保护,低电平有效,保护住,不让写。WP接高电平,不保护,可以写。

Hold,数据保存,低电平有效。如果在进行正常读写时,突然产生中断,然后想用SPI通信线去操控其他器件,这时如果把CS置回高电平,那时序就终止了,但如果不想终止总线,又想操作其他器件,这就可以hold引脚置低电平,芯片释放总线,但是芯片时序不会终止,它会记住当前的状态,当你操作完其他器件时,可以回过来,hold置回高电平,然后继续hold之前的时序,相当于SPI总线进了一次中断,并且在中断里,可以用SPI干别的事情

空间先划分为块block,每一块block划分为若干的扇区Sector,对于每个扇区又可以分为很多页Page。

左下角为控制逻辑,主控芯片通过SPI协议,把指令和数据发给控制逻辑,控制逻辑就会自动去操作内部电路,完成功能。控制逻辑上面有个状态寄存器,芯片是否处于忙状态、是否写使能、是否写保护,都可以在状态寄存器里体现

写控制逻辑,配合WP引脚实现硬件写保护

高电压生成器,配合Flash进行编程,掉电不丢失。比如点亮一个LED表示1,熄灭LED表示0,但如果整个系统电都没有,那1和0就无从说起了,所以要想掉电不丢失,就要我们在存储器里产生一些刻骨铭心的变化,比如一个LED,给它加很高的电压,那LED就烧坏了,我们用烧坏的LED表示1,没烧坏的LED表示0,然后再断电,烧坏的LED还是烧坏的,烧坏的状态不受有电还是没电的影响,此乃掉电不丢失。一般非易失性存储器,都需要一个比较高的电压去刺激它,需要一个高压源。

页地址锁存/计数器和字节地址锁存/计数器,用来指定地址,通过SPI总共发过来3个字节的地址。一页一共是256个字节,所以一页内的字节地址,就取决于最低的一个字节,而高位的2个字节,就对应的是页地址。所以发送的地址,前两个字节会进入到这个页地址锁存器计数器里,最后一个字节会进入到字节地址锁存器计数器里。然后,页地址,通过这个写保护的行解码,来选择我要操作哪一页。字节地址,通过列解码和256字节页缓存,来进行指定字节的读写操作。那又因为我们这个地址锁存都是有一个计数器的,所以这个地址指针在读写之后可以自动加1,这样就可以实现从指定地址开始,连续读写多个字节的目的了。

最后,右下角的256字节的页缓存区,其实是一个256字节的RAM存储器,数据读写就是通过这个RAM缓存区来进行的。我们写入数据,会先进入缓存区里,然后在时序结束后,芯片再将缓存区的数据幅值到对应的Flash里,进行永久保存。这是因为SPI写入的频率非常高,而Flash的写入需要掉电不丢失,就比较慢,所以芯片的设计思路就是,写入的数据先放在页缓存区里存着,因为缓存区是RAM,所以它的速度非常快,可以跟得上SPI总线的速度。因为缓存区是256个字节,所以写入的时序有个限制条件,就是写入的一个时序,连续写入的数据量,不能超过256字节。写完后才把数据从缓存区转移到Flash存储器里。数据从缓存器转到Flash里,需要一定的时间,所以在写入时序结束后,芯片会进入一段忙的状态,通往状态寄存器,给状态寄存器的BUSY位置1。忙的时候,芯片不会响应新的读写时序了。由于读取,只是看一下电路的状态就行了,它基本不花时间,所以读取的限制就很少了,速度也非常快。

Flash的写入和读取并不像RAM那样简单直接,RAM是指哪打哪,想在哪写就在哪写,想写多少就写多少,并且RAM是可以覆盖写入的,比如原来RAM里有个数据0xAA,之后我直接再写入一个新数据0x55,那RAM的数据就变成0x55了。

写使能的话,使用SPI发送一个写使能的指令。

Flash没有直接完全覆盖改写的能力,比如在某一个字节的存储单元里,存储了0xAA这个数据,对应的二进制位就是10101010 ,如果我直接再次在这个存储单元写入一个新的数据,比如再写入一个0x55,0x55的二进制是01010101,当这个01010101要覆盖原来的10101010时,就会受到限制,最终写入的是0x00.

擦除,可以选择整个芯片擦除,也可以选择按块擦除,或者按扇区擦除,最小的擦除单元就是一个扇区。一个扇区4096个字节。擦除时芯片也会处于忙状态,BUSY位置1。

控制和状态寄存器:

当设备正在执行页编程,页编程就是写入数据,然后扇区擦除、块擦除、整片擦除或者写状态寄存器指令时,BUSY位置1。在这期间,设备会忽略进一步的指令,当然除了读状态寄存器和擦除挂起的指令,然后是当编程、擦除、写状态寄存器指令结束后,BUSY清零来指示设备准备好了。

写使能锁存位WEL,在执行完写使能指令后,WEL置1,代表芯片可以进行写入操作了,当设备写失能时,WEL位清零。一是,上电后,芯片默认写失能;二是,在执行完以下指令之后,发送写失能,WEL就等于0,其次是页编程、扇区擦除等。在进行任何写操作之前,都得来一遍写使能,写完会自动写失能。一个写使能,只能保证后续的一条写指令可以执行。

指令集:

写使能,指令码是06,要想发送写使能指令,先起始然后交换一个字节,第一个字节是发送方向,发送0x06指令,这个指令不需要后续跟数据,直接停止。写失能是0x04。

读状态寄存器1,起始,0x05,S0是BUSY位,S1是WEL位。

页编程,就是写数据,起始,0x02,3个字节地址,1个字节数据,如果继续交换写入的话,后续的字节就从起始地址开始依次存储

扇区擦除,起始,0x20,3个字节地址,终止,发送之后,这个指定地址所在的扇区就会被整个擦除,我们一般会把这个地址对齐到扇区的首地址。

JEDEC ID,读ID号,起始,0x9F,随后连续交换读取3个字节,终止。第一个字节是厂商ID,后两个字节是设备ID,这是读取ID号的指令。

读取数据,起始,0x03,3个字节的地址,然后交换读取,这个数据就是这个地址下的数据,如果继续进行交换读取,后面数据就是从指定地址开始依次读存储的数据,这个读取没有页的限制。

------------软件SPI读写W25Q64

对于主机,时钟、主机输出和片选都是输出引脚,都配置为推挽输出模式,主机输入则配置为上拉输入

对于模式0,是先SS下降沿或SCK下降沿,再将数据移除,下降沿是触发数据移出这个动作的条件。对于硬件SPI来说,由于使用了硬件的移位寄存器电路,所以这两个动作几乎是同时发生的。而对于软件SPI来说,由于程序是一步一步执行的,就不能同时完成两个动作。

设备ID高8位,表示存储器类型,低8位表示容量

----------SPI通信外设

16位数据帧相当于连续发两个8位数据帧

SPI和I2C都采用了高位先行,而串口采用低位先行

SPI1挂载在APB2,PCLK是72M,SPI2是挂载在APB1,PCLK是36M

I2S是一种音频传输协议,一种数字音频信号传输的专用协议

 

图示为低位先行,框中的交叉为用来进行主从模式引脚变换,我们的SPI外设,可以做主机也可以做从机 ,LSBFIRST决定高位先行还是低位先行

 和串口一样,TDR和RDR占用同一个地址,统一叫作DR

总线数据进入TDR,TDR的数据会在移位寄存器没有数据移位时立刻转入移位寄存器,开始移位,这个转入时刻,会置状态寄存器的TXE为1,表示发送寄存器空。当我们检查TXE置1后,下一个数据就可以提前写入到TDR里等候了。一旦上一个数据发完,下一个数据就可以立刻跟进,实现不间断的连续传输。移位寄存器这里一旦有数据过来了,就会自动产生时钟,将数据移出去。在移出的过程中,MISO的数据也会移入,一旦数据移出完成,数据移入也完成了。这时,移入的数据,就会整体地从移位寄存器转入到接收缓冲区RDR。这个时刻,会置状态寄存器的RXNE为1.表示接收寄存器非空。当我们检查RXNE置1后,就要尽快把数据从RDR读出来。在下一个数据到来之前,读出RDR,就可以实现连续接收。否则,如果下一个数据已经收到了,上一个数据还没从RDR读出来,那RDR的数据就会被覆盖,不能实现连续的数据流了。

波特率发生器,主要用来产生SCK时钟,内部就是一个分频器,输入时钟是PCLK,72M或36M,经过分频器之后,输出到SCK引脚。当然这里生成的时钟肯定是和移位寄存器同步的了。每产生一个周期的时钟,移入移出一个bit。

然后右边,CR1寄存器的三个位BR0、BR1、BR2,用来控制分频系数

SPE(SPI ENABLE),是SPI使能,就是SPI_Cmd函数配置的位

BR(Baud Rate)配置波特率,就是SCK时钟的频率

MSTR(Master),配置主从模式,1是主模式,0是从模式,我们一般用主模式

CPOL和CPHA,时钟极性和时钟相位,用来选择SPI的4种模式

SR状态寄存器,TXE发送寄存器空,RXNE接收寄存器非空

CR2寄存器就是一些使能位,比如中断使能,DMA使能,

NSS引脚,SS就是从机选择,低电平有效,所以前面加了个N,这里的NSS设计,可能更偏向于实现多主机模型,SS引脚直接使用一个GPIO模拟就行,具体NSS如何实现多主机功能,参考江协科技SPI通信外设19:10.

非连续传输的好处就是容易封装,好理解,好用,但是会损失一点性能;连续传输,传输更快,但是操作起来相对复杂 

连续传输的流程是交错的,发送数据2,接收数据1,发送数据3,接收数据2,发送数据4,接收数据3

 整个非连续流程就是,第1步,等待TXE为1,第2步,写入发送的数据至TDR,第3步,等待RXNE为1,第4步,读取RDR接收的数据,之后交换第二个字节,重复这4步

 ------------------------硬件SPI读写W25Q64

第一步,开启时钟,开启SPI和GPIO的时钟

第二步,初始化GPIO,其中SCK和MOSI,是由硬件外设控制的输出信号,配置为复用推挽输出;MISO是硬件外设的输入信号,配置为上拉输入,因为输入设备可以有多个,所以不存在复用输入这个东西,普通GPIO口可以输入,外设也可以输入,还有SS引脚,是软件控制的输出信号,配置为通用推挽输出。

第三步,配置SPI外设,使用一个结构体选参数即可,调用SPI_Init,比如8位/16位数据帧、高位先行/低位先行、SPI模式几、主机还是从机等等

第四步,开关控制,调用SPI_Cmd,给SPI使能

//恢复缺省配置

void SPI_I2S_DeInit(SPI_TypeDef* SPIx);

//初始化

void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct);

/结构体变量初始化

void SPI_StructInit(SPI_InitTypeDef* SPI_InitStruct);

//使能

void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState);

//中断使能

void SPI_I2S_ITConfig(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT, FunctionalState NewState);

//DMA使能

void SPI_I2S_DMACmd(SPI_TypeDef* SPIx, uint16_t SPI_I2S_DMAReq, FunctionalState NewState);

//写DR数据寄存器,写到TDR

void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data);

//读DR数据寄存器,接受数据寄存器RDR

uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx);

//NSS引脚配置

void SPI_NSSInternalSoftwareConfig(SPI_TypeDef* SPIx, uint16_t SPI_NSSInternalSoft);
void SPI_SSOutputCmd(SPI_TypeDef* SPIx, FunctionalState NewState);

//8位或16位数据帧的配置

void SPI_DataSizeConfig(SPI_TypeDef* SPIx, uint16_t SPI_DataSize);

//CRC校验的配置

void SPI_TransmitCRC(SPI_TypeDef* SPIx);
void SPI_CalculateCRC(SPI_TypeDef* SPIx, FunctionalState NewState);
uint16_t SPI_GetCRC(SPI_TypeDef* SPIx, uint8_t SPI_CRC);
uint16_t SPI_GetCRCPolynomial(SPI_TypeDef* SPIx);

//半双工时,双向线的方向配置

void SPI_BiDirectionalLineConfig(SPI_TypeDef* SPIx, uint16_t SPI_Direction);

//获取标志位和清楚标志位的函数

FlagStatus SPI_I2S_GetFlagStatus(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG);
void SPI_I2S_ClearFlag(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG);
ITStatus SPI_I2S_GetITStatus(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT);
void SPI_I2S_ClearITPendingBit(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT);

写入TDR的数据在TXE置1时刻进入移位寄存器,一旦移位寄存器有数据了,时序波形就会自动产生,这个波形生成,不需要我们调用什么函数让它开始传输,只需要写入数据到TDR就行。

硬件SPI,必须是发送,同时接收,要想接收,就必须得先发送,因为只有你给TDR写东西,才会触发时序的生成,如果你不发送,只调用接收函数,那时序是不会动的

TXE和RXNE标志会被自动清除,无需手动清除 

  • 23
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: ILI9488是一款广泛使用的TFT液晶屏驱动芯片,其SPI通信协议如下: 1. 在SPI通信开始前,先拉低CS (Chip Select)管脚,然后拉低RS (Register Select)管脚,表示接下来要写入命令。 2. 向ILI9488写入命令时,先发送一个字节的命令代码,然后再发送该命令需要的参数(如果有的话)。 3. 写入命令后,可以拉高RS管脚,表示接下来要写入数据。 4. 向ILI9488写入数据时,直接发送数据即可。 5. SPI通信结束后,拉高CS管脚,表示本次通信结束。 具体的命令代码和参数可以参考ILI9488的数据手册,例如: - 0x36:设置扫描方向 - 0x3A:设置像素格式 - 0x2A:设置列地址 - 0x2B:设置行地址 - 0x2C:写入像素数据 在具体实现时,需要根据ILI9488的数据手册来编写SPI通信的代码。 ### 回答2: ILI9488是一种常用于液晶显示屏控制器的芯片,它使用SPI(串行外设接口)进行通信。SPI是一种串行通信协议,它通过四个信号线进行数据传输,包括时钟线(SCLK),主设备输出数据线(MOSI),主设备输入数据线(MISO)和片选线(CS)。 在ILI9488的SPI通信协议中,通信通过以下步骤进行: 1. 在通信开始前,主设备通过拉低片选线来选择ILI9488芯片作为通信对象。 2. 主设备根据芯片规定的时钟频率和极性生成时钟信号,从而同步数据传输。 3. 主设备将需要传输的数据发送到MOSI线上,高位先传送。 4. 在传输数据的过程中,芯片会检测到时钟的上升或下降边沿,并在边沿处读取MOSI线上的数据。数据传输完毕后,芯片会将数据写入相应的寄存器或进行相关操作。 5. 芯片可通过MISO线向主设备发送数据。但对于ILI9488来说,这个功能多数情况下是不被使用的。 6. 传输完成后,主设备通过拉高片选线来结束通信。 ILI9488的SPI通信协议具有简单、可靠和较快的特点。通过SPI接口,可以实现对ILI9488的控制和显示操作。同时,SPI通信协议也可以提供对其他外设的控制和通信,为应用提供了较大的灵活性和可扩展性。值得注意的是,具体的通信细节如时钟频率、数据格式等需要根据ILI9488的数据手册来设置,以确保通信的正常进行。 ### 回答3: ILI9488是一种常见的液晶显示驱动IC,它采用SPI通信协议与主控芯片进行通信。SPI全称为串行外围接口协议,它是一种同步的、全双工的串行通信协议。 ILI9488的SPI通信协议在硬件层面上,需要使用四个引脚进行通信,分别为时钟线CLK、数据命令控制线D/C、数据输入线MOSI和数据输出线MISO。其中CLK用于传输时钟信号,D/C用于控制数据或命令的传输,MOSI用于主控芯片向ILI9488发送数据,MISO用于ILI9488向主控芯片发送数据。 ILI9488的SPI通信协议在数据传输上是基于字节的,通信的数据帧包含一个命令字节和若干数据字节。根据具体的功能需要,主控芯片通过D/C引脚发送命令字节或数据字节。命令字节用于控制ILI9488的各种操作,如初始化设置、显示模式选择、像素颜色设置等,而数据字节则用于传输实际显示的像素数据。 在通信过程中,主控芯片通过CLK引脚向ILI9488提供时钟信号,ILI9488根据时钟信号判断数据的有效性,并按照时钟信号的边沿读取或发送数据。通过MOSI和MISO引脚的数据交换,主控芯片可以向ILI9488发送命令字节或数据字节,并接收ILI9488的响应数据。 总之,ILI9488的SPI通信协议是通过CLK、D/C、MOSI和MISO四个引脚进行数据传输的,主控芯片通过时钟信号控制数据的读写,通过命令字节和数据字节实现与ILI9488的各种交互操作。这种协议结构简单,适用于许多SPI接口的设备,使得ILI9488与主控芯片之间的通信更加方便和高效。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值