1.通讯方式——串行与并行
从一个MCU发送数据到另一个MCU,可以选择两种通讯方式:串行通讯与并行通讯。
串行通信是一种将数据一个位一个地传输的方式。在串行通信中,数据通过单个信道传输,一个位接一个位地传输。例如,串行通信可以通过电缆或光纤将数据从一台计算机传输到另一台计算机。串行通信的优点是可以使用较少的信道传输大量数据,但是传输速度较慢。串行通信根据发送时源和接收时源是否保持一致,又分为同步通信和异步通信,其优点是只需要几条线就可以在系统之间交换信息。
并行通信是一种同时传输多个位的方式。在并行通信中,多个位同时传输,通常使用多个信道进行传输。例如,计算机内部使用并行通信将数据从内存传输到处理器。并行通信的优点是传输速度较快,但需要使用更多的信道来传输数据。成本高,不适宜远距离通信。
串行通信将数据一个位一个地传输,而并行通信则是一次传输多个位。
2.传输模式——单工、半双工、双工
2.串行通讯
常见的串行通讯有UART, I2C, JTAG, CAN, SPI, RS232, RS485等。
2.1 UART
2.1.1 硬件介绍
UART是一种双线,全双工,串行的总线协议。UART即通用异步收发器(Universal Asynchronous Receiver/Transmitter)。适用于短距离,点对点的通信。
硬件:RXD 用于接收信号。TXD 用于发送信号。
两设备使用串口通信时,A设备的RXD连接到B设备的TXD,B设备的RXD连接到A设备的TXD,交叉连接。
波特率:波特率是衡量UART通信速度的重要标准,单位(bit/s)。由于UART没有时钟同步线,所以两设备使用各自的时钟线。统一的波特率才能通信正确。如果连着发送很多数据,假设第二个数据开始错,后面的数据都会出错,所以为了防止累计误差,UART数据是一帧一帧的发送。MCU外设一般自带UART硬件外设,所以实际使用只需要配置寄存器,写好发送和接收函数。两设备的通信,波特率必须配置相同,实际使用中,乱码基本都是波特率不一致。常见的波特率有4800、9600、115200等。一个时钟周期的长度为波特率的倒数。
2.1.2 uart帧格式
UART通信一帧有起始位,数据位,奇偶校验位,停止位。
UART空闲位是高电平。
起始位:用来启动总线,要发送数据时将信号拉低一个时钟周期。
数据位:数据位可配置5-8位,数据位发送数据由低位到高位发送。
奇偶校验位:
奇校验:数据位中的1为偶数,校验位为1(保持为奇数)。
偶校验:数据位中的1为偶数,校验位为0(保持为偶数)。
无校验:可以没有校验位。
停止位:要结束发送数据时将信号拉高一个时钟周期,表示本帧数据通信结束。
帧格式图示:
2.1.2 uart协议工作过程
每次通信开始时,发送方发送一个逻辑“0”信号(VOL),表示传输字符的开始。由于总线空闲时为高电平,因此在开始通信时先发送一个与空闲状态明显不同的信号,即VOL。接收方检测到这个下降沿后认为开始传输数据,一般情况下接收方的采样率为时钟周期的1/8或者1/16,接收方在检测到下降沿后会在半个时钟周期后再次检测是否仍为低电平,以避免抖动引起的错误。
数据包的停止信号可以用0.5、1、1.5或2个逻辑1的数据位(即0.5、1、1.5或2个时钟周期的高电平)表示,只要双方同意即可。
2.1.2 实际应用
在实际应用中,可选用CH9102F芯片实现异步串口与USB之间的转换,如图,PD8和PD9分别接到MCU1的TXD和RXD。
在STM32中,使用UART中断通常需要进行以下步骤:
-
初始化UART:配置UART的波特率、数据位、停止位、校验位等参数,并启用相应的UART时钟。
-
配置NVIC(嵌套向量中断控制器):使能UART中断在NVIC中的对应通道,设置中断优先级。
-
启用UART中断:在UART的配置寄存器中设置相应的中断使能位,如启用接收中断、发送中断等。
-
编写中断处理函数:在中断处理函数中编写处理UART事件的代码,如读取接收到的数据、发送新的数据、处理错误等。
-
全局中断使能:最后,确保全局中断被使能,以便微控制器能够响应UART中断。
当UART事件发生时,微控制器会自动跳转到相应的中断处理函数执行中断服务例程(ISR),处理完中断后再返回到被中断的代码处继续执行。这种机制允许STM32在处理UART通信的同时,仍然能够执行其他实时任务。
2.2 I2C
I2C是一种串行同步的主从模式传输协议,使用两根线,一根数据线,一根时钟线。在这两根线上可以连接多个器件。在这些器件中,一个作为主机,其他作为从机,基本上谁控制时钟线(即控制SCL的电平高低变换)谁就是主设备。每个连接到总线上的器件都有唯一的地址,任何器件既可以作为主机也可以作为从机,但同一时刻只允许有一个主机。I2C 标准是一个具有冲突检测机制和仲裁机制的真正意义上的多主机总线,它能在多个主机同时请求控制总线时利用仲裁机制避免数据冲突并保护数据。作为嵌入式开发者,使用I2C总线通信的场景有很多,例如驱动FRAM、E2PROM、传感器等。
2.2.1 硬件介绍
I2C 总线在物理连接上非常简单,分别由SDA(串行数据线)和SCL(串行时钟线)及上拉电阻组成。通信原理是通过对SCL和SDA线高低电平时序的控制,来产生I2C总线协议所需要的信号进行数据的传递。在总线空闲状态时,SCL和SDA被上拉电阻Rp拉高,使SDA和SCL线都保持高电平。
I2C通信方式为半双工,只有一根SDA线,同一时间只可以单向通信,485也为半双工,SPI和uart通信为全双工。
2.2.1 帧格式
起始信号:SCL保持高电平,SDA由高电平变为低电平后,延时(>4.7us),SCL变为低电平。
终止信号:SCL保持高电平。SDA由低电平变为高电平。
应答位:每当主机向从机发送完一个字节的数据,主机总是需要等待从机给出一个应答信号,以确认从机是否成功接收到了数据。主机SCL拉高,读取从机SDA的电平,为低电平表示产生应答应答信号为低电平时,规定为有效应答位(ACK,简称应答位),表示接收器已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。应答出现在每一次主机完成8个数据位传输后紧跟着的时钟周期,低电平0表示应答,1表示非应答,
设备地址&读写位:多数从设备的地址为7位或者10位,一般都用七位。八位设备地址=7位从机地址+读/写地址,
-
0表示主设备向从设备(write)写数据,
-
1表示主设备向从设备(read)读数据
数据包:主设备发送完设备地址&读写位后,从设备回复应答信号,然后开始数据传输。如果之前发送的读写位为0,则数据传输过程中由主设备控制数据线发送数据,从设备负责发送应答位;反之,从设备控制数据线发送数据,主设备发送应答位。
IIC的每一帧数据由9bit组成,如果是数据帧则包括8bit数据+1bit应答,如果是地址帧,则包括7bit地址+1bit读/写+1bit应答。
2.2.2 工作过程
在发送数据时,先发送高位,再发送低位。
2.3 SPI
spi是一种全双工、同步、串行、主从模式传输协议。使用四根线,一根时钟线,一根主设备发送线,一根主设备接收线和一根时钟线。
2.3.1 硬件介绍
MISO( Master Input Slave Output):主设备数据输入,从设备数据输出;
MOSI(Master Output Slave Input):主设备数据输出,从设备数据输入;
SCLK(Serial Clock):时钟信号,由主设备产生;
CS/SS(Chip Select/Slave Select):从设备使能信号,由主设备控制,一主多从时,CS/SS是从芯片是否被主芯片选中的控制信号,只有片选信号为预先规定的使能信号时(高电位或低电位),主芯片对此从芯片的操作才有效。
2.3.2 工作模式
SPI 通信中有 4 种不同的操作模式,不同的从机设备可能在出厂时就被设置好了某种模式,并且无法更改。但是 SPI 通信必须处于同一种模式下才能进行。因此我们应该对自己手里的 SPI 主机设备进行模式的配置,也就是通过 CPOL(时钟极性) 和 CPHA(时钟相位) 来控制 SPI 主设备的通信模式。
时钟极性(CPOL) 定义了 SCLK 时钟线空闲状态时的电平:
1.CPOL=0,即SCLK=0,表示 SCLK 时钟信号线在空闲状态时的电平为低电平,因此有效状态为高电平。
2.CPOL=1,即SCLK=1,表示 SCLK 时钟信号线在空闲状态时的电平为高电平,因此有效状态为低电平。
时钟相位(CPHA) 定义了数据位相对于时钟线的时序(即相位):
1.CPHA=0,即表示输出 (out) 端在上一个时钟周期的后沿改变数据,而输入 (in) 端在时钟周期的前沿(或不久之后)捕获数据。输出端保持数据有效直到当前时钟周期的尾部边缘。对于第一个时钟周期来说,第一位的数据必须在时钟前沿之前出现在 MOSI 线上。也就是一个 CPHA=0 的周期包括半个时钟空闲和半个时钟置位的周期。
2.CPHA=1,即表示输出 (out) 端在当前时钟周期的前沿改变数据,而输入 (in) 端在时钟周期的后沿(或不久之后)捕获数据。输出端保持数据有效直到下一个时钟周期的前沿。对于最后一个时钟周期来说,从机设备在片选信号消失之前保持 MISO 信号线有效。也就是一个 CHPA=1 的周期包括半个时钟置位和半个时钟空闲的周期。
Note:此处的前沿和后沿的意思表示在每个周期中第一个出现的边沿和最后一个出现的边沿。总的来说则为:当时钟为正向时钟时,时钟线的上升沿为前沿,时钟的下降沿为后沿,反之。
如下表,为 SPI 通信的 4 种模式:
2.3.3 工作过程
SPI数据通信的流程可以分为以下几步:
1、主设备发起信号,将CS/SS拉低(或拉高,具体根据芯片手册),启动通信。
2、主设备通过发送时钟信号,来告诉从设备进行写数据或者读数据操作(采集时机可能是时钟信号的上升沿(从低到高)或下降沿(从高到低),因为SPI有四种模式,后面会讲到),它将立即读取数据线上的信号,这样就得到了一位数据(1bit)。
3、主机(Master)将要发送的数据写到发送数据缓存区(Menory),缓存区经过移位寄存器(缓存长度不一定,看单片机配置),串行移位寄存器通过MOSI信号线将字节一位一位的移出去传送给从机,同时MISO接口接收到的数据经过移位寄存器一位一位的移到接收缓存区。
4、从机(Slave)也将自己的串行移位寄存器(缓存长度不一定,看单片机配置)中的内容通过MISO信号线返回给主机。同时通过MOSI信号线接收主机发送的数据,这样,两个移位寄存器中的内容就被交换。
例如,下图示例中简单模拟SPI通信流程,主机拉低NSS片选信号,启动通信,并且产生时钟信号,上升沿触发边沿信号,主机在MOSI线路一位一位发送数据0X53,在MISO线路一位一位接收数据0X46,如下图所示: