目录
目录
一、 通讯的基本概念
1.1为什么要有不同的通讯协议
通讯协议是指不同设备之间进行通讯时所遵循的一种规则或协议。在计算机设备与设备之间或集成电路之间常常需要进行数据传输,因此我们会学习到各种各样的通讯方式。这些设备可能来自不同的供应商、生产商或不同的类型和技术。因此,不同的设备之间需要进行数据交换和通信,需要使用相应的通讯协议。
单片机中常见的通信协议有哪些?
UART/USART协议、RS232、RS485、I2C通信协议、SPI通信协议、CAN通信协议、Modbus通信协议等。
1.2串行与并行,各自有什么优越点和应用场景?
在芯片内部数据都是并行传输的,只是在芯片发送器一端转换为串行形式,在接收器一端又转换回并行数据。在两个芯片之间的串行传输过程中 时钟问题是导致误码率降低的瓶颈。
串行通信是指设备之间以少量的数据信号线(一般是八根以下),地线、控制信号线,按数据位一位一位地传送。比如把一个数值(如1字节,即8bit)进行单通道(如一根导线)传输,每次传输1bit。在接收端,每个比特都被读出并重新组合为1个字节。
下图所示的为同步串行接口。数据的发送和接收是由从发送器到接收器的一个时钟信号协调的。
并行通信一般指使用8,16,32,64或更多跟数据线进行传送的通讯方式。将一个完整的字节(或更大的数据)一下子从发送器传输到了接收器。
并行通讯就像多个车道的公路,可以同时传输多个数据位的数据,而串行通讯就像单个车道的公路,同一时刻只能传输 一个数据位的数据。
很明显,因为并行通讯一次可以传输多位数据,因此在数据传输速率相同的情况下,相同时间内并行通讯比串行通讯传输数据多的多。两者各有优劣,比如串行通讯可以节省数据线的硬件成本以及PCB布线的面积。并行传输对同步要求比较高,且随着通讯速率的提高,信号干扰的问题会显著 影响通讯性能。
1.1.2串行和并行各自有什么优越点和应用场景
串行通信的优点:1. 通信距离远:串行通信使用单根传输线,可以传输的距离更远,传输线的长度可以达到几百米甚至几千米.2. 传输可靠性高(抗干扰能力强):串行通信使用单根传输线,信号传输的稳定性更高,抗干扰能力更强,传输数据的可靠性更高。3、成本低
串行通信的缺点:1、采用单根数据线,数据带宽相对较窄,无法同时输入多个数据流。传输速率较低等。
串行通讯应用场景:长距离传输。如远程监控、电力通信等。
并行通信的优点:1. 传输速度快:并行通信使用多根传输线,可以同时传输多个比特位。2. 传输带宽大:同时传输多个比特位,数据带宽更大,适用于需要大数据传输的场景。。3. 传输效率高:同时传输多个比特位,传输效率更高,适用于需要高效率数据传输的场景。
并行通信的缺点:1、传输距离近。2、并行通讯使用多跟数据线、信号之间容易有干扰,抗干扰能力较差。3、设计难度大,并行通讯需要使用多个传输线和多路复用器(多路复用器是一种设备,能接收多个输入信号,按每个输入信号可恢复方式合成单个输出信号。复用器是一种综合系统,通常包含一定数目的数据输入,有一个单独的输出。)等复杂的硬件设计。
并行通讯应用场景:1、大数据传输:并行通信可以同时传输多个比特位,数据带宽更大,适用于需要大数据传输的场景,如高清视频传输等。2. 高效率数据传输:并行通信可以同时传输多个比特位,传输效率更高,适用于需要高效率数据传输的场景,如并行计算等。
总结:
现在我们多用的是串行通信,原因如下:
现在随着技术的发展,时钟频率越来越高,并行导线之间的相互干扰越来越严重。并行接口因为有多条并行且紧密的导线,时钟频率提高的一定程度时,传输的数据已经无法恢复。
而串口因为导线少,线间干扰 容易控制,反而可以通过不断提高时钟频率来提高传输速率。而且串口的端子也会比较小。这就是为什么现在高速传输都采用串行方式的原因。
串行通信的发展:
在传统的串行通讯中,一条线路来传输一个比特位。高电平表示为“1”,低电平表示为“0”。倘若在数据传输过程中受到干扰,高低电平信号完全可能因此产生突破临界值的大幅度扰动,一旦高电平或低电平信号超出临界值,信号就会出错。现在随着技术的发展,越来越多的应用场合采用高速率的串行差分传输。差分传输是指在串行数据传输过程中,使用两个信号线的差分信号来表示数据信号。差分信号的优点是可以减少共模干扰,抗干扰能力提高,因此数据传输距离更远。
1.2全双工、半双工及单工通讯
根据数据通讯的方向,通讯又分为全双工、半双工及单工通讯,它们主要以信道的方 向来区分。仍以公路来类比,全双工的通讯就是一个双向车道,两个方向上的车流互不相干;半双工则像乡间小道那样,同一时刻只能让一辆小车通过,另一方向的来车只能等待道路空 出来时才能经过;而单工则像单行道,另一方向的车辆完全禁止通行。
在单工通信方式中,信号只能向一个方向传输。例如:无线广播电台的广播、电视播放。在半双工通信方式中,信号可以双向传送,但必须交替进行,在任一时刻只能向一个方向传送。例如:IIC。在全双工通信方式中,信号可以同时双向传送数据。例如:SPI、串口。
1.3同步通讯与异步通讯
根据通讯的数据同步方式,又分为同步和异步两种,可以根据通讯过程中是否有使用 到时钟信号进行简单的区分。
同步通讯:收发设备双方使用一根信号线表示时钟信号,在时钟信号的驱动下双方进行协调,同步数据。通讯中通常双方会统一规定在时钟信号的上升沿或 下降沿对数据线进行采样。如下图:
异步通讯:不使用时钟信号进行数据同步,而是在数据信号中穿插一些同步用的信号位,或者把主体数据进行打包,以数据帧的格式传输数据。在某些通讯中还需双方约定好通讯速率(即波特率),以便更好地同步。如下图
在同步通讯中,数据信号所传输的内容绝大部分就是有效数据,而异步通讯中会包含有帧的各种标识符,所以同步通讯的效率更高,但是同步通讯双方的时钟允许误差较小, 而异步通讯双方的时钟允许误差较大。
1.3通讯速率
衡量通讯性能的一个非常重要的参数就是通讯速率。
通讯速率通常以比特率来表示:每秒传输的二进制位数,(bit/s)。而容易与其混淆的概念“波特率”是指每秒传输了多少个码元。码元:在数字通信中常常用时间间隔相同的符号来表示一个二进制数字,这样的时间间隔内的信号称为(二进制)码元。如常见的通讯传输中, 用 0V 表示数字 0,5V 表示数字 1,那么一个码元可以表示两种状态 0 和 1,所以一个码元 等于一个二进制比特位,此时波特率的大小与比特率一致;如果在通讯传输中,有 0V、 2V、4V 以及 6V 分别表示二进制数 00、01、10、11,那么每个码元可以表示四种状态, 即两个二进制比特位,所以码元数是二进制比特位数的一半,这个时候的波特率为比特率 的一半。因为很多常见的通讯中一个码元都是表示两种状态,人们常常直接以波特率来表 示比特率,虽然严格来说没什么错误,但希望您能了解它们的区别。
二、USART
简介:
同步异步收发器(Universal Synchronous Asynchronous Receiver and Transmitter)是一 个串行通信设备,可以灵活地与外部设备进行全双工数据交换。UART,它是在 USART 基础上裁剪掉了同 步通信功能,只有异步通信。
USART是STM32内部集成的硬件外设,可根据数据寄存器的一个字节数据自动生成数据帧时序,从TX引脚发送,RX引脚接收存放到数据寄存器里。
USART 在 STM32 应用最多莫过于“打印”程序信息,一般在硬件设计时都会预留一 个 USART 通信接口连接电脑,用于在调试程序是可以把一些调试信息“打印”在电脑端 的串口调试助手工具上。
主要特征:
1、全双工异步通信。USART 支持同步单向通信和 半双工单线通信;
2、使用了小数波特率发生器,可以提供多种波特率。最高达4.5Mbits/s。
3、可编程数据字长度(8位或9位)。可配置的停止位-支持1或2个停止位。
4、配置的使用DMA的多缓冲器通信。可实现数据的高速通信。
功能框图:
①:TX:数据发送。低位在前,高位在后。RX:数据接收。
SCLK:发送器时钟输出引脚,该引脚仅适用于同步模式。
SW_RX:数据接收引脚,只用于单线和智能卡模式,属于内部引脚,没有具体外部引脚。 nRTS:请求以发送(Request To Send),n 表示低电平有效。如果使能 RTS 流控制,当 USART 接收器准备好接收新数据时就会将 nRTS 变成低电平;当接收寄存器已满时, nRTS 将被设置为高电平。该引脚只适用于硬件流控制。
nCTS:清除以发送(Clear To Send),n 表示低电平有效。如果使能 CTS 流控制,发送 器在发送下一帧数据之前会检测 nCTS 引脚,如果为低电平,表示可以发送数据,如果为 高电平则在发送完当前数据帧之后停止发送。该引脚只适用于硬件流控制。
②:USART 数据寄存器(USART_DR)只有低 9 位有效,并且第 9 位数据是否有效要取决于 USART 控制寄存器 1(USART_CR1)的 M 位设置。我们一般使用8位数据字长。
USART_DR 实际是包含了两个数据寄存器,一个专门用于发送的可写 TDR,一个专门用于接收的可读 RDR。发送时把 TDR 内容转移到发送移位寄存器,然后把移位寄存器数据每一位发送出去,接收时把接收到的每一位顺序保存在接收移位寄存器内然后才转移到 RDR。
③:USART有专门的控制发送的发送器,控制接收的接受器,唤醒单元、中断控制等。
在发送数据时,编程的时候有几个比较重要的标志位我们来总结下。
在接收数据时,编程的时候有几个比较重要的标志位我们来总结下。
④:小数波特率生成
波特率指单位时间内传送码元符号的个数。它是对符号传输速率的一种度量。对于 USART 波特率与 比特率相等,以后不区分这两个概念。波特率越大,传输速率越快。
-
两者之间的关系在于,波特率决定了在信号中每秒钟有多少个状态变化,而比特率则决定了每每秒传输的比特数。在数字通信中,波特率和比特率通常是相等的,即每秒钟有多少个状态变化就传输多少比特,因此通常可以将它们混用。在某些特定情况下,波特率和比特率可能不相等,例如如果我们采用两个二进制表示一个码元,此时波特率就是比特率的一半
USART 的发送器和接收器使用相同的波特率。fPLCK 为 USART 时钟, USARTDIV 是一个存放在波特率寄存器(USART_BRR) 的 一个 无符 号定 点数。
⑤:一个字符帧发送需要三个部分:起始位+数据帧+停止位。当选择 8 位字长,使用 1 个停止位,无校验,具体发送字符时序图见图:
UART使用简例流程:
一、开启UART外设时钟,开启UART对应输入输出管脚的时钟。如STM32F103VET6的UART1管脚为PA9,PA10。故开启GPIOA时钟。
注:TX管脚配置为复用推挽输出,RX管脚配置为输入模式
二、USART结构体初始化。
三、对于串口接收来说可以使用查询和中断两种办法,
如果使用查询那串口初始化就结束了,直接接下来UART使能就行。 查询流程:在主函数里不断判断RXNE标志位,若置1则说明收到了数据,读取数据即可。
如果使用中断则还需要开启中断,配置NVIC通道,查询RXNE标志位。RXNE一旦置1,就会像NVIC申请中断。即会读取数据。注:不要忘记配置中断服务函数。
四、UART使能
五、我们已经配置好了UART,下面就可以根据UART.h的封装好的函数进行数据收发封装了。UART 在 STM32 应用最多莫过于“打印”程序信息,一般在硬件设计时都会预留一 个 UART 通信接口连接电脑,用于在调试程序是可以把一些调试信息“打印”在电脑端 的串口调试助手工具上。可以自己封装发送一个数据/多个数据。接收一个数据/多个数据的函数。当然注意判断(等待)数据收发标志位,防止数据传输错误。如下
六、我们还可以重定向printf函数,将printf打印的东西输出到串口,我们就可以直接使用printf函数了。
UART中断请求
UART的各种中断事件被连接到同一个中断向量。通过使能这些事件对应的中断标志,
发送期间:发送完成、清除发送、发送数据寄存器空。
接收期间:空闲总线检测、溢出错误、接收数据寄存器非空、校验错误、LIN断开符号检 测、噪音标志(仅在多缓冲器通信)和帧错误(仅在多缓冲器通信)。可以开启对应的中断,在相应的中断函数里执行指定行为。
三、RS-232
简介:
在串行通讯时,要求通讯双方都采用一个标准接口,使不同的设备可以方便地连接起来进行通讯。。RS-232标准接口是常用的串行通信接口标准之一。而工业控制的RS-232口一般只使用RXD、TXD、GND三条线。
RS232是依附于UART,那既然已经有了UART这种通信协议,我们为什么还要规定新的通信协议呢?为了解决UART的一些问题,人们依附于UART,规定了RS232——较UART一种更为优良的通信协议。
特点:
灵活的波特率选择:RS-232规定的标准传送速率有50b/s、75b/s、110b/s、150b/s、300b/s、600b/s、1200b/s、2400b/s、4800b/s、9600b/s、19200b/s,可以灵活地适应不同速率的设备。
采用负逻辑传送:规定逻辑“1”的电平为-3V~-15 V,逻辑“0”的电平为+3 V~+15 V。选用该电气标准的目的在于提高抗干扰能力,增大通信距离。
传送距离较远:由于RS -232采用串行传送方式,并且将微机的TTL电平转换为RS-232C电平,其传送距离一般可达30 m。
缺点:
(1)接口的信号电平值较高,易损坏接口电路的芯片,又因为与TTL电平不兼容故需使用电平转换电路方能与TTL电路连接。
(2)传输速率较低,在异步传输时,波特率为20Kbps;因此在CPLD开发板中,综合程序波特率只能采用19200,也是这个原因。
(3)接口使用一根信号线和一根信号返回线而构成共地的传输形式,这种共地传输容易产生共模干扰,所以抗噪声干扰性弱。
尽管RS232的出现已经解决UART的很多问题,但是能不能有一种通信速度更快,抗干扰能力更强,传输距离更长的通信协议呢?当然有了,RS485应运而生。
四、RS485
简介:
是隶属于OSI模型物理层的电气特性规定为2线制、半双工、多采用屏蔽双绞线传输,这种接线方式为总线式拓扑结构在同一总线上最多可以挂接32个结点。可以在有电子噪声的环境下进行长距离有效率的通信。用缆线两端的电压差值来表示传递信号,不同的电压差分别标识为逻辑1及逻辑0。两线间的电压差为+2V到+6V为逻辑“1”,-2V—-6V表示逻辑“0” 。(处理器一般产生的是TTL信号,不符合485标准,因此我们需要添加转换芯片将TTL信号转化为差分信号,例如MAX485)。在线性多点总线的配置下,可以在一个网络上有多个接收器。
RS485的优势
1.RS-485的接口信号与RS-232相比降低了,不易损坏芯片。
2.RS-485接口是采用平衡驱动器和差分接收器的组合,抗共模干能力增强,即抗噪声干扰性好。
3.通信速度快,最高传输速率为10Mbps。
4.延长通信的距离,RS-485接口的最大传输距离标准值为4000英尺,实际上可达3000米。
5.RS-485接口的最大传输距离标准值为4000英尺,实际上可达3000米,另外RS-232-C接口在总线上只允许连接1个收发器,即单站能力。而RS-485接口在总线上是允许连接多达128个收发器。即具有多站能力,这样用户可以利用单一的RS-485接口方便地建立起设备网络。
五、IIC
简介:
I2C 通讯协议(Inter-Integrated Circuit)是由 Phiilps 公司开发的。其引脚少、实现简单、可扩展性强、现广泛使用在系统内多个集成电路之间通信。它支持同步、半双工、支持总线挂载多设备。
设备的SCL和SDA均要配置成开漏输出模式
IIC物理层:
物理层规定通讯系统中具有 机械、电子功能部分的特性,确保原始数据在物理媒体的传输。一个IIC通信总线中可以连接多个IIC从设备。
1、一个IIC通讯系统只使用两条总线线路。(双向串行)SDA:数据传输,SCL:时钟线用于数据收发同步。
2、每个连接到总线的设备都有一个独立的地址,主机可以利用这个地址对不同的从机进行访问。
3、总线通过上拉电阻接到电源,当IIC设备空闲时,会输出高阻态。而当所有设备都空闲时,都输出高阻态时,由上拉电阻将总线拉到高电平。
4、总线仲裁机制
5、三种数据传输模式:标准模式:传输速率100kbit/s、快速模式:400kbit/s。高速模式3.4Mbit/s
IIC协议层:
协议层主要规定通讯逻辑, 统一收发双方的数据打包、解包标准。
软件IIC通信过程:
1、起始信号
2、发送从机地址,发送传输方向的选择位(0为写,1为读)。接收从机返回的应答信号(0表示应答,1表示非应答)。若应答则说明总线上存在这个从机。
3.1、若选择当前地址读从机则:时序图如下
如图可得,在步骤1、2之后紧接着IIC主机“读取一个字节的数据并向从机发送 发送应答”。依次循环n次即可连续读取指定地址下的n个数据。当主机希望停止接收数据时,可以向从机返回一个非应答信号(NACK),则从机自动停止数据传输。
3.2、若选择当前地址写从机:时序图如下:
如图可得,在步骤1、2之后紧接着IIC主机“发送一个数据,并接收 从机发送的 接收应答”。依次循环n次即可连续写指定地址下的n个数据。当数据传输结束时,主机向从机发送一个停止传输信号,表示不 再传输数据。
3.3主机指定地址读/写从设备 内部寄存器或存储器,时序图如下:
该模式包含两次起始信号。即起始+当前地址写 + 重复起始信号 + 指定地址读/写+停止。
软件IIC的六个基本时序单元
软件IIC即 自己手动模拟时钟信号进行数据通讯.
写SCL,读SDA,写SDA
起始:SCL高电平期间,SDA由高电平变为低电平 由于初始SDA电平不确定,故要先释放SDA,然后拉高时钟,拉低SDA,拉低SCL.
结束:SCL高电平期间,SDA由低电平变为高电平 由于初始SDA电平不确定,故要先拉低SDA,然后拉动SCL,拉高SDA,拉高SCL
发送一个字节: 初始时SCL低电平,主机将数据位依次放到SDA线上(主机写SDA)(高位先行),然后释放SCL,从机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,然后拉低SCL为下次发送数据作准备。。依次循环上述过程8次,即可发送一个字节.
void MyI2C_SendByte(uint8_t Byte)//发送一个字节
{
//开始时SCL是低电平
uint8_t i;
for(i=0;i<8;i++)
{
MyI2C_W_SDA(Byte & (0x80 >> i));
MyI2C_W_SCL(1);
MyI2C_W_SCL(0);
}
}
接收一个字节:初始时SCL低电平,主机要先释放SDA.从机将数据位依次放到SDA线上(高位先行),然后拉高SCL,主机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,读取完成后,要在拉低SCL为下一次数据读取做准备。。依次循环上述过程8次,即可接收一个字节(主机在接收之前,需要释放SDA)
uint8_t MyI2C_ReceiveByte(void)//接收一个字节
{
//开始时SCL是低电平
uint8_t i,Byte=0x00;
MyI2C_W_SDA(1); //主机先释放SDA
//{从机若发1则释放SDA,若发0则拉低SDA}
for(i=0;i<8;i++)
{
MyI2C_W_SCL(1);
if(MyI2C_R_SDA()==1)//返回读到SDA线的电平
{
Byte |= (0x80 >> i );
}
MyI2C_W_SCL(0);
}
return Byte;
}
发送应答:主机在接收完一个字节之后,在下一个时钟发送一位数据,然后SCL拉高,高电平期间从机读取数据,数据0表示应答,数据1表示非应答(即主机发送一位数据,告诉从机是否继续接收数据)。之后SCL拉低为之后流程做准备状态。
void MyI2C_SendACK(uint8_t AckBit)//发送应答
{
//开始时SCL是低电平
MyI2C_W_SDA(AckBit);
MyI2C_W_SCL(1);
MyI2C_W_SCL(0);
}
接收应答:主机在发送完一个字节之后,在下一个时钟从机发来的接收一位数据,判断从机是否应答,数据0表示应答,数据1表示非应答。
uint8_t MyI2C_ReceiveACK(void)//接收应答
{
//开始时SCL是低电平
uint8_t AckBit;
MyI2C_W_SDA(1); //主机先释放SDA
//{从机若发1则释放SDA,若发0则拉低SDA}
MyI2C_W_SCL(1);
AckBit= MyI2C_R_SDA(); //返回读到SDA线的电平
MyI2C_W_SCL(0);
return AckBit;
}
硬件IIC
STM32内部集成了硬件IIC收发电路,能由硬件自动执行时钟生成\起始\终止\数据收发\应答位收发等功能.能减轻CPU负担.同时支持多主机模型 支持7位/10位地址模式 支持不同的通讯速度,标准速度(高达100 kHz),快速(高达400 kHz) 支持DMA.
硬件IIC框图
硬件IIC收发过程
使用 I2C 外设通讯时,在通讯的不同阶段它会对“状态寄存器(SR1 及 SR2)”的不同数 据位写入参数,我们通过读取这些寄存器标志来了解通讯状态。
I2C 通讯的主机端向外发送数据 时的过程如下;
主机发送起始信号(S),等待EV5事件(状态寄存器的SB位为1),表示起始信号已发送.
主机发送从机地址并等待从机应答,若有从机应答则产生EV6事件(SR的ADDR位为1表示地址已发送),EV8事件(SR的TXE=1表示数据寄存器为空),当DR为空时,此时主机可以将待发送数据写入数据寄存器等待发送.这时 TXE 位会被重置 0,表示数据寄存器非空.硬件IIC自动将数据在SDA信号线上一位一位发送出去,又产生EV8事件(TXE=1,可继续发送数据),当主机希望停止发送数据,则,控制 I2C 设备产生一个停止信号(P),这个时候会产生 EV8_2 事件,SR1 的 TXE 位及 BTF 位都被置 1,表示通讯结束。
I2C 通讯的主机端接收数据 时的过程如下;
主机发送起始信号(S),等待EV5事件(状态寄存器的SB位为1),表示起始信号已发送.
主机发送从机地址并等待从机应答,若有从机应答则产生EV6事件(SR的ADDR位为1表示地址已发送).从机端接收到地址后,开始向主机端发送数据。当主机接收到这些数据后,并产 生“EV7”事件,SR1 寄存器的 RXNE 被置 1,表示接收数据寄存器非空.我们即可读取DR,主机发送应答信号或非应答信号.若应答,则重复以上步骤接收 数据,若非应答,则停止传输;发送非应答信号后,产生停止信号(P),结束传输。
六、SPI
简介:
SPI 协议是由摩托罗拉公司提出的通讯协议(Serial Peripheral Interface),即串行外围设 备接口,是一种高速同步全双工的通信总线。它被广泛地使用在 ADC、LCD 等设备与 MCU 间, 要求通讯速率较高的场合。
所有SPI设备的SCK、MOSI、MISO分别连在一起
输出引脚配置为推挽输出,输入引脚配置为浮空或上拉输入
SPI通讯设备常见连接方式:
SPI通讯 支持主机与多个SPI从设备相连.每一个从设备有一个独立的nSS片选线.。I2C 协议中通过设备地址来寻址、 选中总线上的某个设备并与其进行通讯;而 SPI 协议中没有设备地址,它使用 nSS 信 号线来寻址
SCK (Serial Clock):时钟信号线,用于通讯数据同步.
MOSI (Master Output, Slave Input):主设备输出/从设备输入引脚
MISO(Master Input,,Slave Output):主设备输入/从设备输出引脚
SPI协议层:
软件SPI:
SPI 基本通讯过程:
SPI的基本时序单元:
起始:NSS由高变低
终止;NSS由低变高
//起始信号
void MySPI_Start(void)
{
MySPI_W_SS(0);
}
//终止信号
void MySPI_Stop(void)
{
MySPI_W_SS(1);
}
SPI使用SCL进行数据同步.且数据输入输出是同时进行的.SPI一共有四种通讯模式,他们的区别主要是总线空闲时SCK的时钟状态以及数据采样时刻(上升沿还是下降沿采样).在这里我们需要熟悉入“时钟极性 CPOL”和“时钟相位 CPHA”的概念。
CPOL:指SPI空闲时,SCL电平状态,
CPHA:指数据的采样时刻
二者关系如下
主机与从机需要工 作在相同的模式下才可以正常通讯,实际中采用较多的是“模式 0”与“模式 3”。
这里我们使用模式0(CPOL=0,CPHA=0)进行讲解:
交换一个字节(模式0):
CPOL=0:空闲状态时,SCK为低电平
CPHA=0:奇数边沿采样
注:由于SCK第一个即为奇数边,故MOSI移除数据会提前一段时间,当SCK第一个上升沿来临时,主机开始采样,在非采样时刻,主机才可以继续移出数据,循环8次即交换一个字节。可以看到在最后SCK下降沿时候主机和从机已经提前将下一个数据的第一位移出。
主机首先选择从机,拉低nSS, ,主机在SCK低电平时 通过MOSI将数据移出一位,接着将SCK拉高,在SCK上升沿期间通过MISO读入一位数据.SCK下降沿时 通过MOSI将数据移出一位 往复循环8次即交换一个字节
交换一个字节(模式3):
CPOL=1:空闲状态时,SCK为高电平
CPHA=1:偶数边采样
软件SPI收发过程:
软件SPI即自己手动模拟SCK电平状态进行数据的交换。这里我们依据STM32F103VET6开发板进行模拟,nSS,SCK,MISO,MOSI这四个管脚我们可以任意指定,只要模拟出正确的时序即可。这里我们指定的管脚选择和硬件SPI的管脚相同,以后在写硬件SPI时就可以轻松移植改动了。
基本读写函数:从机选择、写SCK、写MOSI,读MISO。
//从机选择
void MySPI_W_SS(uint8_t BitValue)
{
GPIO_WriteBit(GPIOA,GPIO_Pin_4,(BitAction)BitValue);
}
void MySPI_W_SCK(uint8_t BitValue)
{
GPIO_WriteBit(GPIOA,GPIO_Pin_5,(BitAction)BitValue);
}
void MySPI_W_MOSI(uint8_t BitValue)
{
GPIO_WriteBit(GPIOA,GPIO_Pin_7,(BitAction)BitValue);
}
uint8_t MySPI_R_MISO(void)
{
return GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6);
}
下面就可以模拟时序进行交换一个字节的函数编写:
这里我们用掩码依次提取数据的每一位,模拟时钟信号,在恰当的时机进行数据移出和采样。
注:下面的是 模式0
uint8_t MySPI_SwapByte(uint8_t ByteSend)
{
uint8_t ByteReceive = 0x00,i;
for(i=0;i<8;i++)
{
MySPI_W_MOSI(ByteSend & (0x80 >> i )); //从机的发送不归我们管.(右移)
MySPI_W_SCK(1);//上升沿之后,主机和从机同时移入数据,这里我们只需要读取主机移入的数据,从机不归我们管
if(MySPI_R_MISO() == 1) ByteReceive |= (0x80 >> i);
MySPI_W_SCK(0);
}
return ByteReceive;
}
硬件SPI:
STM32的SPI外设可作为通讯的主机或从机,支持最高SCK时钟频率为Fpclk/2,支持SPI协议的4种模式,可设置数据MSB(高位先行),LSB(低位先行)。还可以同时使用MIOS,MOSI数据线向一个方向传输数据。这里我们只讲解全双工模式。。
硬件SPI框图:
硬件SPI的通讯信号引到不同的GPIO引脚少。使用时必须配置到这些规定的引脚。
实际应用中,我们一般不使用 STM32 SPI 外设的标准 NSS 信号线,而是更简单地使用 普通的 GPIO,软件控制它的电平输出,从而产生通讯起始和停止信号。
SPI的MOSI及MISO都连接到数据移位寄存器上, 当向外发送数据时,数据移位寄存器以发送缓冲区为数据源,一位一位地发送。当接收数据时,数据移位寄存器将采样到的数据一位一位地存储到接收缓冲区。通过读DR可以获得接收缓冲区的内容。
硬件SPI通讯过程:
STM32使用SPI外设时,在通讯的不同阶段它会对“状态寄存器SR”写入不同的参数。通过读取SR我们可以了解通讯状态。
硬件SPI 通讯的主机端的数据收发过程:
1、NSS产生起始信号
2、检测SR的TXE是否为1,若为1则发送缓冲区为空。将待发送的数据写到DR,数据被存储到发送缓冲区。
3、通讯开始,SCK 时钟开始运行。MOSI 把发送缓冲区中的数据一位一位地传输出 去;MISO 则把数据一位一位地存储进接收缓冲区中
4、当发送完一帧数据时,发送数据缓冲区为空,TXE=1。表示传输完一帧数据;类似地当接收完一帧数据时,RXNE=1,表示接收数据缓冲区非空,我们可以在此时读取DR获得接收缓冲区内容。
//使用掩码依次提取数据每一位 交换一个字节
uint8_t MySPI_SwapByte(uint8_t ByteSend)
{
while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)!=SET);//(读DR)TXE,(写DR)RXNE无需手动清除
SPI_I2S_SendData(SPI1,ByteSend);
while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE)!=SET);
return SPI_I2S_ReceiveData(SPI1);
}