SerialPort通信建立:手把手完成第一个串口连接

手把手实现第一个串口连接:从零开始掌握 SerialPort 通信

你有没有遇到过这样的场景?手头有一块开发板,连上电脑后却不知道如何读取它发出来的数据;或者想用 JavaScript 写一个简单的传感器监控程序,却发现“串口”这个词听起来既熟悉又遥远。

别担心,这正是我们今天要解决的问题。
本文不讲空泛理论,也不堆砌术语,而是带你一步步亲手建立第一条串行通信链路——使用 Node.js 和serialport库,让代码真正“听见”硬件的声音。

整个过程就像调试一台老式收音机:选对频道(端口)、调好频率(波特率),然后就能清晰地接收到信号。准备好了吗?我们从最基础的环境搭建开始。


为什么是 SerialPort?JavaScript 怎么也能操作串口?

在很多人印象里,串口通信属于 C/C++、Python 或嵌入式工程师的领域。但随着 Electron、Node.js 在工业控制和 IoT 领域的渗透,JavaScript 正在打破软硬边界

serialport就是这个趋势中的明星库。它是一个基于 Node.js 的开源项目,封装了操作系统底层的串口访问机制,让你可以用熟悉的 JavaScript 语法打开 COM 端口、设置通信参数、收发数据。

更重要的是:
✅ 跨平台支持 Windows / macOS / Linux
✅ 支持 USB 转串口芯片(如 CH340、CP2102)
✅ 可集成到 Web 服务或桌面应用中(比如用 Electron 做可视化串口助手)

换句话说,你现在可以用写前端的方式,去跟单片机对话。


第一步:安装与环境准备

打开终端,创建项目并安装核心依赖:

mkdir my-first-serial && cd my-first-serial npm init -y npm install serialport @serialport/parser-readline

💡 提示:如果你使用的是 Linux 或 macOS,在后续运行脚本时可能会遇到权限问题。建议先执行:

bash sudo usermod -aG dialout $USER

然后重启系统,确保当前用户有访问/dev/tty*的权限。


第二步:找出你的设备接在哪个端口

每当你把 Arduino、ESP32 或任何带串口的设备插入电脑,系统都会为它分配一个“路径”——Windows 上叫COM3COM4,Linux/macOS 上则是/dev/ttyUSB0/dev/cu.usbserial-*

但我们怎么知道是哪一个?

SerialPort.list()来扫描所有可用串口:

const { SerialPort } = require('serialport'); SerialPort.list().then(ports => { if (ports.length === 0) { console.log('❌ 没有发现任何串口设备'); return; } console.log('✅ 发现以下串口设备:'); ports.forEach(port => { console.log(` 路径: ${port.path}`); console.log(` 制造商: ${port.manufacturer || '未知'}`); console.log(` PID/VID: ${port.productId}/${port.vendorId}\n`); }); }).catch(err => { console.error('枚举失败:', err.message); });

保存为list-ports.js并运行:

node list-ports.js

你会看到类似输出:

✅ 发现以下串口设备: 路径: COM3 制造商: Arduino LLC PID/VID: 0043/2341

记下这个path,接下来我们就用它建立连接。


第三步:连接设备 —— 波特率必须匹配!

这是最关键的一步:通信双方必须使用相同的波特率(baudRate),否则就像两个人用不同语速说话,结果只能听到“咕噜咕噜”。

常见波特率包括 9600、115200、57600 等。Arduino 默认常用 9600 或 115200;一些高速传感器可能用 460800 甚至更高。

假设我们的设备使用115200 波特率,其他参数为标准配置(8 数据位、1 停止位、无校验),就可以创建连接了:

const { SerialPort } = require('serialport'); const { ReadlineParser } = require('@serialport/parser-readline'); // 👇 修改为你自己的端口路径 const PORT_PATH = process.platform === 'win32' ? 'COM3' : '/dev/ttyUSB0'; const port = new SerialPort({ path: PORT_PATH, baudRate: 115200, dataBits: 8, stopBits: 1, parity: 'none', autoOpen: true // 自动打开,无需手动调用 open() });

这时候串口已经尝试连接了。但怎么知道是否成功呢?


第四步:监听事件,接收第一行数据

serialport是事件驱动的,就像网页里的 click 事件一样,你可以监听opendataerrorclose等关键状态。

我们来绑定几个重要事件:

// 当串口成功打开 port.on('open', () => { console.log('🎉 串口已打开,波特率:', port.settings.baudRate); // 可选:发送初始化指令(例如 AT 命令) const welcomeMsg = Buffer.from('Hello Device!\r\n'); port.write(welcomeMsg, (err) => { if (err) return console.error('发送失败:', err); console.log('👋 已向设备发送问候'); }); }); // 使用解析器按换行符拆分数据 const parser = new ReadlineParser({ delimiter: '\r\n' }); port.pipe(parser); parser.on('data', (line) => { console.log('📩 收到一行数据:', line.toString()); }); // 错误处理 port.on('error', (err) => { console.error('🚨 串口错误:', err.message); }); // 连接断开(比如拔掉了 USB 线) port.on('close', () => { console.log('🔌 串口已关闭'); });

将这段代码保存为serial-client.js并运行:

node serial-client.js

如果一切正常,你应该会看到:

🎉 串口已打开,波特率: 115200 👋 已向设备发送问候 📩 收到一行数据: TEMP:25.3,HUM:60 📩 收到一行数据: OK

恭喜!你刚刚完成了人生中第一次真正的串口通信。


关键参数详解:五个不能错的设置

为了帮助你避免“乱码”、“收不到数据”这类经典坑,这里列出必须与设备一致的五大参数:

参数典型值说明
baudRate9600, 115200速率要完全一致,差一点都会出错
dataBits8通常为 8,表示每个字符 8 位数据
stopBits1标志一帧结束,一般设为 1
parity‘none’奇偶校验,现代设备大多关闭
flowControlfalse流控用于防丢包,高吞吐场景开启

⚠️ 特别提醒:
很多初学者以为“波特率差不多就行”,但实际上必须精确匹配。比如设备是 115200,你设成 115000 就会持续出错。


数据粘包怎么办?教你用解析器正确分包

原始串口数据是以字节流形式到达的,没有天然的消息边界。这就导致一个问题:一条完整的消息可能被分成两次接收。

例如:
- 第一次收到"HELLO WOR"
- 第二次收到"LD\r\n"

合起来才是完整的一条"HELLO WORLD\r\n"—— 这就是所谓的“拆包”。

解决方案就是使用解析器(Parser)

serialport提供多种内置解析器:

1. 按行解析(推荐多数场景)

const parser = port.pipe(new ReadlineParser({ delimiter: '\n' })); parser.on('data', line => console.log('完整一行:', line));

适用于以\n\r\n结尾的日志、AT 指令等。

2. 固定长度解析

如果你知道每次发送都是 10 字节:

const { ByteLengthParser } = require('@serialport/parser-byte-length'); const parser = new ByteLengthParser({ length: 10 }); port.pipe(parser).on('data', chunk => { console.log('收到固定长度数据:', chunk); });

3. 自定义分隔符(高级)

比如某些协议使用0xFF 0xFE作为帧头:

const { DelimiterParser } = require('@serialport/parser-delimiter'); const parser = new DelimiterParser({ delimiter: Buffer.from([0xFF, 0xFE]) }); port.pipe(parser).on('data', frame => { console.log('收到完整帧:', frame); });

常见问题与应对策略

❌ 打不开串口:Permission Denied

原因:Linux/macOS 用户没有权限访问/dev/tty*
解决方法

sudo usermod -aG dialout $USER

然后注销重新登录。

🛠️ 临时方案:sudo node serial-client.js(不推荐长期使用)


❌ 收到一堆乱码或空字符串

原因:波特率不匹配!
排查步骤
1. 查看设备文档确认正确波特率
2. 用串口调试工具(如 XCOM、SSCOM)验证
3. 尝试常见组合:9600、19200、38400、115200


❌ 只能收到前几个字符

原因:未使用解析器,直接监听port.on('data')导致截断
解决方法:务必使用ReadlineParser或其它合适解析器进行流式处理


❌ 断线后无法自动恢复

默认情况下,一旦 USB 断开,serialport不会自动重连。

加入简单的重连逻辑即可:

let reconnectInterval; port.on('close', () => { console.log('⚠️ 串口已关闭,准备重连...'); if (!reconnectInterval) { reconnectInterval = setInterval(() => { console.log('🔁 正在尝试重新连接...'); connect(); // 重试连接函数 }, 3000); } }); function connect() { try { port.open((err) => { if (err) { console.log('重连失败:', err.message); return; } console.log('✅ 重连成功!'); clearInterval(reconnectInterval); reconnectInterval = null; }); } catch (e) { console.log('连接异常:', e.message); } }

实际应用场景举例

掌握了基本技能后,你可以做很多有趣的事:

✅ 温湿度监控系统

STM32 + DHT22 → UART → PC 上 Node.js 接收 → WebSocket → 浏览器实时图表

✅ 工业 PLC 数据采集

通过串口轮询 Modbus RTU 协议,定时读取电流、电压数据并存入数据库

✅ 自制串口调试助手

用 Electron + React 构建图形化界面,支持日志保存、命令发送、自动补全

✅ 自动化测试平台

MCU 出厂前自动烧录 + 串口验证功能是否正常,大幅提升产线效率


最佳实践建议

  1. 优先使用parser处理数据流,不要直接监听原始data事件
  2. 根据manufacturerpid/vid自动识别目标设备,提升用户体验
  3. 增加超时机制:长时间无响应时提示“设备未就绪”
  4. 记录通信日志:便于后期排查问题
  5. 避免暴露串口接口至公网:防止恶意操作物理设备

写在最后

你不需要成为嵌入式专家才能玩转串口。
通过serialport,JavaScript 开发者现在可以轻松打通软件与硬件之间的最后一公里。

回顾一下今天我们走过的路:
- 安装依赖、列出端口
- 配置正确的通信参数
- 成功打开串口并收发数据
- 使用解析器处理粘包问题
- 解决常见连接故障
- 展望实际工程应用

这一切都不再神秘。只要你有一根 USB 线、一块开发板、一段代码,就能让数字世界与物理世界真正对话。

如果你正在做一个物联网项目,或是需要和某个老旧设备通信,不妨试试serialport。也许下一秒,你就会听到那句期待已久的:“OK”。

对了,你在用什么设备做串口开发?Arduino?树莓派?还是工业PLC?欢迎在评论区分享你的实战经验!

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

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

相关文章

Cursor Pro功能完全解锁技术指南:突破试用限制的专业方案

Cursor Pro功能完全解锁技术指南:突破试用限制的专业方案 【免费下载链接】cursor-free-vip [Support 0.45](Multi Language 多语言)自动注册 Cursor Ai ,自动重置机器ID , 免费升级使用Pro 功能: Youve reached your …

Open Interpreter浏览器版:无需安装的云端体验

Open Interpreter浏览器版:无需安装的云端体验 你是不是也遇到过这样的情况?在网吧、图书馆或者朋友的电脑上,突然想试试用AI来编程,写个小程序、分析点数据,但发现根本没法安装软件——没有管理员权限,连…

音乐格式转换全攻略:让加密音频重获新生

音乐格式转换全攻略:让加密音频重获新生 【免费下载链接】unlock-music 在浏览器中解锁加密的音乐文件。原仓库: 1. https://github.com/unlock-music/unlock-music ;2. https://git.unlock-music.dev/um/web 项目地址: https://gitcode.co…

DeepSeek-R1-Distill-Qwen-1.5B迁移学习:领域适配的完整流程

DeepSeek-R1-Distill-Qwen-1.5B迁移学习:领域适配的完整流程 1. 引言 1.1 业务场景描述 在当前大模型快速发展的背景下,通用预训练语言模型虽然具备强大的基础能力,但在特定垂直领域(如金融、医疗、教育等)的应用中…

Arduino蜂鸣器音乐代码操作指南:轻松上手

用Arduino让蜂鸣器“唱歌”:从零实现一段旋律的完整指南你有没有试过,只用几行代码和一个不到一块钱的小元件,就能让开发板“演奏”出《小星星》?这听起来像魔法,其实背后不过是一个叫无源蜂鸣器的简单器件&#xff0c…

Cursor Pro功能无限使用技术实现方案

Cursor Pro功能无限使用技术实现方案 【免费下载链接】cursor-free-vip [Support 0.45](Multi Language 多语言)自动注册 Cursor Ai ,自动重置机器ID , 免费升级使用Pro 功能: Youve reached your trial request limit. / Too man…

VSCode中配置终极Fortran开发环境:2025完整指南

VSCode中配置终极Fortran开发环境:2025完整指南 【免费下载链接】vscode-fortran-support Fortran language support for Visual Studio Code 项目地址: https://gitcode.com/gh_mirrors/vs/vscode-fortran-support 想要在现代化开发环境中编写Fortran代码吗…

StructBERT中文情感分析镜像发布|CPU友好+WebUI+API一体化体验

StructBERT中文情感分析镜像发布|CPU友好WebUIAPI一体化体验 1. 项目背景与技术价值 在自然语言处理(NLP)领域,情感分析是企业级应用中最常见的需求之一。无论是用户评论、客服对话还是社交媒体内容,快速识别文本情绪…

ACE-Step中文歌曲生成指南:免本地GPU,10分钟出Demo

ACE-Step中文歌曲生成指南:免本地GPU,10分钟出Demo 你是不是也是一位热爱音乐创作的独立音乐人?想写一首属于自己的中文歌,却卡在旋律编排、编曲制作上无从下手?或者好不容易有了歌词灵感,却发现配乐太难搞…

BERT模型日志监控体系搭建:生产环境可观测性实战配置

BERT模型日志监控体系搭建:生产环境可观测性实战配置 1. 引言 1.1 业务场景描述 随着自然语言处理技术在企业服务中的广泛应用,基于BERT的语义理解系统已逐步成为智能客服、内容审核、自动补全等核心功能的技术底座。本文聚焦于一个典型NLP服务——中…

西安电子科技大学XeLaTeX论文模板:新手快速上手终极指南

西安电子科技大学XeLaTeX论文模板:新手快速上手终极指南 【免费下载链接】xdupgthesis [停止维护 请使用note286/xduts]西安电子科技大学研究生学位论文XeLaTeX模板 项目地址: https://gitcode.com/gh_mirrors/xd/xdupgthesis 还在为学位论文格式要求而头疼吗…

为什么Qwen2.5部署总失败?镜像适配问题一文详解

为什么Qwen2.5部署总失败?镜像适配问题一文详解 在大模型落地实践中,越来越多开发者选择使用预置镜像快速部署开源语言模型。然而,在尝试部署阿里云最新发布的 Qwen2.5-0.5B-Instruct 模型时,不少用户反馈“应用启动失败”、“显…

HID硬件调试常见问题:实战案例排错指南

HID硬件调试实战排错指南:从枚举失败到报告混乱的深度解析 你有没有遇到过这样的情况?一个精心设计的自定义HID设备插上电脑后,系统毫无反应;或者键盘明明只按了一个键,却莫名其妙触发了“CtrlC”复制操作&#xff1f…

Happy Island Designer创意设计指南:从新手到专家的岛屿规划实用工具

Happy Island Designer创意设计指南:从新手到专家的岛屿规划实用工具 【免费下载链接】HappyIslandDesigner "Happy Island Designer (Alpha)",是一个在线工具,它允许用户设计和定制自己的岛屿。这个工具是受游戏《动物森友会》(An…

ESP32开发环境使用MicroPython控制智能插座通俗解释

用MicroPython玩转ESP32:手把手教你做个能远程开关的智能插座 你有没有过这样的经历?出门后突然想起家里的电水壶好像没关,赶紧掏出手机查智能插座App——还好,早就养成随手断电的习惯了。但你知道吗?这种看似“高大上…

解锁创意边界:3D打印键盘配件的无限可能

解锁创意边界:3D打印键盘配件的无限可能 【免费下载链接】cherry-mx-keycaps 3D models of Chery MX keycaps 项目地址: https://gitcode.com/gh_mirrors/ch/cherry-mx-keycaps 当指尖触碰到键盘的那一刻,你是否曾想过,这些看似普通的…

Z-Image-Turbo显存不足?16GB消费级显卡部署案例全解析

Z-Image-Turbo显存不足?16GB消费级显卡部署案例全解析 1. 引言:Z-Image-Turbo为何值得部署? 随着AI生成内容(AIGC)技术的快速发展,文生图模型在创意设计、内容创作和数字艺术等领域展现出巨大潜力。然而&…

手把手教你用Qwen All-in-One实现智能对话应用

手把手教你用Qwen All-in-One实现智能对话应用 1. 引言:轻量级AI服务的新范式 在边缘计算和资源受限场景中,如何高效部署大语言模型(LLM)一直是工程实践中的核心挑战。传统方案往往依赖多个专用模型协同工作——例如使用BERT类模…

Axure RP中文界面改造实战:3分钟搞定全版本汉化配置

Axure RP中文界面改造实战:3分钟搞定全版本汉化配置 【免费下载链接】axure-cn Chinese language file for Axure RP. Axure RP 简体中文语言包,不定期更新。支持 Axure 9、Axure 10。 项目地址: https://gitcode.com/gh_mirrors/ax/axure-cn 还在…

通义千问3-14B竞赛必备:学生党逆袭,低成本用顶级算力

通义千问3-14B竞赛必备:学生党逆袭,低成本用顶级算力 你是不是也遇到过这样的情况?作为大学生参加AI竞赛,项目做到一半才发现本地电脑跑不动通义千问3-14B这种大模型——显存爆了、训练慢得像蜗牛、生成结果要等十几分钟。更糟心…