原因:
上个章节我们讲解了spi接口定义,今天我们更加深入讲解下spi协议时序图和spi四种模式的用法。
刚开始接触单片机开发时,最怕就是看时序图,对于我来说就是奇怪的知识。
特别是SPI和IIC的,以前写程序都直接复制别人程序,功能实现就行了也没去研究过数据传输的时候时序具体是怎么样的。
那个时候经验也不足,网上搜的资料说的都太学术化了,也看不懂。
后面项目做多了,发现最常用到的通信总线无非就是SPI、IIC、USART、CAN、单口通信。
理解也慢慢深刻了,现在去分析时序图也更加清晰了。
所以,我经常和无际单片机编程的学员灌输一种理念,先学会用,用多了经验丰富了再深入就轻松了。
不要在你没经验的时候去死磕,否则会付出很多不必要的时间成本。
下面,我们进入主题。
一、spi四种模式详解
在讲时序图之前,我们先要了解spi的四种模式,不同的模式采集数据的方式不一样。
一般内置SPI功能的单片机上,都有两个寄存器配置位CPOL和CPHA。
我们拿STM32单片机来举例,可以通过结构体成员配置。

这是通过固件库直接配置,固件库底层代码也是去配置相应寄存器的。


下面来介绍下CPOL和CPHA到底有什么用。
CPOL就是决定SCLK这个时钟信号线,在没有数据传输的时候的电平状态。
CPOL=0:空闲状态时,SCLK保持低电平
CPOL=1:空闲状态时,SCLK保持高电平

CPHA就是决定数据位传输是从第一个时钟(SCLK)边沿开始,还是第二个从二个时钟(SCLK)边沿开始。
CPHA=0:数据从第一个时钟(SLCK)边沿开始采集
CPHA=1:数据从第二个时钟(SLCK)边沿开始采集

Ok,理解CPOL和CPHA基本概念以后,下面这两个要开始”合体”了。
CPOL和CPHA合体就形成了SPI四种模式。

声明:部分源自网络,并非原创哈。
下面再分析下4种模式的区别,比较重要。
因为从机,从机指的是使用SPI协议通信的芯片,比如说w25q64(Flash)芯片,OLED屏等等。
很多从机没有CPOL和CPHA寄存器设置位,如果你看它们数据手册会一脸懵逼,根本找不到这两个东西。
这些都是需要看他们时序图去分析是用什么模式,如果模式不对,数据传输会有问题。
这也是为什么明明自己写了时序用在这个芯片可以,换到别的spi通信的芯片就不行。
1模式0(CPOL=0,CPHA=0)
模式0特性:
CPOL = 0:空闲时是低电平,第1个跳变沿是上升沿,第2个跳变沿是下降沿
CPHA = 0:数据在第1个跳变沿(上升沿)采样

2模式1(CPOL=0,CPHA=1)
模式1特性:
CPOL = 0:空闲时是低电平,第1个跳变沿是上升沿,第2个跳变沿是下降沿
CPHA = 1:数据在第2个跳变沿(下降沿)采样

3模式2(CPOL=1,CPHA=0)
CPOL = 1:空闲时是高电平,第1个跳变沿是下降沿,第2个跳变沿是上升沿
CPHA = 0:数据在第1个跳变沿(下降沿)采样

4模式3(CPOL=1,CPHA=1)
CPOL = 1:空闲时是高电平,第1个跳变沿是下降沿,第2个跳变沿是上升沿
CPHA = 1:数据在第2个跳变沿(上升沿)采样

不知道你有没有发现,不同的模式,其实就是SCLK空闲时间电平状态和数据采样起点不同
你学废了吗?当初我就是这几种模式看得一脸懵逼。
如果不懂,先从开头继续看,这4种模式是后面分析整体时序图的前提。
二、spi时序图详解
看到这里恭喜你,你马上就能彻底攻破SPI协议了。
Spi时序图,最好的方式就是通过实际应用去学习。
我们拿W25Q64这个Flash芯片举例,这种芯片在SPI通信里都是作为从机的角色,也就SPI Slave。
一般由单片机或者其它处理器作为主控和它通信,SLCK时钟也是由主控发出。
下面是W25Q64读数据指令的时序图,我们以这个例子来讲解下时序图要怎么看。

1先确定芯片支持什么SPI哪种模式读写数据
确定了用哪种模式,主控,也就是单片机这边才能确定数据采集的方式,主控和从机要保持一致。
从时序图中,不难发现,W25Q64的数据手册直接告诉你支持用SPI模式0和模式3来通信。
有些芯片的数据手册,是没有告诉你的,那怎么知道用芯片哪种模式?

第一步:通过时序图分析CLK空闲时的电平状态,通过上面那个时序图,我们可以得知,高低电平都可以对吧?那我们现在先用CLK空闲时是低电平这种状态继续往下分析。
第二步:分析DI和DO是在CLK的上升沿还是下降沿采集数据,注意DI代表从机(W25Q64)的MISO引脚,DO代表从机(W25Q64)MOSI引脚。
我们主要通过DI和DO在数据有效区时CLK是上升沿还是下降沿,来判断
什么是数据有效区?

大家看上面这张图,我用红色框起来的区域就是数据有效区。
一般数据是通过DI和DO两个引脚传输的,所以数据有效区就是,这一时刻,这两个引脚的只能是稳定高电平或者低电平。
相当于数据有效区的电平就是最终要传输的数据位,低电平代表0,高电平代表1。
传输8个位,代表1个字节的数据。
什么是无效数据区?

例如上图蓝色框的区域就是无效数据区,就是这个时刻CLK数据采集时钟还没来,所以DI和DO引脚的电平都可以任意变化。
理解了这两个概念以后,我们重点需要关心是的DI和DO在数据有效区的时候,CLK是上升沿还是下降沿。

从上图可以看出,DI和DO在数据有效区时,CLK是上升沿,下降沿的时候,DI和DO处于电平可任意变化的无效数据区。
这样,就可以分析出模式了。
首先上升沿采集数据,通过排除法,这样只有模式0和模式3符合条件。
然后就是CLK空闲时间要为低电平,这样就只有模式0符合了。
所以,知道用模式0以后,单片机那边写程序就知道数据是从CLK上升沿读取,或者发送,还是从下降沿了。
2分析整体时序
分析时序,我们一定要先熟悉这个时序要实现什么功能,不同的功能虽然时序不一样,但是发送数据的顺序和定义不同。
我们现在分析的这个时序是从W25Q64这个Flash芯片读取存储的数据。

我把整个时序按CLK脉冲顺序拆分成3个部分:
①读指令
这里要注意的是,读指令数据是在W25Q64的DI引脚产生的,DI相当于W25Q64的MISO,就是接收主控(一般是单片机)发送过来的数据。
所以,这个读指令(0x03)是单片机发给W25Q64的。
0x03被拆分成8个Bit在DI线上传输,每个CLK上升沿传输1个Bit。

②24位地址
发完读指令以后,单片机继续发24位的内存地址,相当于要读W25Q64哪个内存地址的数据。
这个数据是由单片机程序定的,所以不是固定的,大家可以看到数据位都是可以高电平,也可以是低电平。
③单片机接收数据
这个时候通信双方的角色就变了,单片机变成了数据接收方,W25Q64变成了数据发送方。
因为数据从W25Q64的DO发出了,也就是W25Q64的MOSI引脚。
通过这个时序,单片机就可以读到存储在W25Q64指定地址的数据了。
如果你是我们无际单片机编程学员,看文章还不是很理解的话,可以跟我反馈,反馈的人多就直播讲解,如果少就针对性一对一远程电话讲解。
三、单片机程序注意
51单片机一般没有内置SPI模块,所以整个时序需要自己写程序去模拟,简称模拟SPI。
而STM32单片机一般有内置SPI,就不用自己写程序去模拟时序,直接应用。
但是如果用内置SPI有一个细节,特别容易被忽略,就是你读数据的时候,读一个字节之前要先发一个字节任意值数据。
发一个字节任意值数据是为了在CLK总线上产生时钟,给从机的SPI信号提供时钟用的,从机SPI不会自己产生CLK信号的。
比如我下面这个读数据函数:

能理解到这一步,你基本上就已经吃透SPI协议了。
不管从机怎么换,比如说不是W25Q24了,换成OLED屏了,时序原理也是一样的,只是相关的指令和寄存器不同。
首先软件SPI,这个毫无疑问你需要用IO模拟SPI时序,这个模拟过程全部是CPU在负责执行,为了稳定得存取数据,你可能会插入软件延时,这个时间在读取数据量不大的情况下并不明显,但是基本上你在读取过程中,其他非中断非异常程序是无法得到执行。
来说说硬件SPI,首先这个数据存储的过程是不需要CPU参与得,程序中配置好SPI的访问时序,开启中断,CPU就可以在中断函数中搬移数据,省下了软件模拟IO得存取时间。
仔细研究就会发现,CPU在进行SPI中断服务程序还是需要耽误时间得,这个过程在大数据量传输中还是很耗时,arm中cortex-m3内核得处理器在硬件SPI上加入了DMA,这个DMA直接从SPI的数据寄存器,软件配置好DMA之后,基本上整个传输都不要CPU参与,软件设计得好的话,整个数据传输都不要CPU参与,这个省下来CPU,你就可以干更多有意义的事情了。
1:SPI是一种高速,全双工的,同步的通信总线;
2:四线连接,MISO-主设备数据输入,从设备数据输出;MOSI-主设备数据输出,从设备数据输入;SCLK-时钟信号,由主设备产生;CS-从设备片选信号,由主设备控制。
3:主机和从机各有一个串行移位寄存器,两个寄存器中的数据在同一时刻被交换,如果只进行写 *** 作,主机只需要忽略接收到的字节;如果主机要读取从机中的字节,就必须发送一个空字节来引发从机的传输。
4:SPI可以设置输出串行时钟的极性和相位,时钟极性与串行同步时钟的空闲状态的电平有关,CPOL=0,串行同步时钟空闲状态为低电平,反之为高;CPHA可以设置选择两种不同的传输协议,CPHA=0,串行同步时钟的第一个跳边沿数据被采样,反之,在串行同步时钟的第二个跳边沿数据被采样;
5:为了防止MISO总线冲突,同一时间只允许一个从设备与主设备通讯;
6:SPI主机和从机的时钟极性和相位应该一致;
7:在数据传输(数据交换)的过程中,每次接收到的数据必须在下一次数据传输之前被采样如果之前接收到的数据没有被读取,那么这些已经接收完成的数据将有可能会被丢弃,导致SPI物理模块最终失效。因此,在程序中一般都会在SPI传输完数据后,去读取SPI设备里的数据,即使这些数据(DummyData)在我们的程序里是无用的。
1:概述
2:时序
1:配置相关引脚复用为SPI,使能SPI时钟;
2:设置SPI工作模式,包括主机或者从机、数据格式(高位在前还是低位在前)、设置串行时钟的极性和相位(采样方式)、SPI时钟频率(SPI的传输速度);
3:使能SPI;
spic-SPI驱动
flashc-w25q128驱动
可以的,但SPI接口的器件有多种工作方式,如高位在前还是低位在前,空闲时时钟线高电平还是低电平
第一个跳变沿还是第二个跳变沿数据有效,程序是不同的,下面程序供参考
sbit CLK=P2^2;
sbit MOSI=P2^3; //发送方方管脚配置
sbit MISO=P2^4;
sbit BIT0=ACC^0;
sbit BIT7=ACC^7;//
void Write(uchar byte)//写数据
{
uchar i;
ACC=byte;
i=8;
while(i)
{
MOSI=BIT7;
CLK=1; // output 'uchar', MSB to MOSI
_nop_();
_nop_(); // shift next bit into MSB
_nop_();
_nop_();
ACC<<=1;
CLK=0; // Set SCK high
i--; // then set SCK low again
_nop_();
}
}
/
/函数:Read(uchar reg)
/功能:NRF24L01的读时序
//
uchar Read(void)
{
uchar i;
i=8;
sbit BIT0=ACC^0;
sbit BIT7=ACC^7;
while(i)
{
CLK=1; // output 'uchar', MSB to MOSI
_nop_();
_nop_();
_nop_();
_nop_(); // shift next bit into MSB
ACC<<=1;
BIT0=MISO ;
CLK=0; // Set SCK high
i--; // then set SCK low again
_nop_();
//led1=~led1;
}
return ACC; // return register value
}
1、SPTAT=0xc0;之后SPIF是不是等于零。如Datasheet,是的。置1清零。
2、SPDAT = SPDAT;两个形式相同,含义却不同。因为发送缓冲和接收缓冲,一个只写,一个只读。所以,没有必要安排两个寄存器分别存放。而是复用了一个地址。左边的是发送缓冲,可以被赋值,如SPDAT =0x11;表示发数据0x11。右边的是接收缓冲,如i=SPDAT;表示接收到的内容读取到i变量中。=赋值语句,是有要求的,左边和右边是不同的。比如0=i;就是不合法的。这样你能理解了为什么是SPDAT = SPDAT了吧。就是把收到的内容再写到发缓冲的意思。
时序没有区别。
硬件SPI效率高些,写程序的时候只要把要发的数据写到寄存器里,硬件就自动给发了。
软件需要去实现时钟拉高拉低,数据串行输出等等。
硬件的SPI必须要处理器支持才可以用。
软件SPI就不需要特定的要求了,一般的IO口就可用。
以上就是关于spi模式0可以通信模式3不能通信的原因全部的内容,包括:spi模式0可以通信模式3不能通信的原因、硬件spi相比软件spi的优势在哪里、柒:SPI总线,实现外部FLASH(W25Q128)读写等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)