通信协议UART、i2c、SPI与电平标准梳理

2023-12-18 10:14:34

今年入门嵌入式以来看了很多教程和文档,短时间内接触了很多新知识但是却没有相应的项目经验,所以难免混淆了一些嵌入式技术和知识。最近强化学习了一遍这些概念,看了很多别人写的文章,发现了一些之前遗漏的细节,正好写一篇笔记录整合一下看的资料。仅作为个人后续的翻阅资料。

一、前言

有的教程中概念很多,比如I2C、UART、SPI、TLL、RS232等等,首先要分清楚什么是电平标准,什么是通信协议。通信协议就是一种规定好的数据格式,用这种规定好的数据格式来传输信息和进行设备之间的通信。比如我规定发送的一帧数据有多少位,第几位表示什么意思,接受设备收到数据后是否应答等等,这就是通信协议。嵌入式设备上用的这些通信协议相比计算机网络那些来讲都比较容易理解。

电平标准通俗来讲就是规定使用什么电气属性来表示“0”和“1”,其实我觉得也可以理解为一种硬件层面的协议。有了电平标准之后就可以来承载通信协议。

二、电平标准

常见的电平标准有TTL、CMOS、RS232、RS485等等,电平标准描述转载自这篇博客这篇博客,稍微做了一些补充后将其贴在下面

2.1 TTL

TTL电平标准如下:

供电范围在0~5V;如74系列都是5V供电

对输出:大于2.7V是逻辑高电"1";小于0.5V是逻辑低电平"0"

对输入:大于2V是逻辑高电平"1";小于0.8V是逻辑低电平"0"

注意:TTL电平输入脚悬空时内部认为是高电平,且TTL电平输出不能驱动CMOS电平输入。

如果想了解TTL电平的电路实现原理,可以看一下这篇博客

2.2 CMOS

CMOS电平标准如下:

供电范围在3~15V;如4000系列(4011与非门)

假设5V供电

对输出:大于4.6V是逻辑高电平"1";小于0.05V是逻辑低电平"0"

对输入:大于3.5V是逻辑高电平"1";小于1.5V是逻辑低电平"0"

如果想了解CMOS电平的电路实现原理,可以看一下这篇博客

2.3 RS232

RS232电平标准如下:

对输出:输出“1”时的电平应在-5-15 V之间,输出“0”时的电平应在+5+15 V之间

对输入:输入电平在-3-15 V之间被认为“1”,在+3+15 V之间被认为“0”

当线路上不传送数据(空闲)时,发送器输出为“1

可以看得出,RS232与TTL是不兼容的,TTL在输出0v的时候是RS232的非法状态,所以TTL到RS232电平标准需要电平转换芯片。而且RS232传输速率较低,在异步传输时,波特率为20Kbps。

2.3 RS485

RS485电平标准如下:

RS485 通信采用差分信号传输,通常情况下只需要两根信号线就可以进行正常的通信。
在差分信号中,逻辑0和逻辑1是用两根信号线(A+和B-)的电压差来表示。

逻辑 1:两根信号线(A+和B-)的电压差在 +2V~+6V 之间。
逻辑 0:两根信号线(A+和B-)的电压差在 -2V~-6V 之间。

也与TTL不兼容,通常会使用 485 收发器来转换 TTL 电平和 RS485 电平。RS485的数据最高传输速率为10Mbps,远高于RS232,并且因为采用差分信号传输的方式,所以抗干扰能力强。

三、通信协议

首先要了解一些基本的概念,这些概念的解释引自这篇博客这篇博客

  • 串行通信/并行通信
 串行通信:是指计算机与I/O设备之间,同一时刻,只能传输一个bit位的信号。传输数据按顺序依次一bit位接一bit位进行传输,通常数据在一
 根数据线或一对差分线上传输。
 
 并行通信:时指计算机与I/O设备之间,通过多条传输线,可以同时传输多个bit位的信号。
  • 同步通信/异步通信
 同步通信:会利用一根额外的信号线,其实也就是时钟信号线,它往往是发送设备提供的时钟信号,发送设备和接收设备在发送设备提供的同一
 时钟频率下完成同步。
 
 异步通信:没有额外的一根信号线用于同步,接收者和发送者使用各自的时钟信号,接收者根据与发送者按事先约定的规来确定数据发送的开始
 与结束以及数据单位的持续时间。例如异步串行通信中,一般接收双方会确定一致的停止位,数据位的个数、波特率的大小以及是否采用奇偶校验位。
  • 单工通信/半双工通信/全双工通信
单工通信:是指数据只按照一个方向传送而不能反方向传送。

半双工通信:是指两个设备之间的数据可以双向通信,但不能同时进行,同一时刻只能我发你收或者你发我收。

全双工通信:对应于半双工通信,就是可以同时双向传输数据。
  • 波特率/比特率
波特率:指的是信号状态变化的次数或每秒传输的符号数。在通信系统中,携带数据信息的信号单元称为码元,也称为符号。
实际上波特已经是表示速率了,称为波特率只是中文习惯。波特率的单也是Symbol/秒

比特率:指的是每秒钟传输的比特数。

比特率 = 波特率 x 每个符号的比特数

上面的波特率定义是百度百科定义的,但是好像嵌入式领域中的波特率是另一种定义,看下来好像确实是用的下面这种定义:

波特率:描述信道的数据传输速度,单位是bit/s

比特率:指的是每秒钟传输的有效数据的比特数。

比特率 = 波特率 x 单个数据帧有效二进制位数的占比。
比如传输一个字节的数据(8),再加上起始位和停止位后变成10位构成一个“符号”,每s传输960个符号,那么波特率 = 96 x 100 = 9600(bit/s),比特率 = 960 x 8 = 9600 x (8/10) = 7680(bit/s)

了解了基本的一些概念之后就可以理解常见通信协议的一些细节了。

3.1 UART协议
3.1.1 UART采用的通信方式:
  • 串行通信
  • 异步通信
  • 可以单工(一个设备发送)/半双工(你发我收,我发你收)/全双工(两个设备同时收/发)通信
  • 一般小端传输

当使用TTL电平时,发送设备和接收设备一般有三个引脚要接:

在这里插入图片描述

  • RXD:设备的接收引脚,应与其他使用UART通信的设备的TXD引脚相接
  • TXD:设备的发送引脚,应与其他使用UART通信的设备的RXD引脚相接
  • GND:地线,两个通信设备的地线应该相连
3.1.2 UART数据帧格式

UART协议比较简单,其数据帧可由正点原子教程中的图来表示
在这里插入图片描述
其各数据位的作用转载自这篇博客,将其贴在下面

  • 起始位:当不传输数据时, UART 数据传输线通常保持高电压电平。若要开始数据传输,发送UART 会将传输线从高电平拉到低电平并保持1 个时钟周期。当接收 UART 检测到高到低电压跃迁时,便开始以波特率对应的频率读取数据帧中的位。
  • 数据位:数据帧包含所传输的实际数据。如果使用奇偶校验位,数据帧长度可以是5 位到 8 位。如果不使用奇偶校验位,数据帧长度可以是9 位。在大多数情况下,数据以最低有效位优先方式发送,即小端传输
  • 奇偶校验位:奇偶性描述数字是偶数还是奇数。通过奇偶校验位,接收 UART判断传输期间是否有数据发生改变。电磁辐射、不一致的波特率或长距离数据传输都可能改变数据位。校验位可以配置成 1 位偶校验或 1 位奇校验或无校验位。
  • 停止位:为了表示数据包结束,发送方将数据传输线从低电压驱动到高电压并保持1 到 2 位时间。
  • 空闲位:UART协议规定,接收到停止位之后,当总线处于空闲状态时信号线的状态为1即高电平,表示当前线路上没有数据传输。

同样在这篇博客中还讲了UART接收双方的通信步骤,比较详细,值得一看

3.1.3 一些理解:
  • 没有时钟线,接收方怎么确定是接收到了第几位?

    异步通信使以一个字符为传输单位,通信过程中两个字符之间的时间间隔是不固定的,但是在一个字符发送的过程中,一个字符内两个相邻bit的时间间隔是固定的。(这里可以放张图)

    所以只要规定好时间间隔是多久,再约定好一个字符有多少个bit(比如规定数据有几个bit,是否带奇偶检验位等等),就可以进行通信了。那怎么保证字符内相bit时间间隔固定呢,就需要在接受和发送双方约定同样的波特率,并且发送设备和接收设备都要有精密时钟振荡器/晶振来支持所设定的波特率。比如约定波特率为9600bit/s,那么一个电平持续时间(时间间隔)就应该是1/9600s

  • 那万一发送设备和接收设备时钟不一致了呢?比如差了0.5个间隔?

    这篇博客提到,对于UART来讲,只要保证在接受一个字符的时候主设备和从设备是时钟同步的即可。所以在下一个字符起始位的到来时可以依靠检测起始位来实现发送与接收方的时钟同步。

3.2 SPI协议
3.2.1 SPI通信方式
  • 串行
  • 同步通信
  • 全双工
  • 对大端和小端没做硬性规定,主从之间协商好就可以

这篇博客在一篇文章中就对SPI的解释的非常详细和全面了,我也没找到还有什么其他我疑惑的地方,所以这里只是做个传送门。

这篇博客用了一个例子来解释如何根据SPI从设备的手册使用SPI进行主从通信,也写的非常详细,这里放个传送门

在重新看了正点原子的spi教程之后也解决了我一个问题,就是什么时候开始发启动然后传输信息:对于不同的spi芯片有不同的设计方式,可以根据电平手册进行设置。正点原子上使用的spi芯片可以通过设置某个寄存器来设置两种启动传输方式:

  • 数据装入发送缓存中立即开始传输
  • 使能某个寄存器中的某一传输启动标志位后开始传输
3.3 I2C协议
  • 串行
  • 同步通信
  • 全双工
  • 一般为大端传输

这篇博客在一篇文章中就对i2c的解释的非常详细和全面,做个传送门。

I2C 总线内部使用漏极开路输出驱动器,因此 SDA和 SCL 可以被拉低为低电平,但是不能被驱动为高电平,所以每条线上都要使用一个上拉电阻,默认情况下将其保持在高电平。所以,在传输数据的过程中,时钟线SCL为高电平时,SDA线是不能发生变化的,否则会被认为是起始或者停止信号。

文章来源:https://blog.csdn.net/xi_xix_i/article/details/134902293
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。