嵌入式设备在电路中交换信息的时候必须通过共享一个通用的协议。现在嵌入式系统中已经定义了数百种通信协议来实现数据交换,一般来说可以将其分为两类:并行或串行。
并行传输数据是指同时传输多个数据位,它们通常需要数据线和时钟线配合工作,数据线的条数可能为8、16或更多。
而串行传输时一次只能传输一位数据,只使用一根导线工作,通常总共不需要超过四根。
可以将这两种通信方式看作车辆在路上行驶,并行传输是一条八车道的豪华高速公路,而串行传输更像是两车道的乡间小路。并行传输可以在同一时刻通过8辆汽车,而串行传输只能在同一时刻通过一辆汽车,但两车道的建设费用可能更低。
并行传输的好处是快速、简单且易于实施。但是它需要更多的输入/输出(I/O)口。如果你曾经使用过Arduino编程,那你就知道处理器上的I/O口有多宝贵了。因此我们经常选择串行通信,以节约端口。
多年来,研究人员设计了数十种串行协议以满足嵌入式系统的特殊需求,USB和以太网算是其中比较知名的串行协议。其他常见的串行协议包括:IIC、SP等等。
这些串行传输协议都可以分为两类:同步和异步。
同步串行传输协议始终将数据线与时钟信号配对,因此同步串行总线上所有设备都共享一个公共时钟。这样可以进行更直接、更快的串行传输,但也额外需要一根时钟线。同步串行传输协议的包括SPI和IIC。
异步串口是指在没有外部时钟信号的情况下传输数据。这种传输方法非常适合于I/O口紧张的情况,但这意味着需要付出额外的资源来可靠地传输和接收数据。我们将在本文中讨论的串行协议是异步传输的最常见形式。实际上,大多时候人们说的串口均是指的该类型。
异步串行协议的许多内置规则可以确保可靠且无误的数据传输,分别为:
数据位
同步位
奇偶校验位
波特率
通过各种这些信令机制,可以保障数据传输的完整性,但最最最重要的是在收发双方一定要配置位相同的规则才能正确的发送和接收。
波特率指定通过串行线发送数据的速度。通常以每秒位数(bps)为单位。如果反转波特率,则可以计算出传输单个比特需要的时长。该值确定发送器将串行线保持为高/低状态的时间,或接收设备在多长时间内对其进行采样。
在合理范围内,波特率几乎可以是任何值。唯一的要求是两个设备均以相同的速率运行。对速度要求不高的情况而言,9600 bps是较常见的波特率之一。其他“标准”波特为1200、2400、4800、19200、38400、57600和115200。
波特率越高,发送/接收数据的速度就越快。通常不会有超过115200的波特率-因为这对于大多数单片机而言速度太快,将在接收端看到错误,因为时钟和采样周期无法跟上发送端。
实际传输的每个数据块(一般为一个字节)都以数据包或帧的形式发送。通过将同步位和奇偶校验位附加到我们的数据中来创建帧。
9600 8N1(示例)
9600 8N1代表着波特为9600,8个数据位,无奇偶校验和1个停止位,这一种是较为常用的串行协议配置方法。那么,9600 8N1的数据包是什么样的呢?举个例子吧!传输ASCII字符"O"和"K"的设备必须创建两个数据包。O的ASCII值(大写)为79,则二进制值01001111,而K的二进制值为01001011。剩下的就是追加同步位。假设传输数据时首先传输最低位:
由于我们以9600 bps的速度进行传输,因此将电平保持高位或低位所花费的时间为每位1/(9600 bps)或104 µs。
对于每个传输的数据字节,实际上有10个位被发送:一个起始位,8个数据位和一个停止位。因此,在9600 bps时,我们实际上每秒发送9600位或每秒960(9600/10)字节。
接线和硬件
串行总线仅由两根电线组成-一根用于发送数据,另一根用于接收。因此,串行设备应具有两个串行引脚:接收器RX和发送器TX。
请注意,RX和TX口是相对于设备本身的。因此,来自一台设备的RX应该接到另一台设备的TX,反之亦然。发射机应与接收机通信,而不是与其他发射机通信。
两个设备都可以发送和接收数据的串行接口是全双工或半双工。全双工意味着两个设备可以同时发送和接收。半双工通信意味着串行设备必须轮流发送和接收。
常见问题
任何水平的工程师都容易犯以下错误:
1. 接收到发送,接收到发送
这种情况看起来特别简单,但是非常容易遇到,我已经犯了无数次,请始终确保在串行设备之间交叉RX和TX线。
波特率不匹配
波特率类似于串行通信的语言。如果两个设备的通话速度不同,则数据可能会被误解或完全丢失。如果接收设备在其接收线路上看到的都是垃圾,请检查以确保波特率匹配。
数据以9600 bps传输,但以19200 bps接收。波特率不匹配==垃圾。
总线争用
串行通信旨在仅允许两个设备通过一条串行总线进行通信。如果有多个设备尝试在同一串行线上进行传输,则可能会发生总线争用。等等等...
例如,如果您要将GPS模块连接到Arduino,则可以仅将模块的TX线连接到Arduino的RX线。但是,该Arduino RX引脚已经连接至USB到串行转换器的TX引脚,该端口在您对Arduino进行编程或使用Serial Monitor时就可以使用。这设置了GPS模块和FTDI芯片都试图同时在同一条线上传输的潜在情况。
试图在同一条线上同时传输数据的两个设备很糟糕!在"最佳"状态下,两个设备都无法发送其数据。最坏的情况是,两个设备的传输线都会go声(尽管这种情况很少见,而且通常会受到保护)。
将多个接收设备连接到单个发送设备可以很安全。并非真正符合规格,并且可能不适合经过严格训练的工程师,但是它会起作用。例如,如果要将串行LCD连接到Arduino,最简单的方法可能是将LCD模块的RX线连接到Arduino的TX线。Arduino的TX已经连接到USB编程器的RX线,但是仍然只剩下一个设备来控制传输线。
从固件的角度来看,这样分配TX线仍然很危险,因为您无法选择哪个设备可以听到什么传输信号。LCD最终会接收到不适合它的数据,这可能会命令LCD进入未知状态。
一般来说:一条串行总线,两个串行设备!
本文转载引用:
https://learn.sparkfun.com/tutorials/serial-communication