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

程序代码篇---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 编码转换为字符串 → 去除首尾空白字符
理解字节与字符串的区别、编码转换机制以及字符串处理方法,是解决串口通信中文乱码、格式错误等问题的关键。

相关文章:

  • Qt Quick Layout功能及架构
  • 从代码学习深度强化学习 - 初探强化学习 PyTorch版
  • 基于 Transformer robert的情感分类任务实践总结之二——R-Drop
  • model.classifier 通常指模型的分类头 是什么,详细举例说明在什么部位,发挥什么作用
  • 多模型协同:基于 SAM 分割 + YOLO 检测 + ResNet 分类的工业开关状态实时监控方案
  • Modbus RTU/TCP 协议详解与Spring Boot集成指南
  • 什么是异步 I/O?深入解析从基础到实践
  • 20250607-在Ubuntu中使用Anaconda创建新环境并使用本地的备份文件yaml进行配置
  • similarsites网页版入口,一键查询相似网站
  • Go 并发编程深度指南
  • 【MATLAB代码】基于MCC(最大相关熵)的EKF,一维滤波,用于解决观测噪声的异常|附完整代码,订阅专栏后可直接查看
  • mariadb5.5.56在centos7.6环境安装
  • JVM 垃圾回收器 详解
  • Python网页自动化测试,DrissonPage库入门说明文档
  • Spring Boot 3.3 + MyBatis 基础教程:从入门到实践
  • Android座舱系统Agent改造方案
  • cmake编译LASzip和LAStools
  • CVE-2023-25194源码分析与漏洞复现(Kafka JNDI注入)
  • Java优化:双重for循环
  • 2023年ASOC SCI2区TOP,随机跟随蚁群优化算法RFACO,深度解析+性能实测
  • wordpress怎么设置语言设置/济南seo网站关键词排名
  • 苏州专业网站建设公司/网站报价
  • 旅游公司网站 优帮云/关键词排名查询软件
  • 网站建设流程咨询/站长工具是干嘛的
  • 网络推广软文怎么写/seo词条
  • 请人做网站需要注意什么条件/seo网络搜索引擎优化