当前位置: 首页 > article >正文

程序代码篇---Python串口

在 Python 里,serial库(一般指pyserial)是串口通信的常用工具。下面为你介绍其常用的读取和发送操作函数及使用示例:

1. 初始化串口

要进行串口通信,首先得对串口对象进行初始化,代码如下:

import serial# 初始化串口
ser = serial.Serial(port='/dev/ttyUSB0',  # 串口设备,Windows系统可能是COM1、COM2等baudrate=9600,         # 波特率timeout=1              # 超时时间(秒)
)# 判断串口是否已打开
if ser.is_open:print("串口已打开")

2. 发送数据

使用write()函数可以向串口发送数据,示例如下:

# 发送字符串
ser.write(b'Hello, serial!\n')  # 注意要使用字节类型# 发送字节数据
data = [0x01, 0x02, 0xFF]
ser.write(bytes(data))

3. 读取数据

读取数据有多种方式,以下是几种常见的:

# 读取单个字节
byte = ser.read()  # 返回一个字节# 读取指定数量的字节
data = ser.read(size=10)  # 最多读取10个字节# 读取一行数据(以换行符结尾)
line = ser.readline()  # 需设置超时时间,避免程序阻塞# 循环读取所有可用数据
while ser.in_waiting:data = ser.read(ser.in_waiting)print(f"收到数据: {data}")

4. 其他常用函数

还有一些辅助函数能帮助你更好地进行串口通信:

# 获取待读取的字节数
bytes_waiting = ser.in_waiting# 清空输入/输出缓冲区
ser.flush()           # 清空所有缓冲区
ser.flushInput()      # 清空输入缓冲区
ser.flushOutput()     # 清空输出缓冲区# 关闭串口
ser.close()

完整示例

下面是一个完整的串口通信示例,展示了数据的发送和读取过程:

import serialtry:# 初始化串口ser = serial.Serial(port='/dev/ttyUSB0',baudrate=9600,timeout=1)# 发送数据ser.write(b'Hello, Arduino!\n')# 读取响应if ser.in_waiting:response = ser.readline().decode('utf-8').strip()print(f"收到响应: {response}")except serial.SerialException as e:print(f"串口错误: {e}")
finally:# 确保串口最终会被关闭if 'ser' in locals() and ser.is_open:ser.close()

使用串口通信时,要特别留意以下几点:

  1. 要保证波特率、数据位、停止位等参数和设备设置一致。
  2. 为避免程序阻塞,建议设置超时时间
  3. 数据传输时,要注意字节和字符串之间的转换
  4. 要妥善处理异常情况,并及时关闭串口

在 Python 的serial库中,read()readline()readlines()是用于从串口读取数据的三个常用方法,它们的功能和行为有明显区别。以下是对这三个方法的详细对比:

1. read(size=1)

  • 功能:从串口读取指定数量的字节(默认读取 1 个字节)。
  • 参数
    • size:要读取的最大字节数,默认值为 1。
  • 返回值:返回一个包含读取字节的bytes对象。
  • 特点
    • 非阻塞行为:如果没有数据可读,且设置了timeout,则最多等待timeout秒后返回空字节b''
    • 精确控制:适合按固定长度读取数据(如二进制协议)。
  • 示例
    # 读取1个字节
    byte = ser.read()# 读取10个字节
    data = ser.read(size=10)
    

2. readline()

  • 功能:从串口读取一行数据,直到遇到换行符\n(或超时)
  • 参数:无。
  • 返回值:返回包含读取内容bytes对象包含换行符
  • 特点
    • 行缓冲机制:需要设置timeout,否则可能因等待换行符而导致程序阻塞。
    • 文本协议适用:适合按行读取文本数据(如日志、命令响应)。
  • # 读取一行数据(以\n结尾)
    line = ser.readline()  # 返回 b'Hello\n'
    print(line.decode('utf-8'))  # 转为字符串并打印
    

3. readlines()

  • 功能:读取多行数据,直到超时,并返回一个包含所有行的列表
  • 参数
    • hint(可选):指定读取的最大字节数,默认值为 - 1(无限制)。
  • 返回值:返回一个由bytes对象组成的列表,每个元素代表一行。
  • 特点
    • 批量读取:一次性读取所有可用数据,并按行分割。
    • 依赖超时:必须设置timeout,否则会一直等待直到无新数据。
  • 示例
    # 读取所有行直到超时
    lines = ser.readlines()  # 返回 [b'Line 1\n', b'Line 2\n']
    for line in lines:print(line.decode('utf-8').strip())  # 打印每行内容(去除换行符)
    

核心区别总结

方法读取方式终止条件返回类型适用场景
read(size)按字节数读取读取指定数量的字节或超时bytes二进制数据、固定长度协议
readline()按行读取遇到换行符\n或超时bytes(单行)文本协议、逐行处理
readlines()批量读取多行超时(收集所有完整行)list[bytes]一次性读取所有数据并按行分割

注意事项

  1. 超时设置

    • 所有方法都依赖timeout参数,否则可能导致程序阻塞(尤其是readline()readlines())。
    • 建议在初始化串口时设置合理的超时值(如timeout=1)。
  2. 编码问题

    • 串口返回的是bytes类型,若需转为字符串,需使用decode()方法(如data.decode('utf-8'))。
  3. 性能考量

    • readlines()会一次性读取所有数据到内存,若数据量较大可能导致内存占用过高

常见应用场景

  • 读取传感器数据:使用read(size)按固定长度解析二进制数据
  • 命令行交互:使用readline()读取设备响应(如 AT 指令)
  • 日志收集:使用readlines()批量获取历史数据

根据具体需求选择合适的方法,可以更高效地处理串口通信。

在计算机中,\r(回车符)、\n(换行符)和\r\n(回车换行符)是用于表示文本行结束的不同方式,它们源于不同的历史背景和系统设计。以下是它们的核心区别和应用场景:

1. 基本定义

  • \r(回车符,Carriage Return)

    • 对应 ASCII 码13(十进制),表示为\r0x0D(十六进制)。
    • 作用:将光标移动到当前行的行首,不换行。
  • \n(换行符,Line Feed)

    • 对应 ASCII 码10(十进制),表示为\n0x0A(十六进制)。
    • 作用:将光标移动到下一行,但不回到行首。
  • \r\n(回车换行符)

    • 组合使用\r\n,表示一个完整的行结束符。
    • 常见于 Windows 系统和网络协议(如 HTTP、SMTP)。

2. 历史起源

  • 打字机时代

    • \r:将打印头移动到行首(Carriage Return)。
    • \n:将纸张向上滚动一行(Line Feed)。
    • 早期计算机沿用了这两个控制字符的组合。
  • 不同系统的标准化

    • Unix/Linux/macOS(现代):使用\n作为行结束符。
    • Windows:使用\r\n作为行结束符。
    • 旧版 macOS(OS 9 及之前):使用\r作为行结束符。
    • 网络协议(如 HTTP、SMTP):强制使用\r\n确保跨平台兼容性。

3. 实际影响

文本处理差异
  • Unix 系统

    # Unix文本文件(每行以\n结尾)
    line1\nline2\nline3
    
  • Windows 系统

    # Windows文本文件(每行以\r\n结尾)
    line1\r\nline2\r\nline3
    
  • 跨平台问题

    • 若在 Windows 中打开 Unix 文件,可能会看到^M符号(即\r)。
    • 若在 Unix 中打开 Windows 文件,每行末尾可能会多出一个不可见的\r
编程语言处理
  • Python

    # 读取文件时自动处理不同换行符
    with open('file.txt', 'r') as f:lines = f.readlines()  # 自动识别\n、\r\n或\r# 手动处理字节数据时需注意
    data = b'line1\r\nline2\nline3\r'
    lines = data.split(b'\r\n')  # 需根据实际情况选择分隔符
    
  • 正则表达式

    import re# 匹配任意换行符
    re.split(r'\r\n|\r|\n', text)
    

4. 应用场景

场景推荐使用的行结束符示例说明
Unix/Linux 脚本\nShell 脚本、Python 脚本等默认使用\n
Windows 程序\r\n批处理文件(.bat)、Windows 文本编辑器默认使用\r\n
网络协议\r\nHTTP 请求 / 响应、SMTP 邮件协议等要求使用\r\n分隔行。
串口通信取决于设备- 某些设备(如 Arduino)默认使用\r\n
- 需查阅设备文档确认。
编程处理按需求选择- 若处理多平台文本,建议使用 Python 的universal newlines模式。

5. 转换方法

  • 文本编辑器

    • VS Code、Sublime Text 等支持在不同换行符格式(LF/CRLF)间切换。
  • 命令行工具

    # Windows → Unix(将\r\n替换为\n)
    dos2unix file.txt# Unix → Windows(将\n替换为\r\n)
    unix2dos file.txt
    
  • Python 代码

    # 将\r\n转换为\n
    with open('windows.txt', 'r') as f:content = f.read().replace('\r\n', '\n')
    with open('unix.txt', 'w') as f:f.write(content)
    

总结

符号ASCII 值名称系统示例场景
\n10换行符(LF)Unix/Linux/macOS代码文件、Unix 配置文件
\r13回车符(CR)旧版 macOS(OS 9-)极少使用
\r\n13+10回车换行符(CRLF)Windows、网络协议Windows 文本、HTTP 请求 / 响应

选择合适的行结束符时,需考虑目标系统应用场景,避免因换行符不匹配导致的解析错误。

response = ser.readline().decode('utf-8').strip() 这行代码虽然简短,但涉及了串口通信、编码转换和字符串处理等多个关键知识点。以下是对其含义及背后知识点的详细解析:

1. ser.readline():从串口读取一行数据

  • 功能:从串口缓冲区读取数据,直到遇到换行符 \n(或超时)。

  • 返回值:返回一个 bytes 类型的对象,包含读取的原始字节数据(包括换行符)。

  • 示例
    若串口接收到 Hello World!\r\n,则 ser.readline() 返回 b'Hello World!\r\n'

  • 注意事项

    • 需要设置串口超时时间(如 timeout=1),否则可能因等待换行符而导致程序阻塞。
    • 若数据中没有换行符readline() 会等待到超时,并返回已读取的部分数据。

2. .decode('utf-8'):字节解码为字符串

  • 功能:将 bytes 类型的数据按指定编码格式转换为 str 类型(即字符串)

  • 编码格式

    • UTF-8:一种通用的 Unicode 编码,支持全球大多数语言(如中文、英文、日文等)。
    • 其他常见编码
      • 'gbk':中文国标码,兼容简体中文。
      • 'ascii':仅支持英文字母、数字和基本符号。
      • 'latin-1':西欧语言编码,直接映射字节值(0-255)。
  • 示例

    b = b'Hello World!\r\n'
    s = b.decode('utf-8')  # 转换为字符串 'Hello World!\r\n'
    
  • 潜在问题

    • 若数据编码与指定编码不匹配,会抛出 UnicodeDecodeError
      例如:
      # 假设数据实际为GBK编码
      b = b'\xd6\xd0\xce\xc4'  # GBK编码的"中文"
      b.decode('utf-8')  # 报错:UnicodeDecodeError
      b.decode('gbk')    # 正确:'中文'
      
    • 解决方案:
      try:s = data.decode('utf-8')
      except UnicodeDecodeError:s = data.decode('gbk', errors='replace')  # 忽略无法解码的字符
      

3. .strip():去除字符串首尾空白字符

  • 功能:移除字符串开头和结尾的空白字符(如 \n\r、空格、制表符 \t 等)。

  • 示例

    s = '  Hello World!\r\n  '
    s.strip()  # 返回 'Hello World!'
    
  • 变体方法

    • .lstrip():仅移除左侧空白字符。
    • .rstrip():仅移除右侧空白字符。
    • .strip(chars):移除指定字符(如 .strip('\r\n') 仅移除换行符)。

4. 完整流程示例

假设串口发送的原始数据为 b'Hello World!\r\n',执行 response = ser.readline().decode('utf-8').strip() 后:

  1. ser.readline() 返回 b'Hello World!\r\n'bytes 类型)。
  2. .decode('utf-8') 将其转换为字符串 'Hello World!\r\n'str 类型)。
  3. .strip() 移除首尾的 \r\n,最终 response 的值为 'Hello World!'

5. 关键知识点总结

操作输入类型输出类型作用
ser.readline()bytes从串口读取一行数据(含换行符)
.decode('utf-8')bytesstr将字节按 UTF-8 编码转换为字符串
.strip()strstr移除字符串首尾的空白字符

编码格式适用范围常见场景
utf-8全球通用编码,支持多语言互联网数据、跨平台文本
gbk简体中文中文 Windows 系统、早期中文软件
ascii仅英文和基本符号简单文本协议(如 HTTP 头)

6. 常见问题与建议

  1. 编码错误

    • 若数据包含非 UTF-8 字符(如中文),尝试使用 'gbk' 或 'latin-1' 解码。
    • 使用 errors='ignore' 或 errors='replace' 忽略 / 替换无法解码的字符。
  2. 换行符处理

    • 若需要保留换行符(如处理多行文本),可省略 .strip()
    • 若数据使用 \r 或 \r\n 作为换行符,可使用 .replace('\r', '') 统一处理。
  3. 调试技巧

    # 打印原始字节数据,便于排查编码问题
    data = ser.readline()
    print(f"原始字节: {data}")
    try:response = data.decode('utf-8').strip()print(f"解码后: {response}")
    except UnicodeDecodeError as e:print(f"解码错误: {e}")
    

总结

这行代码的核心逻辑是:
从串口读取原始字节数据 → 按 UTF-8 编码转换为字符串 → 去除首尾空白字符
理解字节与字符串的区别、编码转换机制以及字符串处理方法,是解决串口通信中文乱码、格式错误等问题的关键。

相关文章:

程序代码篇---Python串口

在 Python 里,serial库(一般指pyserial)是串口通信的常用工具。下面为你介绍其常用的读取和发送操作函数及使用示例: 1. 初始化串口 要进行串口通信,首先得对串口对象进行初始化,代码如下: i…...

jenkins gerrit-trigger插件配置

插件gerrit-trigger下载好之后要在Manage Jenkins -->Gerrit Trigger-->New Server 中新增Gerrit Servers 配置好保存后点击“状态”查看是否正常...

虚拟主机都有哪些应用场景?

虚拟主机作为一种高效的网络托管方案,已经逐渐成为企业构建网站和应用软件的重要选择,下面,小编将为大家介绍一下虚拟主机的应用场景都有哪些吧! 虚拟主机可以帮助企业建立属于自己的企业网站,是用来展示公司形象和服务…...

预训练语言模型T5-11B的简要介绍

文章目录 模型基本信息架构特点性能表现应用场景 T5-11B 是谷歌提出的一种基于 Transformer 架构的预训练语言模型,属于 T5(Text-To-Text Transfer Transformer)模型系列,来自论文 Colin Raffel, Noam Shazeer, Adam Roberts, Kat…...

数论总结,(模版与题解)

数论 欧拉函数X质数(线性筛与二进制枚举)求解组合数欧拉降幂(乘积幂次)乘法逆元最小质因子之和模版 欧拉函数 欧拉函数的定义就是小于等于n的数里有f(n)个数与n互质,下面是求欧拉函数的模版。 package com.js.datas…...

EasyRTC嵌入式音视频通信SDK助力物联网/视频物联网音视频打造全场景应用

一、方案概述​ 随着物联网技术的飞速发展,视频物联网在各行业的应用日益广泛。实时音视频通信技术作为视频物联网的核心支撑,其性能直接影响着系统的交互体验和信息传递效率。EasyRTC作为一款成熟的音视频框架,具备低延迟、高画质、跨平台等…...

1-2 Linux-虚拟机(2025.6.7学习篇- win版本)

1、虚拟机 学习Linux系统,就需要有一个可用的Linux系统。 如何获得?将自己的电脑重装系统为Linux? NoNo。这不现实,因为Linux系统并不适合日常办公使用。 我们需要借助虚拟机来获得可用的Linux系统环境进行学习。 借助虚拟化技术&…...

Deepseek基座:Deepseek-v2核心内容解析

DeepSeek原创文章1 DeepSeek-v3:基于MLA的高效kv缓存压缩与位置编码优化技术 2 Deepseek基座:DeepSeek LLM核心内容解析 3 Deepseek基座:Deepseek MOE核心内容解析 4 Deepseek基座:Deepseek-v2核心内容解析 5Deepseek基座&#xf…...

2025主流智能体Agent终极指南:Manus、OpenManus、MetaGPT、AutoGPT与CrewAI深度横评

当你的手机助手突然提醒"明天会议要带投影仪转接头",或是电商客服自动生成售后方案时,背后都是**智能体(Agent)**在悄悄打工。这个AI界的"瑞士军刀"具备三大核心特征: 自主决策能力:像老司机一样根据路况实时…...

家政小程序开发——AI+IoT技术融合,打造“智慧家政”新物种

基于用户历史订单(如“每周一次保洁”)、设备状态(如智能门锁记录的清洁频率),自动生成服务计划。 结合天气数据(如“雨天推荐玻璃清洁”),动态推送服务套餐。 IoT设备联动&#x…...

Keil开发STM32生成hex文件/bin文件

生成hex文件生成bin文件 STM32工程的hex文件和bin文件都可以通过Keil直接配置生成 生成hex文件 工程中点击魔术棒,在 Output 中勾选 Create HEX File 选项,OK保存工程配置 编译工程通过后可以看到编译输出窗口有创建hex文件的提示 默认可以在Output文…...

Windows 系统安装 Redis 详细教程

Windows 系统安装 Redis 详细教程 一、Redis 简介 Redis(Remote Dictionary Server)是一个开源的、基于内存的高性能键值存储系统,常被用作数据库、缓存和消息中间件。相比传统数据库,Redis 具有以下优势: 超高性能…...

“组件、路由懒加载”,在 Vue3 和 React 中分别如何实现? (copy)

Vue3 和 React 组件懒加载实现方式 React 中组件懒加载的实现方式 React 提供了 React.lazy 和 Suspense 两个 API 来实现组件的懒加载。React.lazy 用于动态导入组件,而 Suspense 则用于指定加载过程中的占位内容。例如,可以通过以下代码实现懒加载&a…...

.NET 事件模式举例介绍

.NET 事件模式:实现对象间松耦合通信 在软件开发中,对象之间的通信是一个常见且重要的问题。.NET 框架提供了一种标准化的事件模式,用于解决对象间的通信问题,实现松耦合的交互方式。今天,我们就通过一个简单的例子来…...

PDF 转 Markdown

本地可部署的模型 Marker Marker 快速准确地将文档转换为 markdown、JSON 和 HTML。 转换所有语言的 PDF、图像、PPTX、DOCX、XLSX、HTML、EPUB 文件在给定 JSON 架构 (beta) 的情况下进行结构化提取设置表格、表单、方程式、内联数学、链接、引用和代…...

北大开源音频编辑模型PlayDiffusion,可实现音频局部编辑,比传统 AR 模型的效率高出 50 倍!

北大开源了一个音频编辑模型PlayDiffusion,可以实现类似图片修复(inpaint)的局部编辑功能 - 只需修改音频中的特定片段,而无需重新生成整段音频。此外,它还是一个高性能的 TTS 系统,比传统 AR 模型的效率高出 50 倍。 自回归 Tra…...

蒲公英盒子连接问题debug

1、 现象描述 2、问题解决 上图为整体架构图,其中左边一套硬件设备是放在机房,右边是放在办公室。左边的局域网连接了可以访问外网的路由器,利用蒲公英作为旁路路由将局域网暴露在外网环境下。 我需要通过蒲公英作为旁路路由来进行远程访问&…...

Unity | AmplifyShaderEditor插件基础(第五集:简易膨胀shader)

一、👋🏻前言 大家好,我是菌菌巧乐兹~本节内容主要讲一下,如何用shader来膨胀~ 效果预览: 二、💨膨胀的基本原理 之前的移动是所有顶点朝着一个方向走,所以是移动 如果所有顶点照着自己的方…...

Django核心知识点全景解析

引言 本文深入剖析Django核心组件,涵盖数据交换、异步交互、状态管理及安全认证,附完整代码示例和避坑指南! 目录 引言 一、JSON:轻量级数据交换标准 1. 核心特性 2. 标准格式 3. 各语言处理方法 4. 常见错误示例 二、AJA…...

生物发酵展同期举办2025中国合成生物学与生物制造创新发展论坛

一、会议介绍 2025中国合成生物学与生物制造创新发展论坛暨上海国际合成生物学与生物制造展览会于2025年8月7-9日在上海新国际博览中心(浦东新区龙阳路2345号)召开,本次论坛汇聚了国内外顶尖学者、行业领袖及政策制定者,将围绕“…...

WINUI——Magewell视频捕捉开发手记

背景 因需要融合视频,并加载患者CT中提取出的气管镜与病变,以便能实时查看气管镜是否在正确位置。 开发环境 硬件:Magewell的USB Capture HDMI Gen 2 IDE:VS2022 FrameWork: .Net6 WINUI Package: MVVMToolKit NLog Ma…...

Jetpack Compose 中,DisposableEffect、LaunchedEffect 和 sideEffect 区别和用途

在 Jetpack Compose 中,DisposableEffect、LaunchedEffect 和 sideEffect 都是用于处理副作用(Side Effects)的 API,但它们的用途和触发时机不同。以下是它们的核心概念和区别: 1. 副作用(Side Effect&…...

STM32开发,创建线程栈空间大小判断

1. 使用RTOS提供的API函数(以FreeRTOS为例) 函数原型:UBaseType_t uxTaskGetStackHighWaterMark(TaskHandle_t xTask)功能:获取指定任务堆栈中剩余的最小空间(以字为单位,非字节)。使用步骤&am…...

正则表达式检测文件类型是否为视频或图片

// 配置化文件类型检测(集中管理支持的类型) const FILE_TYPE_CONFIG {video: {extensions: [mp4, webm, ogg, quicktime], // 可扩展支持更多格式regex: /^video\/(mp4|webm|ogg|quicktime)$/i // 自动生成正则},image: {extensions: [jpeg, jpg, png,…...

Qwen大语言模型里,<CLS>属于特殊的标记:Classification Token

Qwen大语言模型里,<CLS>属于特殊的标记:Classification Token 目录 Qwen大语言模型里,<CLS>属于特殊的标记:Classification Token功能解析工作机制应用场景举例说明技术要点在自然语言处理(NLP)领域 都是<CLS> + <SEP>吗?一、CLS和SEP的作用与常见用法1. **CLS标…...

TDengine 开发指南——无模式写入

简介 在物联网应用中,为了实现自动化管理、业务分析和设备监控等多种功能,通常需要采集大量的数据项。然而,由于应用逻辑的版本升级和设备自身的硬件调整等原因,数据采集项可能会频繁发生变化。为了应对这种挑战,TDen…...

分布式互斥算法

1. 概述:什么是分布式互斥 假设有两个小孩想玩同一个玩具(临界资源),但玩具只有一个,必须保证一次只有一个人能够玩。当一个小孩在玩时,另一个小孩只能原地等待,直到玩完才能轮到自己。这就是 …...

第34次CCF-CSP认证真题解析(目标300分做法)

第34次CCF-CSP认证 矩阵重塑(其一)AC代码及解析矩阵重塑(其二)AC代码及解析货物调度AC代码及解析 矩阵重塑(其一) 输入输出及样例: AC代码及解析 1.线性化原矩阵 :由于cin的特性我们…...

video-audio-extractor:视频转换为音频

软件介绍 前几天在网上看见有人分享了一个源码,大概就是py调用的ffmpeg来制作的。 这一次我带来源码版(需要py环境才可以运行),开箱即用版本(直接即可运行) 软件特点 软件功能 视频提取音频&#xff1a…...

rk3588 区分两个相同的usb相机

有时候会插入两个一模一样的usb相机,担心每次启动他们所对应的设备节点 /dev/video* 会变化,所以需要绑定usb口,区分两个相机。把两个相机都插入后,查看usb信息 rootrk3588:/# udevadm info --attribute-walk --name/dev/video0U…...