一般用来读取外挂设备的ID测试通信有没有问题
I2C通信用的是开漏输出加上拉电阻的模式,所以他的高电平驱动能力不强,通信线在低电平变到高电平的时候,所需的时间比较长限制了最大通信速度,标准模式最高一般来说是100khz,快速模式一般来说是400khz,虽然经过改良电路之后达到了高速模式3.4MHz,但是普及度不高。
【在STM32单片机中,I2C通信采用开漏输出加上拉电阻的模式,这种模式会导致高电平驱动能力不强。因为在这种模式下,当输出端口为高电平时,实际上是将输出端口变为高阻态,通过外部上拉电阻将总线拉高,因此输出端口的电流能力非常有限,无法提供足够的电流来驱动负载,导致输出电压下降或失真的情况。
另外,通信线从低电平到高电平的时候耗时比较长,是因为在I2C通信中,数据线的电平变化需要经过一定的上升时间和下降时间,这个时间与线路的电容、电阻等参数有关。在开漏输出加上拉电阻的模式下,由于输出电阻较大,导致上升时间和下降时间变长,从而限制了I2C的通信速度。】
SPI通信速度没有限制,一般来说根据芯片厂商的需求设计,比如W25Q64芯片,芯片手册上SPI时钟频率最高可达80MHZ,另外,SPI实现的功能没有IIC那么多,所以比较简单,SPI拥有很多通信线,并且硬件开销大,容易造成资源浪费的现象。
有时候通信线的名称不一定一直,比如SCK可能叫SCLK,CK,SCK等等,MISO以及MOSI有时候直接叫DI,DO。SS有的地方也叫做NSS或者CS。
SPI是同步时序,所以SPI有一根SCK线,又因为是全双工,有两根线,一根是主机发送到从机,一根是从机发送到主机,这样的好处是输入输出可以同时进行,并且不用像SPI那样担心没协调好数据的输入输出,担心数据流的冲突,但是这样做的后果就是有硬件资源的消耗。I2C通信线只有一根,既负责输入也负责输出。
SPI只支持一主多从的模式,并且不用像IIC那样先发送一个字节的地址进行寻址,SPI直接给每个从机挂载一根SS线,需要连接那个从机的时候就置低电平,跟其中的从机设备连接。并且SPI没有应答机制,一旦发送出去了就是发送出去了,至于对面是否存在,是否接收成功,无我无瓜。
第一个图,是W25Q64,是一个Flash存储器,CLK就是SCK,CS就是SS,DI以及DO的判断,一般根据给设备进行判断,比如这个W25Q64是一个从机设备,然后DI代表数据输入得意思,这里就是从机的数据输入,也就是MOSI,而DO就是MISO了,其中M是master是主宰者的意思,S就是Slave仆从的意思。
剩下的也就是一些可以使用SPI协议的外设设备,右二那个就是2.4G无线通信模块,芯片型号是NRF24L01。
SPI硬件电路:
SPI协议下主从连接如上,其中VCC跟GND没有画出来,由于SPI主机是的信号单端信号,电平高低的判断是相对于GND来说的,所以主从设备一定要共地,如果从机没有供电,还需要跟主机共vcc。
SS只是低电平的手才有效,当不选择的时候,从机的SS都是高电平,但选择的时候,SS变成低电平,因为MISO是多从机对主机的输入,有此案好冲突的可能,所以一般从机会在SS为高电平的时候,MISO引脚切换成高阻态(相当于引脚断开),当从机被主机选择SS变成低电平的时候,MISO会切换为推挽输出。
推挽输出就是在电平的上升沿下降沿变化的特别快,高低电平都有很强的驱动能力,没有像I2C通信的时候,那个开漏输出+上拉电阻的模式,导致上升沿的变化缓慢,这也是两者信号传输速度迥异的原因。
并不是IIC通信不想用推挽输出,而是无能为力,这体现在两个方面,IIC要实现半双工,经常切换输入输出,而且要实现多主机的总线仲裁以及时钟同步,都不允许,容易电源短路。所以IIC选择了更强的功能,自然要放弃性能了。SPI通信则是不支持错主机而是半双工,基本不会冲突,完美避开。
波特率发生器产生时钟信号,可以设定,假设时钟上升沿的时候,移位寄存器就会向左移动一位,然后各自把那一位的数据放在输出数据寄存器中放着,然后时钟下降沿的时候,输出数据寄存器的数据就会放到移位寄存器的末尾,周而复始,知道数据传输完毕,实则就是主机从机移位寄存器的数据进行了交换,如果只想主机读,那就只看主机的移位寄存器,如果只想从机读,那就看从机的移位寄存器,至于发送的数据可以是0xFF或者0X00等随意的数据。
选择SS正在通信过程中的时候,SS一直是低电平。
SPI存在多种模式是为了适应各种不同的芯片。
CPOL(clock polarity)的意思是时钟时钟极性,CPHA(clock phase)时钟相位,每一位可以配置为0或者1,总共四种搭配。
其中上图为模式1,与上面的一位模型是对应的,也可以说是SCK的偶数边沿进行采样。
空闲状态也就是SS为高电平未被选中的时候,这时候SCK时钟信号为0.
MISO代表的是主机输入,从机输出,这根线是多输出仅仅一个输入,为了避免信号冲突,所以在不被选择的时候都是高阻态的,也就是非高非低电平,居于中间。
过程是:未选择从机的时候,SCLK为低电平,MOSI为低电平或者高电平(主要由主机控制),MISO主要由从机设备控制,当从机被选择的时候,SS低电平,SCK运行,MOSI在移出数据的时候进行一次电平变化,从低电平变成高电平或者从高电平变成低电平,MISO从高阻态解放,同样从低电平变成高电平或者从高电平变成低电平。而CLK下降沿的时候,中间部分要对准MISO或者MOSI的电平持续的时候,知道下一次上升沿到来再度变化。到最后SS上升沿的时候,准备结束通信,MOSI再度恢复到初始的状态高电平还是低电平,这个动作跟CLK上升沿基本同步,要在它上升沿结束之前结束。MISO则是回归高阻态。至于是高电平还是低电平,根据发送的数据来看,1位高电平,0位低电平。
模式0相比于模式1把MOSI以及MISO的数据移出移入的时机提前了半个时钟,也就是相位提前了,第一个边沿就要移入数据,所以要提前进行把数据移出,所以要在SS下降沿变化的时候就要把数据移出,最后一位数传输结束,MOSI就要变化为原来的电平,而MISO因为相位提前了,所以下一个字节的B7会漏一个头,如果不需要的话,在SS上升沿的时候,MISO就恢复为高阻态。
模式0和3都是SCK上升沿采样,12都是下降沿采样,01时钟相同,23时钟相同。
w25q64为例子进行讲解时序图。
IIC使用的是读写寄存器的模型,有效数据第一个字节写的是寄存器的地址,之后是读写的数据;而SPI中一般采用指令码+读写数据的模型,SPI启动后,第一个发送的数据是指令码,从机中会对应着一个指令集,如果我们想要实现什么功能直接发送指令集中的指令即可,不同的指令有不同的数据个数,有的指令直接一个指令码就能完成,有的指令就要在后面跟上读写的数据才行。
有些地址也会融合到指令码中去,不用直接一个一个的发送字节组成地址。
MISO以及MOSI的初始电平没有严格的规定。(由于MISO是上拉输入,所以显示为高电平?)
*发送指令 向SS指定的设备,发送指令(0x06),这是模式0,一般来说都是用模式0.
在SS下降沿的时候MOSI以及MISO的数据就要发生改变了,因为在sclk上升沿的时候,就要把数据采样。SCK下降沿的时候,两者的数据优惠改变,如此循环往复,如果为1,就要变成高电平。而MISO在高阻态是不确定的,但是由于电路是上拉电阻,所以默认在高阻态的时候为高电平。绿色的线是采样输入的意思。因为是软件模拟的有一定延迟,但是只要在下一个时钟边沿之前完成变化就可以了。
指定地址写,就是先发送指令,然后写入指定的地址,因为w25q64的存储器大小是8M,地址也很大,三个字节才存的下。
SS下降沿后,SCK上升沿之前,MISO以及MOSI要把电平变换结束。模式0中下降沿采样数据,上升沿变换数据。开始发送的0X02是一条指令,代表的写指令。后面还要跟着写的地址以及数据。在一个字节传输结束之后,要把下一个字节的最高放在MOSI第一个传送字节的末尾。第二个字节代表地址的24到17位,第三个字节代表16到8位,第三个字节代表0到7位。最后一个字节就是要在这个地址0X123456中写入的数据。
【
8M的存储器,指的是存储器的容量为8兆字节(MegaByte),其中1兆字节等于1024*1024字节,即1048576字节。因此,8M的存储器容量为8388608字节。
要确定8M存储器需要多大的地址,需要知道存储器单元的大小。通常情况下,存储器单元的大小是1个字节,即8位二进制数。因此,8M存储器中有8388608个存储单元。
为了标识存储器中每个存储单元的位置,需要使用地址。由于存储器中有8388608个存储单元,因此需要使用23位二进制数来表示每个存储单元的地址。这是因为2的23次方等于8388608,即23位二进制数可以表示8388608个不同的地址。
因此,8M的存储器需要23位地址来标识每个存储单元的位置。
】
基本跟鞋大差不差,但是不同点在于,先是有主机给从机发送指令以及地址,因为主机要在从机中读取数据,所以从机要发送数据,所以在地址发送完成之后要改为在MISO通信线上面进行并且MISO的变化紧贴着SCK时序的变化。
并且这一部分也印证了上面的话,在一个字节传送完成下降沿的时候,会变成下一个字节最高位一样的电平。