安卓与串口通信-基础篇

news2025/1/18 11:45:47

前言

安卓并不仅仅只是一个手机操作系统,在很多领域都能见到安卓的身影。

无论是车载系统、工控系统、屏控系统还是物联网设备基本都有安卓的一席之地。

在所谓的寒冬之下,纯粹的安卓开发似乎已经不再吃香,于是越来越多的安卓开发者转向了车载、工控等领域。

而在这些领域,绕不开串口通信相关知识,无论是车载系统与车身各个传感器或者 ECU 通信还是工控系统与 PLC 交互,都离不开串口。

说来惭愧,虽然我勉强算是一个做安卓工控的吧,但是实际上干的活却是调轮子,调参数,对于其中的基本原理一直是一知半解的。

正好最近有空,我决定先从串口通信学起,慢慢夯实我的基础知识。

在学习过程中也会把自己学到的东西结合自己工作中积累的为数不多的经验分享出来。

因为对这方面其实我也不甚了解,所以难免会有纰漏,如有错误还望各位大佬指正。

本文中的部分图表来自于文末标注的参考资料

串口基础知识

串行与并行

如果我们想让两台设备(单片机、电脑等)相互通信,一般可以有两种方式:串行与并行。

例如我们想从设备A中发送一条 8 bit 的数据到设备 B。

如果是串行的方式则会从第1位到第8位依次排队从一根线(注意,这里的一根线不是物理意义上的一根线,可以理解成一根完整的数据线)上发送过去。

如果使用并行的方式,则可能设备A和设备B之间有8条线相连接,发送时这 8 bit 数据会同时从8根线上发送到设备B。

直接说可能不太好理解,但是看这张图就能秒懂:

serial_parallel

从上面的图也不难看出,并行传输相比于串行传输速度会更快,但是相应的线路成本也更高,而且抗干扰能力也没有串行强,所以并行的通信距离没有串行的距离长。

同时,由于串行协议的外设简单,成本低通信距离远,所以我们在单片机或者说工控设备之间通常使用的都是串行传输。

而串行传输又可以分为同步串行和异步串行。

同步串行与异步串行

同步串行指的是通信双方的时钟频率保持一致,接收方时刻准备接收数据,并且只需要在接受到开始传输的信号后即可连续传输数据,数据之间没有间隙,不需要起始位和结束位,传输效率高,可以进行一对多通信。常用的同步串行有 I2C 和 SPI。

而异步串行指的是双方时钟频率不一致,传输数据时采用帧格式传输,发送方发送每一帧数据时需要附加起始位和结束位,接收方通过读取起始位和结束位来实现与发送方的信息同步,传输效率低,只能1对1通信。通常一帧数据由起始位、数据位、校验位、停止位组成。常用的异步串行有 UART ,即我们俗称的串口通信。

串口通信(UART)

为了实现串口通信,我们需要在设备之间连接三条线:TX(发送)、RX(接收)、GND(接地)。

分别将设备A的TX和设备B的RX相连;设备A的RX和设备B的TX相连;设备A、B的GND相连。

由于每个设备之间都同时有发送和接收端,所以串口通信是全双工通信,即支持同时发送和接收数据。

假如我们想要由设备A向设备B发送一个字符 “E”,则发送效果如图:

1

即通过设备A的发送端(TX)向设备B的接收端(RX)发送一段数据。

此时如果测量发送数据时的这条线上的电平,将得到这么一个波形图:

2

此即二进制的 “01000101” 换算成十进制则为 69 ,在 ASCII 中表示字母 “E” :

3

而这里电平中读到的 0 和 1 是怎么定义呢?一般来说我们会定义高电平为1,低电平为0,具体怎么定义下面会讲,现在先按下不表。

事实上,这里的波形图并不完整,还记得我们上面介绍异步串行时说过的吗?它是采用帧传输的方式来传输数据的。也就是说,一个完整的数据帧至少还应该包含前面的起始位(1位低电平)和最后的结束位(1-2位高电平):

4

另外,一帧数据中数据位可选5-8位,一般来说使用的是 8 位;在数据位之后结束位之前还可以有一个校验位用于校验数据传输是否正确(奇偶校验、CRC校验等),当空闲时数据线输出高电平,称为空闲位:

5

那么问题来了,接收端怎么知道使用的数据位是多少位、是否使用校验、结束位有几位?

答案是不知道,也无法知道。

所以通常在串口通信开始之前,传输双方需要约定好使用的 数据位、校验位、停止位。

一般使用时都是 8位数据位、无校验、1位停止位,即俗称的 “8N1”。

除了上面说的三个参数外,在开始通信前还需要约定一个参数,那就是“波特率”。

波特率即每秒传输多少个bit的数据,单位为 bps(bits per second)。

回到我们上面说的传输字母 “E” 的图上,虽然从图中可以很直观的看出电平的变化,但是,接收方应该怎么知道“多长一段”是一个 bit 呢?这就需要用到我们的波特率了。

例如我们上面设置的波特率是 9600 bps,则表示每秒发送 9600 bit,即一个 bit 宽度为 104 微秒。

此时接收方在读取到起始位后,会开始每间隔104微秒读取一次数据,直至读取到结束位。

(事实上,在读取到起始位后通常还会延迟 52 微秒才会开始读取,此后每隔 104 微秒读取一次,这是为了避免开始读取时数据不稳定)

自此,串口通信的基本原理就全部讲完了。

是不是觉得少了点什么呢?

对的,上面还留了一个问题,就是我们怎么去界定高电平和低电平呢?

这就引出了我们的下一个主角 RS232 。

RS232

一般来说,串口通信使用的是 TTL 电平。

TTL 即 Transistor-transistor logic ,晶体管逻辑,其电路由双极晶体管构成,工作电压为 5V。所以我们一般将 +5V 电压认为是高电平(1),0V认为是低电平(0)。但是,TTL电路输出的高电平最小为 2.4V、低电平最大为0.4V,这就导致高低电平之间的差值最小可能只有2V,所以其传输数据时极易受到干扰,例如此时受到静电干扰,可能就会把低电平变为了高电平。所以此种传输方式的距离非常短,一般在1米以内,只适用于芯片和芯片之间或设备与电脑之间的数据传输。

为了改善这些缺点,美国电子工业联盟制定了一个标准:RS232 。

RS232改善的方法非常简单,就是将电平提高。

为了提高传输的电平,我们只需要在原本的串口传输设备之间增加一个电平转换芯片即可。

此时,如果发送设备发送一个 5V 的高电平给转换芯片,会被提高到 -15V 后发送给接收设备;反之,如果这个芯片接收到 -15V 的高电平,又会将其转换为 5V 发送给设备。

这就完成了将 TTL 电平转换为 RS232 电平的操作。

6

在 RS232 中,高电平(1)为 -3V至-15V;低电平(0)为 +3V至+15V。

7

RS232 只是改变了电平大小,使得高低电平之间相差了将近 20V ,这样一来就让 RS232 的抗干扰能力大大增强,传输距离也达到了理论 15 米,同时传输数据格式也没有改变。但是这也导致 RS232 的最大波特率只能使用 19200 bps,使得传输速率有限,且抗共模干扰能力依旧没有改善。

所以,又诞生了 RS485 标准。

RS485

与 RS232 相同的是,RS485也是通过在原本的串口通讯基础上添加了电平转换芯片来实现。

8

不同的是, RS485 不再采用固定的电平高低判断方式,而是使用差分信号来表示数据。

RS485 接线只需要两根线A与B。当A与B之间的电压差在2V到6V之间时表示逻辑1;差值在-6V到-2V之间时表示逻辑0 。

同时 RS485 通常采用双绞线的形式接线,这就使得它的抗共模干扰能力大大增强,因为当受到干扰时 A和B的电压都会改变,此时他们的电压差值就基本不会受到影响。

9

由于 RS485 使用差分信号的特点,使得它的可传输信号最低能达到 200mV、数据最高传输率能达到 10Mbps、传输距离可以达到1200米。

不过由于 RS485 只使用了两根线,且两根线都用于传输同一个数据的特性,使得它只支持半双工通信,即同一时间只能发送或接收数据,不能同时发送与接收数据;但是也因为这个特点,使得 RS485 不同于 RS232 只能两个设备点对点通信,而是可以一对多通信,即一个主机可以同时与多个从机通信。

10

总结

自此我们已经对串口通信有了一个基本的认识。

从上文中我们可以发现,UART定义了数据传输格式标准,RS232和RS485定义物理层面的数据传输方式与接线方式:

11

也就是说,无论是串口通信还是 RS232 还是 RS485,其实它们的数据格式与内容都是一样的。

对于我们安卓开发人员来说,无论使用什么标准几乎都对我们没有影响,我们需要做的只是解析好通过串口传输过来的数据即可。

如何进行测试

讲解完了上述的串口通信原理,那么我们应该怎么测试呢?

最好的方式当然是有一个实机能够测试,但是有时候我们手头暂时没有设备或者不方便使用真实设备进行测试,此时我们就可以使用虚拟串口进行模拟测试。

概述

在 Windows 上进行模拟测试相对于 MAC 上简单的多。

大致流程为:使用软件创建虚拟串口-启动安卓模拟器并与创建的虚拟串口连接-完成安卓与虚拟串口的通讯。

由于我目前主力机使用的是 MAC ,所以我尝试按照上述步骤在 MAC 上进行模拟测试。

但是却卡死在了第一步,即创建虚拟串口。

我尝试查找了一番,发现在 MAC 上并没有可用的虚拟串口软件,好不容易找到一款,却已经停止维护,因为新版本的 MAC 权限收紧,无法再创建虚拟串口。

好在,我手头还有两块 ESP32 的开发版,所以其实不使用虚拟串口模拟也行,我可以直接使用 ESP32 开发版进行测试。

那么,现在问题又来到了第二个步骤。

但是经过我的尝试,MAC 始终无法在启动安卓模拟器与串口设备连接。

不过虽然无法使用,但是过程中踩了一些坑,也找到了解决方案,所以这里还是大致讲一下。

MAC 启动模拟器与串口连接

首先,我们需要创建好安卓模拟器,这一步直接在 Android Studio 中按照常规方式创建就可以了

创建好模拟器后,我们不能直接在 Android Studio 中启动,而是必须在终端中启动,因为我们需要指定启动参数。

启动需要执行 emulator 命令,这个命令的可执行为文件在 AndroidSdk/tools 中,例如我的路径是 /Users/equationl/Library/Android/sdk/tools 。如果你不知道你的 AndroidSdk 目录在哪儿,你可以直接在 Android Studio 的设置中搜索 “sdk” 后,在 “Android SDK Location” 选项中看到这个路径:

sdk_location

找到你的路径后执行以下命令即可启动模拟器:

cd /Users/equationl/Library/Android/sdk/tools

./emulator -avd Pixel_6_Pro_API_31

其中的 “Pixel_6_Pro_API_31” 就是你之前创建的模拟器的名称。

当然,这里只是单纯的启动了模拟器,并没有连接到串口,所以此时你启动的模拟器是找不到你插入设备的串口的。

如果我们需要连接串口,则需要执行:

./emulator -avd Pixel_6_Pro_API_31 -qemu -serial /dev/tty.wchusbserial544C0047221

其中的 /dev/tty.wchusbserial544C0047221 即为你的串口路径。

在 MAC 上查看可用串口的命令为:

ls /dev/tty.*

然而,如果你的 MAC 是 ARM CPU的话,大概率启动模拟器时会报错:

launcher_emulator_fail

这应该是谷歌的一个小 BUG,从错误信息也能看出,错误的原因是不存在 darwin-x86_64/qemu-system-aarch64 这个文件。

我们来到报错的路径,可以看到,压根没有叫 darwin-x86_64 的文件夹,但是有一个叫 darwin-aarch64 的文件夹,里面就有 qemu-system-aarch64 文件。

哈哈哈,其实到这里估计已经有人反应过来了,我们明明是 ARM 的处理器,怎么会有 x86 文件夹嘛。

所以我们直接把 darwin-aarch64 软连接到 darwin-x86_64 就行了。

执行命令:

cd /Users/equationl/Library/Android/sdk/emulator/qemu

ln -s darwin-aarch64 darwin-x86_64

然后再返回 tools 目录,执行启动模拟器的命令,可以看到,启动成功了。

但是,连接串口失败,并报错:

serial_error

可以看到,有两个错误,一个是无法识别 serial 命令;另一个是无法连接到我们指定的串口。

关于这个错误,我也是搜索了好久,也尝试了各种方法,但是都无法解决。

不过我发现另外一种实现方法,那就是使用单独的虚拟机开启一个安卓的模拟器,然后由这个虚拟机创建一个虚拟串口给安卓模拟器使用,并将这个虚拟串口连接至物理设备。

啊这?搁这套娃呢?太麻烦了!果断放弃!

感兴趣的可以去尝试一下,教程地址:【Android】mac下Android的串口及NDK调试探索

总结

因为上面的原因,最终我选择的测试方案是 使用安卓真机+ESP32开发版进行测试。

对于同样是使用 MAC 的用户,我的建议是直接使用真机+ESP32开发版,或者其他更便宜的开发版进行测试学习,毕竟一块开发版也就十几块钱,真没必要为了省这十几块钱而去折腾这个神坑的无底洞。

而对于 Windows 用户就方便多了,不仅可以使用和 MAC 一样的真机测试方案,还可以很方便的使用虚拟串口以及安卓模拟器进行测试。

总结

我们今天主要讲解了串口的一些基本知识,并且大概介绍了应该怎么去测试串口通信。

所有知识点都是循序渐进的,设备间的通信有串行通信和并行通信,一般我们在实际中使用的是串行比较多,而串行分为同步串行与异步串行,常用的是异步串行,异步串行常用协议是 UART 即常说的串口,为了解决串口通信的问题,又衍生出了 RS232、RS485等协议。

参考资料

  1. How can I launch Android Emulator without android studio on Mac M1
  2. 5分钟看懂!串口RS232 RS485最本质的区别!
  3. 串行通信接口之RS-232、RS-485与RS-422
  4. 3分钟理解通信协议之串口UART到底是个啥?
  5. 超简单的一种通信,2分钟搞懂,串口通讯的工作原理!
  6. UART协议详解
  7. UART接口的基础知识详解
  8. 串口通信(UART)介绍
  9. 什么是串口通讯?
  10. 串口通讯详解
  11. 串口通讯详解

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/550411.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

浅谈新兴室内外无线局域精准定位技术UWB(超宽带)

浅谈新兴室内外无线局域精准定位技术UWB(超宽带) 1、UWB高精度定位系统概述2、与传统定位比较3、应用场景4、实现uwb高精度定位4、UWB室内定位的缺陷5、应用案例 1、UWB高精度定位系统概述 UWB室内定位技术是一种全新的、与传统通信技术有极大差异的通信…

【MySQL学习】事务管理

文章目录 一、事务的基本认识1.1 事务的基本概念1.2 事务的基本属性1.3 支持事务的存储引擎 二、为什么要有事务三、事务的基本操作3.1 事务的提交方式3.2 事务的操作案例 四、事务的隔离级别4.1 对事务隔离性的初步理解4.2 四种隔离级别4.3 读未提交(Read Uncommit…

Mybatis Plus代码生成器

文章目录 1 代码生成器原理分析2 代码生成器实现步骤1:创建一个Maven项目代码2:导入对应的jar包步骤3:编写引导类步骤4:创建代码生成类步骤5:运行程序 3 MP中Service的CRUD 1 代码生成器原理分析 造句: 我们可以往空白内容进行填词造句,比如: 在比如: 观察我们之…

FAT NTFS Ext3文件系统有什么区别

10 年前 FAT 文件系统还是常见的格式,而现在 Windows 上主要是 NTFS,Linux 上主要是Ext3、Ext4 文件系统。关于这块知识,一般资料只会从支持的磁盘大小、数据保护、文件名等各种维度帮你比较,但是最本质的内容却被一笔带过。它们最…

SQL教程(四)简单实例学习:时间函数(一)基础入门级

目录 一、🌎SQL 简介 1.1 📜SQL 是什么? 1.2 📜SQL 能做什么? 1.3 📜SQL 是一种标准 - 但是... 1.4 📜在您的网站中使用 SQL 1.4 📜RDBMS 1.5 📜请记住... 1.6 &…

物业管理可视化大屏

物业管理可视化大屏是一种可视化的智能物业管理,它可以将物业管理中的各种数据进行可视化展示,帮助物业管理人员更好地管理社区或园区。 什么是物业可视化数据大屏? 物业可视化数据大屏就是利用大数据技术,将物业管理中的各种信…

1091 Acute Stroke

One important factor to identify acute stroke (急性脑卒中) is the volume of the stroke core. Given the results of image analysis in which the core regions are identified in each MRI slice, your job is to calculate the volume of the stroke core. Input Spec…

C++中的取余函数%、remainder、fmod以及matlab中的取余函数mod

C 1 整数取余 % 2 remainder函数 https://cplusplus.com/reference/cmath/remainder/?kwremainder double remainder (double numer , double denom); float remainder (float numer , float denom); long double remainder (long double numer, long double denom); doub…

一文带你了解MySQL之单表访问方法

前言 本文章收录在MySQL性能优化原理实战专栏,点击此处查看更多优质内容。 本文摘录自 ▪ 小孩子4919《MySQL是怎样运行的:从根儿上理解MySQL》 对于我们这些MySQL的使用者来说,MySQL其实就是一个软件,平时用的最多的就是查询功…

Grow模型

Grow模型 该模型是约翰.惠特默,在1992年其著作《高绩效教练》一书中提出的,核心是围绕设定目标和寻找解决方案的有效工具。 模型介绍 GROW模型给到应用者一个可以高效的设立目标并制定计划,最终解决问题的思路框架。 GROW 由四个步骤构成&am…

老胡的周刊(第091期)

老胡的信息周刊[1],记录这周我看到的有价值的信息,主要针对计算机领域,内容主题极大程度被我个人喜好主导。这个项目核心目的在于记录让自己有印象的信息做一个留存以及共享。 🎯 项目 omnivore[2] 无干扰、注重隐私、免费开源专为…

【P26】JMeter WebSocket Sampler

文章目录 一、WebSocket Sampler 安装说明二、WebSocket Sampler 参数说明三、测试计划设计 一、WebSocket Sampler 安装说明 下载路径:https://jmeter-plugins.org/install/Install/ (1)、打开网页,点击 plugins-manager.jar 进…

​C++中虚函数 纯虚函数 虚基类的基础知识点​

一、前言 原文转载自 c中的 虚函数 纯虚函数 虚基类_名字全都被占用了的博客-CSDN博客,为了理解下C中虚函数 纯虚函数 虚基类的基础知识点。 二、虚函数 纯虚函数 虚基类三者区别 1.虚函数是用于多态中virtual修饰父类函数,确保父类指针调用子类对…

Maven基础学习---4、Maven的使用(IDEA)

1、创建父工程(本人用的是IDEA2022.3) 1、创建Project 2、配置Maven信息 如果没有提前设置过Setting for new project这个配置,那么每次创建Project后都需要设置Maven家目录位置,否则IDEA将使用内置的Maven核心程序(…

数据仓库理论

数据仓库理论 基础理论数据仓库主要特征面相主题集成性非易失性、非易变性时变性 OLTP、OLAPOLTPOLAP对比 数据库与数据仓库的区别数据仓库、数据集市数据仓库分层架构分层思想和标准阿里巴巴数仓三层架构ODS层DW层DA层(ADS层) 分层的好处好处 ETL和ELT的…

mysql存储过程实例统计最大销售数量

1.需求 统计某天的销售的商品中,数量大于m的最大的销售数量。 传入参数:销售日期,销售数量 返回参数:最大销售数量 2.数据库表 销售表 CREATE TABLE t_sale ( id int NOT NULL COMMENT ‘主键’, good_id int NULL COMMENT ‘…

[山海关crypto 训练营 day17]

[HNCTF 2022 WEEK3]pnearq 题目代码和数据 from Crypto.Util.number import * from gmpy2 import next_prime from flag import flagp getPrime(1024) q next_prime(p) n p*q e 0x10001 c pow(bytes_to_long(flag), e, n) print(f"n {n}") print(f"c {…

chatgpt赋能Python-python8_9

Python 8-9: 了解更多关于Python的新特性 Python 作为一种高级编程语言已经被广泛应用于数据科学,Web开发,人工智能等领域。Python 8-9带来了新特色的更新和改进,这些功能使得Python更加强大和易于使用,吸引了越来越多开发者的关…

符尧最新研究:大语言模型玩砍价游戏?技巧水涨船高!

深度学习自然语言处理 原创作者:鸽鸽 若干年前,AlphaGo Zero用两个AI代理切磋围棋技艺,打败了人类。今早,符尧的一篇论文刷新了我的认知:让大语言模型相互对弈,再加一个评论家提供建设性意见,提…

自动控制原理备考-1题-传递函数

首先致敬西北工业大学自动控制原理的无冕之王张科老师。 期末考试,先下手为强,后下手遭殃。今天我们就开始一起针对期末考试有关题型一一梳理,突破解决。 给你一个系统结构图,让你求R(s)和N(s)同时作用下的C(s)。基本…