上一篇已经介绍了 RS-232 串口的理论基础,本文开始讲解串口的应用实例。

Linux 上的 tty

在 Bash 环境中执行 ls /dev 命令可以看到很多 tty 开头的文件名,这些文件是干什么的呢?

tty 是 Linux 给用户提供的一个常驻小程序,用于接收用户的标准输入,返回操作系统的标准输出。

Linux 将每个设备都当成一个文件来对待,举例来说,硬盘 IDE 接口的硬盘的文件名即为 /dev/sd[a-d],同样的串口就是 /dev/ttyS[0-n],分别对应于 DOS 系统下的 COM1、COM2 等。

在 Linux 系统中,串口设备是通过串口终端设备文件来访问的,也就是通过访问 /dev/ttyS0、/dev/ttyS1、/dev/ttyS2、/dev/ttyS3 这些设备文件实现对串口的访问,若要向一个端口发送数据,只需要在命令行上把标准输出重定向到这些特别文档名上即可。

例如, 在 Bash 下键入:echo test >/dev/ttyS1 会把单词「test」发送到连接在 ttyS1 ( COM2 ) 端口的设备上,可以连接串口来实验。

Android 的串口通信

大家都知道,Android 系统是基于 Linux 内核的,串口通信的方式也是共通的,基本原理仍然是将输入流重定向到 /dev/ttyS[0-n] 文件中。

OK,道理都懂,但是脱离了 Bash 环境,我们怎么用代码实现 Android 串口通信呢?

Google 在 Google Code 上提供了一个叫做 android-serialport-api (https://code.google.com/archive/p/android-serialport-api/ ) 的项目,供开发人员用 Java 代码来实现串口操作,该项目本质上是用 JNI ( Java Native Interface ) 技术调用写好的 C 函数库,由 C 语言代码实现与底层操作系统的通信。但是该项目年代较为久远,且示例程序源码是 eclipse 工程,感兴趣的读者可以到 Github 上找一下前人基于此项目重新组织实现的 AndroidStudio 工程来观摩学习。

串口的应用场景

对于多数非嵌入式程序猿来说,用到串口的可能能行不大,但是串口的应用已经融入我们的生活中,只是我们没有留意而已。

工控机通过串口配合 PLC(可编程控制器件)是工控领域的黄金搭档。

ATM 机、自动售货机内部都用到了串口通信与 PLC 的配合。 多数传感器如温湿度传感器等嵌入式设备的首选通讯方式也是串口。

如果掌握了串口通信技术,你甚至可以利用实验室的串口传感器自己搭建一套简易的智能家居系统,学会了串口通信真的可以为所欲为!

串口调试实战

2 - 3 短接

要进行串口调试,首先要确认的一点就是该设备提供的串口是否能用,就如 PC 机上若主板本身的 USB 接口坏掉了,在这个接口上插上 U盘将毫无意义。

回顾一下上一篇「理论篇」讲到的 DB9 各个脚位的作用,其中 Pin 2 代表接收,Pin 3 代表发送,若我们用导线将 Pin 2、Pin 3 连接起来,当此串口往外发送数据时,数据由 Pin 3 引脚出来,由于将 Pin 2 和 Pin 3 短接,数据会延由导线进入此串口的 Pin 2 脚位,这就实现了该串口的自发自收,可以通过检查自发自收是否成功来验证该串口是否异常。

等一等,上一篇讲到 DB9 有 9 个脚位,为什么此处只用到了两个引脚就能实现通信?

实际上要实现最简单的串口通信仅需3个引脚就够了,分别是:Pin 2、Pin 3 和 GND,分别用于收发信息和平衡电荷,目前市面上的 RS-232 设备多数也只用到了这三个引脚。

公母交叉

串口线分直通和交叉,直通一般用于延长 PC 与设备,将 Pin 2、Pin 3、Pin 5 分别连接 Pin 2、Pin 3、Pin 5,因为 PC 上一般为公头,而设备上多为母头,所以正好它们是通用的,既可用于延长也可用于连接;交叉一般用于 PC 与 PC 对接,将 Pin 2 对 Pin 3、Pin 3对 Pin 2、Pin 5对 Pin 5,一般两头都是母头。

若我们将一个公头与一根交叉线连接起来,此时要注意串口的引脚已经被改变了,交叉线的一排左数第二位置不再对应 RXD 而是变为了 TXD,若要改变回原状可再接一根交叉线。

粘包拆包

我们将串口通信的数据流类比作河流的流水,是连成一片的,中间并没有分隔界限。

举个例子,假设 PC 机(上位机)要通过串口向某传感器设备(下位机)发送两条消息,第一条是「 Hello 」;第二条是「 Serial Port 」。

理想情况下下位机应该收到两条消息分别解析为「 Hello 」和「 Serial Port 」,但是串口数据流是没有分隔界限的。

  • 倘若两次通信的时间间隔较短,下位机可能只会收到一条消息「 Hello Serial Port 」,这就是粘包。

  • 下位机也有可能会收到两条消息但是读取的时候分别识别为「 Hello Ser 」和 「 ial Port 」,这就是拆包。

因为串口数据流底层并不了解上层业务数据的具体含义,这就涉及到两个设备在进行串口通信时如何进行数据截断的问题,粘包拆包问题只能通过上层的应用协议栈设计来解决。

粘包和拆包不仅出现在串口通信中,而是一类问题。TCP 通信同样需要处理战报和拆包,对此,业界已经形成了几种主流的解决方案,这不是本文的重点,将在后续讲解网络编程的时候进行详细介绍。

文末福利

实际进行串口调试时,为了调试方便,善于利用工具的程序猿们开发出一种叫做「串口调试助手」的工具,配合交叉线大大方便了开发调试过程,笔者对比多个调试工具,最终决定将一款界面友好,操作简单的调试工具分享给大家,这也是笔者一直在用的一款,非常感谢这款调试助手的作者。

-c

在「Geek笔记」微信公众号留言框回复「串口助手」或长按识别下方二维码即可获取下载链接!

-c