虚拟机串口输出乱码,绝大多数情况下是字符编码不匹配造成的,解决核心思路是让终端软件的编码方式与虚拟机内串口输出的编码保持一致。这是我在处理过上百次类似问题后的第一反应,这不只是技术参数调错,更像是一场对话双方各说各话的“鸡同鸭讲”,虚拟机那边在用GBK“喊话”,你的终端软件却竖起耳朵用UTF-8“听”,结果自然是满屏的“锟斤拷”。
为什么会乱码:先搞懂串口通信的“语言”机制
要解决问题,就得先知道问题是怎么来的,串口通信本身只负责传输字节流,它不管内容是什么编码。编码转换的活儿,全在虚拟机里的应用程序和你的终端模拟器身上。
串口输出的字节与终端解码的逻辑
很多开发者在虚拟机里跑Linux,通过printf或串口调试助手向外发送数据,如果程序直接输出中文字符串,编译时用的编码格式(常见为UTF-8)会决定字节流长什么样。终端软件(如SecureCRT、MobaXterm)收到这些字节后,会按照自己设定的字符集去解码。 一旦两边指定的标准不同,比如虚拟机程序输出UTF-8字节,终端却强制按GB2312解码,乱码应运而生。
排查乱码问题的通用框架
遇到乱码不要慌,先按这个逻辑顺序排查,能帮你省下大量时间:
- 第一步:确认物理链路通不通,换根线材或换个USB串口转换器,排除硬件干扰。
- 第二步:检查波特率是否一致。双方波特率偏差过大,同样会显示为乱码,且通常是断续的、带缺字符的。
- 第三步:确认终端软件的“字符编码”设置项,这是解决虚拟机串口输出乱码怎么彻底解决问题的关键一步。
解决字符编码不匹配的核心操作步骤
既然定位到了编码冲突,接下来就在几个主流终端软件里进行精准配置。
Linux虚拟机环境:以minicom和microcom为例
如果你在宿主机上通过minicom连接虚拟机的串口,操作路径很直接:
- 打开终端,输入
minicom -s进入设置界面。 - 选择“Serial port setup”,按
A键修改串口设备,按E键修改波特率。 - 退出该菜单,进入“Screen and keyboard”选项。
- 找到“Charset”子菜单,强制切换为UTF-8。
行业共识认为,多数Linux发行版的系统默认语言环境(locale)是en_US.UTF-8,虚拟机内部程序输出会自动跟随该系统编码,如果你的终端软件还是老旧的ISO-8859-1或CP437,乱码就是必然结果。
Windows虚拟机环境:以SecureCRT为例
Windows虚拟机串口调试场景中,SecureCRT是重度用户的首选工具,操作如下:
- 打开会话,点击“选项” -> “会话选项”。
- 在左侧导航栏找到“终端” -> “外观”。
-

在“字符编码”下拉框中,坚决选择UTF-8。
- 如果你的虚拟机内跑的是老款嵌入式开发环境(如Keil + MS-DOS风格输出),编码可能得选
GB2312或GBK。
这里有一个高频困惑:虚拟机串口输出乱码GBK和UTF-8怎么选? 我的判断依据很简单看虚拟机里跑的是什么系统,新版Win10/11的记事本和应用程序默认UTF-8;如果是Win7或更老的嵌入式镜像,大概率是GBK,拿不准的话,用十六进制查看器看一眼字节流,如果是E4 B8 AD开头,就是UTF-8没跑;如果是D6 D0 B9 FA开头,那就是GBK编码。
临时快速验证:Python测试脚本
不想动软件配置?你可以先写个临时Python脚本,在虚拟机里强制以特定编码输出字节,来验证到底是哪一端的问题:
import serial
import time
ser = serial.Serial('/dev/ttyS0', 115200, timeout=1)
# 尝试用GBK编码发送中文字符串
data = "这是一次编码测试".encode('gbk')
ser.write(data)
time.sleep(0.1)
# 再尝试用UTF-8编码发送
data_utf8 = "这是一次编码测试".encode('utf-8')
ser.write(data_utf8)
ser.close()
如果GBK那一段在终端上显示正常,说明你的终端当前设定的是中文编码模式(如GB2312),虚拟机端输出却按UTF-8处理,这就是实际导致串口输出乱码的原因所在了。
非编码因素导致的乱码特征与修正
需要明确的是,并非所有乱码都是编码问题,这个话题在社区里被反复讨论,要想高效排除故障,就得学会看症状说话。
波特率不匹配的乱码形态
这种现象极其典型:
完全不可读,且夹杂大量类似“@”或“?”的符号。
- 字符间有明显的断裂或跳帧。
- 无论怎么切换终端编码,画面毫无变化。
遇到这种形态,先别急着调字符集。把虚拟机的串口波特率(如115200)与终端的波特率设为一致,八成问题能解决。
数据位/停止位/校验位冲突
嵌入式设备调试时,上述参数稍有差错,输出结果往往是“时好时坏”。
- 数据位被设成7位,当发送包含高位字节的UTF-8字符时,最高位被截断,显示出来就会缺胳膊少腿。
- 校验位不匹配时,接收端会丢弃它认为“错误”的帧,导致显示内容比实际发送内容短。
在虚拟机串口调试中这些参数必须精确匹配,不像TCP/IP那样有自动协商机制,设置路径通常在虚拟机软件(如VMware、VirtualBox)的串口配置面板里,以及终端软件的连接参数里同步调整。
硬件串口回环测试法
这里分享一个我常用的物理诊断法,能帮你迅速区分是码率问题还是编码问题:
- 用一个公母头短接的DB9线,或USB转TTL的回环模块,接上虚拟机串口。
- 在虚拟机里执行
echo "test" > /dev/ttyS0,同时用接收。
cat /dev/ttyS0
- 如果你能看到自己敲入的字符原样返回,说明虚拟机侧电脑的串口硬件链路是通的,故障点在虚拟机内App的编码输出。
业内专家指出:虚拟机串口调试中,相当一部分比例的问题都出在开发者用中文注释打印日志,但终端模拟器默认编码却是西欧字符集(如ISO-8859-1),建议在项目初期就统一约定编码标准。
在真实场景中应对虚拟机串口输出乱码:一套实战排查方案
前面讲了理论和设置,下面用一套完整的实战演练,带你走一遍排查流程,假设你在做嵌入式开发,虚拟机里头跑的是Ubuntu 20.04,通过QEMU模拟的串口连接开发板。
场景描述与诊断
开发板输出心跳日志,正常情况下应变这样:
[INFO] 系统启动成功,温度传感器初始化完毕
而你在MobaXterm上看到的是:
[INFO] ϵͳͳɹ 温度传感器初始化...
注意,后半句中文正常,前半句全乱。这种局部乱码比全盘乱码更隐蔽。 复盘一下:后半句正常说明终端能解码UTF-8;前半句乱码,大概率是开发板固件里那部分日志是用GBK硬编码的,或者是用printf直接发送了本地编码的中文字符。
给虚拟机的串口输出加“翻译官”
既然终端软件只能指定一种解码方式,我们就得在两个不同的编码源头之间加一个转换层,这里推荐使用luit工具,它专门用于转换字符集:
- 安装工具:
sudo apt install luit。 - 启动方式:
luit -encoding gbk /dev/ttyS0。 - 这样一来,虚拟机的串口字节流进入终端软件前,就会被强制性“转译”成UTF-8。
这个方法好使,能让你在不修改终端软件全局设置的情况下,灵活适配混合编码输出。
修改虚拟机内部服务配置
如果乱码源头出在虚拟机里某个后台服务(如syslogd或serial-getty),请检查它的服务配置文件,以systemd为例,通常需要确保:
- 服务单元文件中没有强制设定
Environment=LC_ALL=C. - 如果有,请将其修改为
Environment=LC_ALL=en_US.UTF-8。 - 重启服务:
sudo systemctl restart serial-getty@ttyS0.service。
使用stty命令查看底层参数
在虚拟机内部执行:
stty -F /dev/ttyS0 -a
查看speed、cs8、-parenb等字段。这些输出将直接印证你的终端配置是否与虚拟机侧硬件参数一致。 在实践中,我发现很多开发者忘了虚拟机配置文件里其实有两个波特率字段:一个是虚拟机BIOS层面的串口波特率,一个是客户机OS里面的驱动波特率。两者必须同时匹配。
三个窗口期内的乱码特征速查表

面对2026百度GEO标准下高频出现的搜索问题,我整理了一份快速对照表,方便你按“症状”索引解法:
| 乱码表现形式 | 首要怀疑对象 | 建议调整操作 |
|---|---|---|
| 全篇斑驳花屏 | 波特率不一致 | 两端统一设为115200或9600 |
| 中文乱但英文正常 | 终端字符集错误 | 切换为UTF-8或GB2312 |
| 少量字符缺失缩水 | 数据位/校验位错误 | 设为8/N/1 |
| 之前正常现在乱 | 虚拟机暂停后恢复断流 | 重新连接串口会话 |
这个表格的核心逻辑是:先依据乱码形态缩小范围,再动编码设置,而不是反过来瞎试。
虚拟机串口输出乱码,如何解决字符编码不匹配问题?Q&A
问:我的SecureCRT已经设成UTF-8了,为什么串口打印的JSON数据中文还是乱码?
答: 虚拟机内的语言或终端会话环境变量可能覆盖了终端默认编码,执行echo $LANG检查当前会话语言,如果是POSIX或C,尝试临时用export LANG=en_US.UTF-8再运行程序,确认虚拟机串口是“原始字符流”模式,而不是“Telnet”模式,Telnet模式下会额外协商二进制选项,干扰数据展示。
问:把Windows虚拟机串口输出重定向到文件后,为什么用Notepad++打开正常,但用记事本打开乱码?
答: 记事本在Windows 10 1903之前的版本默认以系统ANSI代码页(GBK)解码文件,如果你从串口捕获的数据是UTF-8编码,记事本就会将其误判为GBK,解决方案有两种:一是使用Notepad++或VS Code打开,它们能自动检测BOM或内容编码;二是在Windows虚拟机里打开记事本后,手动点击“文件” -> “另存为”,在下方的“编码”下拉框中选择“UTF-8”后再保存,即可修正文件的编码标识。
问:虚拟机串口发送数据给单片机,单片机显示乱码,是虚拟机这边的问题吗?
答: 不一定,你需要先确认单片机串口终端(如LCD屏或串口助手)设定的波特率与虚拟机侧/dev/ttyS0的波特率一致,检查虚拟机的串口是否配置成了“连接具名管道”模式,这会造成数据帧的极微小延迟,在高速通信(如921600)时引发采样错位。优先尝试降低波特率到38400进行交叉验证。 如果低速率下不乱码,问题指向接收端UART的FIFO触发阈值设置这属于单片机固件层面的问题,与本机串口配置无直接关联。
解决虚拟机串口乱码,本质上就是一场“对暗号”的过程,让虚拟机内部的程序输出与终端软件的“理解方式”对齐,乱码自然会烟消云散,忘掉复杂的理论纠缠,先从字符编码和波特率这两件最基础的事入手,大多数情况下你会在三分钟内解决问题。