登录
首页 >  Golang >  Go教程

golang如何实现串口通信Serial Port_golang串口通信Serial Port实现技巧

时间:2026-05-04 08:37:30 111浏览 收藏

一分耕耘,一分收获!既然都打开这篇《golang如何实现串口通信Serial Port_golang串口通信Serial Port实现技巧》,就坚持看下去,学下去吧!本文主要会给大家讲到等等知识点,如果大家对本文有好的建议或者看到有不足之处,非常欢迎大家积极提出!在后续文章我会继续更新Golang相关的内容,希望对大家都有所帮助!

最推荐使用 github.com/goburrow/serial:API 简洁、无 CGO 依赖、全平台支持、错误处理清晰;需显式配置 Address、BaudRate 等参数,读写阻塞需配合 context 或 goroutine 控制超时,Linux 权限问题须加 dialout 组。

golang如何实现串口通信Serial Port_golang串口通信Serial Port实现技巧

Go 语言本身不提供串口通信原生支持,必须依赖第三方库;最成熟、跨平台、维护活跃的是 github.com/tarm/serial,但要注意它已归档,新项目建议优先考虑 github.com/jacobsa/serialgithub.com/goburrow/serial(后者更轻量且仍在更新)。

goburrow/serial 打开串口并读写数据

这是目前最推荐的入门选择:API 简洁、无 CGO 依赖、Windows/macOS/Linux 全支持、错误处理清晰。

  • 安装:go get github.com/goburrow/serial
  • 关键配置项必须显式设置:Address(如 /dev/ttyUSB0COM3)、BaudRate(如 9600)、DataBits(通常 8)、StopBits(通常 1)、Parity(通常 serial.NoParity
  • 打开后务必检查返回的 error,常见失败原因包括端口被占用、权限不足(Linux/macOS 需加 sudo 或将用户加入 dialout 组)、设备不存在
  • 读写都是阻塞的,默认无超时 —— 若需响应性,应配合 context.WithTimeout 或启动 goroutine + select 监听 time.After
cfg := &serial.Config{
    Address:  "/dev/ttyUSB0",
    BaudRate: 9600,
    DataBits: 8,
    StopBits: 1,
    Parity:   serial.NoParity,
}
port, err := serial.Open(cfg)
if err != nil {
    log.Fatal(err) // 比如 "permission denied" 或 "no such file"
}
defer port.Close()

// 写入
_, err = port.Write([]byte("AT\r\n"))
if err != nil { log.Print("write failed:", err) }

// 读取(需注意:可能只读到部分字节,要自己拼接或按协议解析)
buf := make([]byte, 128)
n, _ := port.Read(buf)
log.Printf("read %d bytes: %s", n, string(buf[:n]))

为什么 tarm/serial 不再推荐?

它曾是事实标准,但现在仓库已标记为 Archived,最后一次提交在 2020 年;其底层使用 CGO 调用系统 API,在 Windows 上依赖 msvcrt,交叉编译困难;更严重的是,它对读缓冲区管理较粗放,容易出现丢字节或阻塞无法退出的问题。

  • 如果你在旧代码里看到 serial.OpenPortserial.Mode,说明用的是这个库
  • 迁移成本低:只需替换 import 和构造 config 的方式,其余读写逻辑基本一致
  • 特别注意:它默认开启硬件流控(RTS/CTS),而多数嵌入式设备并不启用 —— 必须手动设 Mode.RTSCTSControl = serial.NoHardwareFlowControl,否则可能发不出数据

如何可靠地接收不定长响应(比如 AT 指令回显)?

串口没有“消息边界”,Read 返回的字节数完全取决于当前缓冲区状态和调用时机。不能假设一次 Read 就能拿到完整响应。

  • 最稳妥的做法是按协议特征切分:比如等待 "\r\n""OK\r\n" 或特定结束符
  • 避免死等:用带超时的循环,每次读少量字节(如 1~16 字节),追加到临时 []byte,再扫描是否满足结束条件
  • 警惕粘包和拆包:同一帧可能分两次 Read 到达;也可能一次 Read 包含两帧 —— 所以解析逻辑必须可重入、支持残留数据缓存
  • 不要依赖 port.SetReadTimeout(部分库不实现或行为不一致),统一用 time.Timer 控制整体等待窗口

Linux 下 Permission denied 怎么快速修复?

不是代码问题,是系统权限问题。错误信息通常是 open /dev/ttyUSB0: permission denied

  • 临时方案:sudo chmod a+rw /dev/ttyUSB0(每次插拔后失效)
  • 永久方案:把当前用户加入 dialout 组:sudo usermod -a -G dialout $USER,然后**完全退出当前会话(关闭终端、重新登录)**,否则组权限不生效
  • 验证:groups 命令输出中应包含 dialoutls -l /dev/ttyUSB0 显示组为 dialout 且有读写权限
  • 注意:某些发行版(如 Ubuntu 22.04+)改用 plugdev 组,可查 udevadm info --name=/dev/ttyUSB0 | grep GROUP

串口通信真正的复杂点从来不在打开或读写那几行代码,而在于时序控制、异常恢复(断线重连、缓冲区溢出)、协议解析健壮性,以及不同操作系统底层驱动行为的细微差异 —— 这些没法靠一个库自动兜底,得在业务逻辑层做针对性设计。

终于介绍完啦!小伙伴们,这篇关于《golang如何实现串口通信Serial Port_golang串口通信Serial Port实现技巧》的介绍应该让你收获多多了吧!欢迎大家收藏或分享给更多需要学习的朋友吧~golang学习网公众号也会发布Golang相关知识,快来关注吧!

资料下载
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>