目录

工欲善其事

实践出真知

活跃标签: linux java mysql 待分类 js springboot win10 电路 vue macOS nginx windows esp32 git docker idea maven esp8266 python Arduino

存档:

X

[ MCU ] 单片机通讯协议介绍!

单片机之间,单片机设备之间,电脑与单片机之间的通讯是基于通讯协议实现的。或者说任何设备之间的通讯都是基于某种约定(协议)的方式进行通讯的,因为他们真的只认识高低电平!

先来个表格

UARTRS232RS485I2CSPICAN

I2C

有时需要快速的进行数据的交互,为了使用最简单的方式使这些芯片互联互通,于是I2C诞生了,I2C( Inter-Integrated Circuit )是一种通用的总线协议。它是由Philips(飞利浦)公司,现NXP(恩智浦)半导体开发的一种简单的双向两线制总线协议标准。

对于硬件设计人员来说,只需要2个管脚,极少的连接线和面积,就可以实现芯片间的通讯,对于软件开发者来说,可以使用同一个I2C驱动库,来实现实现不同器件的驱动,大大减少了软件的开发时间。极低的工作电流,降低了系统的功耗,完善的应答机制大大增强通讯的可靠性。

5种速率

I2C协议可以工作在以下5种速率模式下,不同的器件可能支持不同的速率。

  • 标准模式(Standard):100kbps
  • 快速模式(Fast):400kbps
  • 快速模式+(Fast-Plus):1Mbps
  • 高速模式(High-speed):3.4Mbps
  • 超快模式(Ultra-Fast):5Mbps(单向传输)

其中超快模式是单向数据传输,通常用于LED、LCD等不需要应答的器件,和正常的I2C操作时序类似,但是只进行写数据,不需要考虑ACK应答信号。

在I2C协议的官方文档 NXP_UM10204_I2C-bus specification and user manual_Rev.6 ,超快模式和其他模式在3.2和3.1章节分别进行介绍。

4种信号

I2C协议最基础的几种信号: 起始、停止、应答和非应答信号

起始信号

I2C协议规定,SCL处于高电平时,SDA由高到低变化,这种信号是起始信号。

停止信号

I2C协议规定,SCL处于高电平,SDA由低到高变化,这种信号是停止信号。

数据有效性

I2C协议对数据的采样发生在SCL高电平期间,除了起始和停止信号,在数据传输期间,SCL为高电平时,SDA必须 保持稳定 ,不允许改变,在SCL低电平时才可以进行变化。

应答信号

I2C最大的一个特点就是有完善的应答机制,从机接收到主机的数据时,会回复一个应答信号来通知主机表示“ 我收到了 ”。

应答信号出现在1个字节传输完成之后,即第9个SCL时钟周期内,此时主机需要释放SDA总线,把总线控制权交给从机,由于上拉电阻的作用,此时总线为高电平,如果从机正确的收到了主机发来的数据,会把SDA拉低,表示应答响应。

使用MCU、FPGA等控制器实现时,需要在第9个SCL时钟周期把SDA设置为高阻输入状态,如果读取到SDA为低电平,则表示数据被成功接收到,可以进行下一步操作。

非应答信号

当第9个SCL时钟周期时,SDA保持高电平,表示非应答信号。

非应答信号可能是主机产生也可能是从机产生,产生非应答信号的情况主要有以下几种:

  1. I2C总线上没有主机所指定地址的从机设备
  2. 从机正在执行一些操作,处于忙状态,还没有准备好与主机通讯
  3. 主机发送的一些控制命令,从机不支持
  4. 主机接收从机数据时,主机产生非应答信号,通知从机数据传输结束,不要再发数据了

读写时序

向指定寄存器地址写入指定数据操作时序:

从指定寄存器地址读取数据操作时序:

注意,读数据时有两次起始信号。

7位和10位地址

大多数I2C器件支持7位地址模式,有一些器件还支持 10位地址 ,而且两种类型的器件可以连接在同一个I2C总线上,目前10位地址的器件 还没有被广泛使用

主机发送,从机接收。使用10位地址进行写时序:

主机接收,从机发送。使用10位地址进行读时序:

I2C保留字节

I2C读写时起始位之后的第一个字节,除了厂商指定的设备地址外,还有一些保留字节,主要有两组0000 xxx和1111 xxx,保留字节的含义:

上述的10位地址模式,就是使用到了最后一种 保留字节

第一种广播模式,可以通过写入第二个字节06h来 复位I2C总线上所有的从机器件 。具体操作时序可以查看文档NXP_UM10204_I2C-bus specification and user manual_Rev.6:3.1.12 Reserved addresses章节有详细介绍。其中device ID控制字(1111 1xx1),可以读取I2C器件内部的 24位器件ID ,通过对照NXP I2C协议器件列表可以查询到器件所属的 厂商和型号 。** **

设备ID与器件厂商对应表

工作过程

整体叙述一下I2C通讯过程

第1步:起始条件

主设备通过将SDA线从高电平切换到低电平,再将SCL线从高电平切换到低电平,来向每个连接的从机发送启动条件,如下图所示:

第2步:发送从设备地址

主设备向每个从机发送要与之通信的从机的7位或10位地址,以及相应的 读/写位 ,如下图所示:

第3步:接收应答

每个从设备将主设备发送的地址与其自己的地址进行比较。如果地址匹配,则从设备通过 将SDA线拉低一位以表示返回一个ACK位

如果来自主设备的地址与从机自身的地址不匹配,则从设备将SDA线拉高,表示返回一个NACK位。

第4步:收发数据

主设备发送或接收数据到从设备,如下图所示:

第5步:接收应答

在传输完每个数据帧后,接收设备将另一个ACK位返回给发送方,以确认已成功接收到该帧,如下图所示:

第6步:停止通信

为了停止数据传输,主设备将SCL切换为高电平,然后再将SDA切换为高电平,从而向从机发送停止条件,如下图所示:

1、单个主设备连接多个从机

I2C总线上的主设备使用7位地址对从设备进行寻址,可以使用128(2的7次方)个从机地址,如下图所示:

2、多个主设备连接多个从机** **

多个主设备可以连接到一个或多个从机。

当两个主设备试图通过SDA线路同时发送或接收数据时,同一系统中的多个主设备就会出现问题。

为了解决这个问题, 每个主设备都需要在发送消息之前检测SDA线是低电平还是高电平

  • 如果SDA线为低电平,则意味着另一个主设备可以控制总线,并且主设备应等待发送消息;
  • 如果SDA线为高电平,则可以安全地发送消息。


FPGA实测I2C波形

FPGA实现UARTSPI、I2C等串行时序,最常用的实现方式就是 状态机大法 ,将各个步骤分解为各个状态,然后根据不同的状态去控制输出或读取输入,细节方面需要考虑数据的对齐、建立和保持时间、一些异常情况时状态的跳转,不能进入死循环,或卡死在某一个状态。

I2C控制状态机状态定义:

//general
S0_IDLE       = 0,
S1_START1     = 1,
S2_CTRL_BYTE1 = 2,
S3_ACK1       = 3,
S4_ADDR       = 4,
S5_ACK2       = 5,

//write: 0-1-2-3-4-5->6-7-13-14
S6W_DATA      = 6,
S7W_ACK3      = 7,

//read: 0-1-2-3-4-5->8-9-10-11-12-13-14
S8R_START2     = 8,
S9R_CTRL_BYTE2 = 9,
S10R_ACK3      = 10,
S11R_DATA      = 11,
S12R_NACK      = 12,

//general
S13_STOP       = 13,
S14_DONE       = 14,
S15_ERR        = 15;

注意SDA双向端口的方向控制。

output eeprom_scl,
inout eeprom_sda,

localparam DIR_IN  = 1'b0;
localparam DIR_OUT = !DIR_IN;

reg dir;
reg i2c_sda;
reg i2c_scl;

assign eeprom_scl = i2c_scl;
assign eeprom_sda = (dir == DIR_OUT) ? i2c_sda : 1'bz;

wire sda_in = eeprom_sda;

SDA应该在第9个SCL时钟周期设置为输入状态:

下图的波形是使用Xilinx FPGA对AT24C1024的驱动,使用片上逻辑分析仪ChipScope抓取的实际波形,AT24C1024B存储空间为1024K Bit = 131072 Byte,存储单元地址位宽为17位。

AT24C1024B写时序:

AT24C1024B读时序:

SPI和I2C的对比

  • I2C是半双工,SPI是全双工。
  • I2C支持多主多从模式,而SPI只能有一个主机。
  • 从GPIO占用上来看,I2C占用更少的GPIO,更节省资源。
  • I2C有应答响应机制,数据可靠性更高,SPI没有应答机制。
  • I2C速率不会太高,最高速率3.4Mbps,SPI可以达到很高的速率。
  • I2C通过器件地址来选择从机,从机数量的增加不会导致GPIO的增加,而SPI通过CS选择从机,每增加一个从机就要多占用一个GPIO。
  • SPI协议在SCLK边沿进行数据采样,I2C在SCL高电平器件进行数据采样。
  • 两者大多都应用于板内器件短距离通讯。

官方标准文档下载

目前网上比较详细的介绍I2C文档主要有以下3个:

1. I2C官方标准文档_UM10204

I2C的官方文档是原飞利浦(Philips)半导体事业部,现恩智浦(NXP)半导体发布的UM10204文档,全文共64页,是目前最权威最详细的I2C协议介绍文章,最新版本Rev. 6发布于20140404,UM10204_4 April 2014: I2C-bus specification and user manual_Rev.6

2. TI:理解I2C文档_SLVA704

TI在2015年发布了一篇SLVA704文档, 全文共8页,精简的概括了I2C协议的电气特性,操作时序,读写时序等,比较适合I2C入门学习。

3. ZLG:I2C总线规范中文版

这篇文档发布于2000年左右,是对飞利浦官方文档UM10204_v2.1的翻译。

I2C协议文档只是最基础的文档,具体寄存器读写操作等操作,还是要结合所使用芯片的数据手册来使用。

优缺点

总结来说,I2C总线具有以下特点:

  • 只需要SDA、SCL两条总线;
  • 没有严格的波特率要求;
  • 所有组件之间都存在简单的主/从关系,连接到总线的每个设备均可通过唯一地址进行软件寻址;
  • I2C是真正的多主设备总线,可提供仲裁和冲突检测;
  • 传输速度分为四种模式:
  1. 标准模式(Standard Mode):100 Kbps
  2. 快速模式(Fast Mode):400 Kbps
  3. 高速模式(High speed mode):3.4 Mbps
  4. 超快速模式(Ultra fast mode):5 Mbps
  • 最大主设备数:无限制;
  • 最大从机数:理论上是127。

SPI

SPI是一个同步的数据总线,也就是说它是用单独的数据线一个单独的时钟信号来保证 发送端和接收端的完美同步

时钟是一个振荡信号,它告诉接收端在确切的时机对数据线上的信号进行采样。

产生时钟的一侧称为 主机 ,另一侧称为 从机 。总是 只有一个主机 (一般来说可以是 微控制器/MCU ),但是可以有多个 从机 (后面详细介绍);

数据的采集时机可能是时钟信号上升沿 (从低到高)或 下降沿 (从高到低)。

具体要看对SPI的配置;

整体的传输大概可以分为以下几个过程:

  • 主机先将NSS信号拉低,这样保证开始接收数据;
  • 接收端检测到时钟的边沿信号时,它将立即读取数据线上的信号,这样就得到了一位数据(1bit);
    由于时钟是随数据一起发送的,因此指定 数据的传输速度并不重要 ,尽管设备将具有可以运行的最高速度(稍后我们将讨论选择合适的时钟边沿和速度)。
  • 主机发送到从机时:主机产生相应的时钟信号,然后数据一位一位地将从MOSI信号线上进行发送到从机;
  • 主机接收从机数据:如果从机需要将数据发送回主机,则主机将继续生成预定数量的时钟信号,并且从机会将数据通过MISO信号线发送;

具体如下图所示;

注意,SPI是“全双工”(具有单独的发送和接收线路),因此可以在同一时间发送和接收数据,另外SPI的接收硬件可以是一个简单的移位寄存器。这比异步串行通信所需的完整UART要简单得多,并且更加便宜;

SPI特性

SPI总线包括4条逻辑线,定义如下:

  • MISOMaster input slave output 主机输入,从机输出(数据来自从机);
  • MOSIMaster output slave input 主机输出,从机输入(数据来自主机);
  • SCLKSerial Clock 串行时钟信号,由主机产生发送给从机;
  • SSSlave Select 片选信号,由主机发送,以控制与哪个从机通信,通常是低电平有效信号。

其他制造商可能会遵循其他命名规则,但是最终他们指的相同的含义。以下是一些常用术语;

  • MISO也可以是SIMODOUTDOSDOSO(在主机端);
  • MOSI也可以是SOMIDINDISDISI(在主机端);
  • NSS也可以是CECSSSEL;
  • SCLK也可以是SCK;

本文将按照以下命名进行讲解[MISO, MOSI, SCK,NSS]

下图显示了单个主机和单个从机之间的典型SPI连接。

时钟频率

SPI总线上的主机必须在通信开始时候配置并生成相应的时钟信号。在每个SPI时钟周期内,都会发生 全双工数据传输

主机在MOSI线上发送一位数据,从机读取它,而从机在MISO线上发送一位数据,主机读取它。

就算只进行单向的数据传输,也要保持这样的顺序。这就意味着无论接收任何数据,必须实际发送一些东西!在这种情况下,我们称其为虚拟数据;

从理论上讲,只要实际可行,时钟速率就可以是您想要的任何速率,当然这个速率受限于每个系统能提供多大的系统时钟频率,以及最大的SPI传输速率。

时钟极性 CKP/Clock Polarity

除了配置串行时钟速率(频率)外,SPI主设备还需要配置 时钟极性

根据硬件制造商的命名规则不同,时钟极性通常写为CKPCPOL 。时钟极性和相位共同决定读取数据的方式,比如信号上升沿读取数据还是信号下降沿读取数据;

CKP可以配置为1或0。这意味着您可以根据需要将时钟的默认状态(IDLE)设置为高或低。极性反转可以通过简单的逻辑逆变器实现。您必须参考设备的数据手册才能正确设置CKP和CKE。

  • CKP = 0:时钟空闲IDLE为低电平** **0
  • CKP = 1:时钟空闲IDLE为高电平1

时钟相位 CKE /Clock Phase (Edge)

除配置串行时钟速率和极性外,SPI主设备还应配置时钟相位(或边沿)。根据硬件制造商的不同,时钟相位通常写为CKECPHA

顾名思义,时钟相位/边沿,也就是采集数据时是在时钟信号的具体相位或者边沿;

  • CKE = 0:在时钟信号SCK的第一个跳变沿采样;
  • CKE = 1:在时钟信号SCK的第二个跳变沿采样;

时钟配置总结

综上几种情况,下图总结了所有时钟配置组合,并突出显示了实际采样数据的时刻;

其中黑色线为采样数据的时刻;
蓝色线为SCK时钟信号;

具体如下图所示;

SPI ModeCPOLCPHA
0 [00]00
1 [01]01
2 [10]10
3 [11]11

除此之外,我们还应该仔细检查微控制器数据手册中包含的模式表,以确保一切正常。

多从机模式

前面说到SPI总线必须有一个主机,可以有多个从机,那么具体连接到SPI总线的方法有以下两种:

第一种方法:多NSS

  1. 通常,每个从机都需要一条单独的SS线。
  2. 如果要和特定的从机进行通讯,可以将相应的NSS信号线拉低,并保持其他NSS信号线的状态为高电平;如果同时将两个NSS信号线拉低,则可能会出现乱码,因为从机可能都试图在同一条MISO线上传输数据,最终导致接收数据乱码。

具体连接方式如下图所示;

第二种方法:菊花链

在数字通信世界中,在设备信号(总线信号或中断信号)以串行的方式从一 个设备依次传到下一个设备,不断循环直到数据到达目标设备的方式被称为 菊花链

  1. 菊花链的最大缺点是因为是信号串行传输,所以一旦数据链路中的某设备发生故障的时候,它下面优先级较低的设备就不可能得到服务了;
  2. 另一方面,距离主机越远的从机,获得服务的优先级越低,所以需要安排好从机的优先级,并且设置总线检测器,如果某个从机超时,则对该从机进行短路,防止单个从机损坏造成整个链路崩溃的情况;

具体的连接如下图所示;

其中红线加粗为数据的流向;

所以最终的数据流向图可以表示为:

SCK为时钟信号,8clks表示8个边沿信号;
其中D为数据,X为无效数据;

所以不难发现,菊花链模式充分使用了SPI其移位寄存器的功能,整个链充当通信移位寄存器,每个从机在下一个时钟周期将输入数据复制到输出。

优缺点

SPI通讯的优势

使SPI作为串行通信接口脱颖而出的原因很多;

  • 全双工串行通信;
  • 高速数据传输速率。
  • 简单的软件配置;
  • 极其灵活的数据传输,不限于8位,它可以是任意大小的字;
  • 非常简单的硬件结构。从站不需要唯一地址(与I2C不同)。从机使用主机时钟,不需要精密时钟振荡器/晶振(与UART不同)。不需要收发器(与CAN不同)。

SPI的缺点

  • 没有硬件从机应答信号(主机可能在不知情的情况下无处发送);
  • 通常仅支持一个主设备;
  • 需要更多的引脚(与I2C不同);
  • 没有定义硬件级别的错误检查协议;
  • 与RS-232和CAN总线相比,只能支持非常短的距离;

UART

1.1 早期的串行通讯设备

早期的电报机器使用长度可变的脉冲信号进行数据传输,比如摩斯电码;

摩斯电码

后来电传打印机(teleprinters )普遍使用5、6、7或8个数据位来表示各种字符编码,最终成为计算机外围设备。电传打字机(** teletypewriter 简称 **tty)成为小型计算机十分出色的通用I/O设备。

由于历史的发展原因,早期在Unix终端是一个名字为ASR33的电传打字机,而电传打字机的英文单词为Teletype(或Teletypewritter),缩写为tty。因此,终端设备也被称为tty设备。这就是TTY这个名称的来源。

1.2 早期的芯片级UART

DEC(Digital Equipment Corporation)公司的Gordon Bell 为该公司的PDP系列计算机设计了第一个UART,不过体积庞大,UART的线路占据了整个电路板;

后来DEC将串行线路单元的设计浓缩为早期的 UART单芯片 ,以方便自己使用。

DEC公司Logo

DEC是美国一家计算机公司;

西部数据(Western Digital)公司在1971年左右将其开发为第一个广泛可用的UART单芯片** **WD1402A。这是中型集成电路的早期产品。

Western Digital是美国计算机硬盘驱动器制造商和数据存储公司。

1.3 现代UART的发展

2000年代开始,大多数IBM或者相关的计算机都删除了其外部RS232的COM端口,将其替换为带宽性能更加出色的USB端口;

早期带RS232的PC

对于仍然需要RS-232串行COM端口的用户,现在通常使用外部USB转UART转换器,常见的有CH340,Silicon Labs 210x的驱动程序,现在很多处理器和芯片都内置了UART。

2 预备知识

通用异步收发传输器Universal Asynchronous Receiver/Transmitter,通常称为 UART ),在UART通信中,两个UART直接通信。

发送端的UART将来自控制设备(如 CPU )的并行数据转换为 串行数据 ,以串行方式将其发送到接收端的UART,然后由接收端的UART将串行数据转换为并行数据以用于接收设备的正常处理。

这里只需要两条线RX/TX即可在两个UART之间传输数据 。具体如下图所示;

3 协议层

UART传输的数据被封装成数据包。每个数据包包含1个起始位,5~9个数据位(取决于UART的具体设置),一个可选的奇偶校验位以及1个或2个停止位,具体如下图所示;

在这里插入图片描述

起始位

UART数据传输线通常在不传输数据时 保持在高电平

为了 开始数据传输 ,发送端UART在一个时钟周期内将传输线从 高电平拉低到低电平

当接收端UART检测到高电压到低电压转换时,它开始以波特率的频率读取数据位中的每一位数据。

数据

数据位包含正在传输的 实际数据 。如果使用奇偶校验位,则可以是5位,最多8位。如果不使用奇偶校验位,则数据帧的长度可以为9位。

在大多数情况下,数据首先以低有效位发送。

校验位

在串口通信中一种简单的检错方式。

有四种检错方式: 偶校验奇校验高校验低校验 。当然没有校验位也是可以的。

对于偶和奇校验的情况,串口会设置校验位(数据位后面的一位),用一个值确保传输的数据有偶个或者奇个逻辑高位。

举个例子,如果数据是011,则满足;

偶校验 ,校验位为0,保证逻辑高的位数是偶数个。

奇校验 ,校验位为1,这样就有3个逻辑高位。

具体如下图所示;

高位和低位不是真正的检查数据,而是强行将校验位设置为逻辑高或者逻辑低。这样使得接收设备能够知道一个位的状态,有机会判断是否有噪声干扰了通信或者是否传输和接收数据是否不同步。

停止位

发送端UART将数据传输线从低电压驱动到高电压至少持续两位数据的时间宽度来表示整个数据包的传输已经结束。

由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。适用于 停止位的位数越多 ,不同时钟同步的 容错性越好 ,但是 数据传输率同时也越慢

波特率

波特率是串口数据的传输速度,即Bit/s,常见的波特率有:9600,19200,38400,57600,115200,当然还有很多波特率,不再一一给出;

假设目前UART的配置为,1个起始位,8个数据位,0个校验位,1个停止位,那么9600的波特率,可以计算出每一位数据的时间宽度为:

Td=19600∗1000=104us

那么传输一个字节(也就是10 bit 数据)需要的时间为 1.04 毫秒。

下面用串口抓取了UART的TX上的信号,其中一位数据的时间宽度为26微秒,具体如下图所示;

则可以简单计算得到;

126us=38461

因此波特率大概为 38400;

下表是各个波特率下数据位时间宽度;

TimeBaud Rate
3333µs (3.3ms)300
833µs1200
416µs2400
208µs4800
104µs9600
69µs14400
52µs19200
34µs28800
26µs38400
17.3µs57600
8µs115200
4.34µs230400

4 传输过程

发送端UART从数据总线转换并行数据:

发送端UART将 起始位奇偶校验位停止位添加到数据包中:

整个数据包从发送端UART串行发送到接收端UART;接收端UART按照预先配置好的波特率对数据线进行采样:

接收端UART解析接收的数据,丢弃数据包中的起始位,奇偶校验位和停止位:

接收UART将串行数据转换回并行数据,并将其传输到接收端的数据总线:

5 物理层

UART、RS232、RS485在串口通信中,主要区别是电平的不同,其中UART通常使用TTL电平,下面介绍这几个存在的差异;

TTL

TTL全名是晶体管-晶体管逻辑集成电路(Transistor-Transistor Logic)

  • 输入高电平最小2V,输出高电平最小2.4V,典型值3.4V;
  • 输入低电平最大0.8V,输出低电平最大0.4V,典型值0.2V。

RS232

RS232 逻辑1电平(MARK)=-3V~-15V,逻辑0电平(SPACE)=+3~+15V;

同样的,对于传输数据0x55,即二进制的01010101,RS232和TTL的区别如下;

RS485

RS485是差分信号进行串行传输;

  • 逻辑1以两线间的电压差为+(2~6)V表示;
  • 逻辑"0"以两线间的电压差为-(2~6)V表示;

在工业通信中,使用RS485比较多,因为RS485是差分信号,可以抑制共模干扰,因此在恶劣的环境中拥有很好的抗干扰性,比较稳定;

6 优缺点

没有任何通信协议是完美的,以下是UART的一些利弊,可帮助您确定它们是否适合您的项目需求:

优点

  • 通信只需要两条数据线;
  • 无需时钟信号;
  • 有奇偶校验位,方便通信的差错检查;
  • 只需要接收端和发送端设置好数据包结构,即可稳定通信;

缺点

  • 数据帧最大支持9位数据;
  • 不支持多主机或多从机的主从系统;

标题:[ MCU ] 单片机通讯协议介绍!
作者:llilei
地址:http://solo.llilei.work/articles/2023/02/28/1677588005196.html