嵌入式硬件篇---龙芯2k1000串口

article/2025/6/13 20:24:38

针对串口错误 “device reports readiness to read but returned no data (Device disconnected or multiple access on port?)” 的排查和解决方法

硬件方面

  1. 检查连接
    • 确认串口设备(如串口线、连接的模块等)与龙芯设备之间的物理连接是否牢固,没有松动、脱落情况。尝试重新插拔串口线,确保两端都插紧。
    • 查看串口线是否有破损、断裂等物理损坏迹象,如有,更换新的串口线。
  2. 检查设备供电
    • 确保串口设备供电正常。如果是外接设备,检查其电源适配器是否正常工作,输出电压和电流是否符合设备要求。可以使用万用表测量电源适配器输出,若不正常,更换适配 器。
    • 对于由龙芯设备直接供电的串口设备,检查龙芯设备的电源输出是否稳定,可查看龙芯设备电源指示灯状态,或使用相关工具监测电源输出。
  3. 排查设备冲突
    • 确认是否有多个设备同时尝试访问该串口端口。如果有其他程序或设备在占用 /dev/ttyS3 端口,可能会导致冲突。关闭其他可能使用该串口的程序或设备,然后重新测试。

软件方面

  1. 权限检查
    • 确保当前用户对 /dev/ttyS3 端口有足够的读写权限。在龙芯系统的终端中,使用命令 ls -l /dev/ttyS3 查看端口权限。如果权限不足,可通过 sudo chmod 666 /dev/ttyS3 临时赋予读写权限(不建议长期使用这种宽泛的权限设置,生产环境可通过添加用户到 dialout 等相关组来解决权限问题,如 sudo usermod -a -G dialout your_username ,然后重新登录)。
  2. 驱动检查与更新
    • 确认串口设备的驱动程序已正确安装。在龙芯系统中,可通过查看系统日志(一般在 /var/log 目录下,如 dmesg 日志),搜索与串口设备相关的信息,看是否有驱动加载错误提示。
    • 如果驱动程序版本过旧,尝试更新驱动。可到龙芯官方或设备制造商官网查找适用于龙芯平台的最新驱动程序,按照说明进行安装。
  3. 程序逻辑检查
    • 检查使用串口的应用程序代码,确认打开串口的参数设置(如波特率、数据位、停止位、校验位等)是否与串口设备实际设置一致。如果设置不匹配,会导致数据读取异常。
    • 排查程序中是否存在多线程或异步操作对串口访问的影响,确保对串口的读写操作是线程安全的,避免出现竞争条件导致数据读取失败。

import json
import time
import paho.mqtt.client as mqtt
import serial# 配置
MQTT_BROKER = "115.28.209.116"
MQTT_PORT = 1883
MQTT_USERNAME = "bkrc"
MQTT_PASSWORD = "88888888"
CLIENT_ID = "*************"
DEVICE_ID = "*************"TOPIC_UP = f"device/{DEVICE_ID}/up"
TOPIC_DOWN = f"device/{DEVICE_ID}/down"SERIAL_PORT = "COM4"
BAUDRATE = 115200
TIMEOUT = 1# 连接成功回调
def on_connect(client, userdata, flags, reason_code, properties):if reason_code == 0:print("已连接到MQTT服务器")client.subscribe(TOPIC_DOWN)else:print(f"连接失败,错误码:{reason_code}")def on_message(client, userdata, msg):print(f"收到下行消息:{msg.topic} -> {msg.payload.decode()}")# 从串口读取温度和湿度数据
def read_data_from_serial(ser):"""从串口读取温湿度数据,格式:26.7C24.0 %RH"""if ser and ser.is_open:raw_data = ser.readline().decode('utf-8').strip()  # 读取串口数据if raw_data:try:temperature = Nonehumidity = Noneweight = None# # 提取温度数据(温度后面跟着 'C')# temp_str = raw_data.split('C')[0]  # 以 'C' 为分隔符提取温度# temperature = float(temp_str) if temp_str else None## # 提取湿度数据(湿度后面跟着 '%RH')# humidity_str = raw_data.split('C')[1].split('%')[0]  # 先分割 'C',然后分割 '%'# humidity = float(humidity_str) if humidity_str else None## # 提取温度数据(温度后面跟着 'C')# weight_str = raw_data.split('g')[0]  # 以 'C' 为分隔符提取温度# weight = float(weight_str) if weight_str else None# 判断是温度if raw_data.endswith("C"):temperature = float(raw_data[:-1])  # 去掉 C# 湿度:如 24.5 %RH 或 24.5%%RHelif "%RH" in raw_data:humi_str = raw_data.replace("%RH", "").replace("%%RH", "").strip()humidity = float(humi_str)# 重量:如 25.7g(独立上报)elif raw_data.endswith("g"):weight = float(raw_data[:-1])  # 去掉 greturn temperature, humidity,weightexcept ValueError:print("无法解析串口数据:", raw_data)return None, None,Nonereturn None, None,None# 创建MQTT客户端
client = mqtt.Client(client_id=CLIENT_ID, protocol=mqtt.MQTTv5)
client.username_pw_set(MQTT_USERNAME, MQTT_PASSWORD)
client.on_connect = on_connect
client.on_message = on_messageclient.connect(MQTT_BROKER, MQTT_PORT, keepalive=60)
client.loop_start()# 串口连接
try:ser = serial.Serial(SERIAL_PORT, BAUDRATE, timeout=TIMEOUT)print(f"成功连接串口 {SERIAL_PORT}")temperature_from_sensor = Nonehumidity_from_sensor = Noneweight_from_sensor = Nonewhile True:# 获取温度和湿度数据t, h, w = read_data_from_serial(ser)if t is not None:temperature_from_sensor = tif h is not None:humidity_from_sensor = hif w is not None:weight_from_sensor = w  # 缓存最新重量# 只要温湿度都有数据,就上传if temperature_from_sensor is not None and humidity_from_sensor is not None:data = {"sign": DEVICE_ID,"type": "1","data": {"Temp": {"temp": str(temperature_from_sensor)},"Humi": {"humi": str(humidity_from_sensor)},}}if w is not None:data["data"]["Weight"] = {"weight": str(weight_from_sensor)}weight_from_sensor = None  # 上传后清空缓存client.publish(TOPIC_UP, json.dumps(data, ensure_ascii=False))print(f"上报数据:{json.dumps(data, ensure_ascii=False)}")# 立刻清空温湿度数据,避免重复上传同样数据temperature_from_sensor = Nonehumidity_from_sensor = Nonetime.sleep(0.1)except KeyboardInterrupt:print("程序终止")client.loop_stop()client.disconnect()except serial.SerialException as e:print(f"串口错误:{str(e)}")except Exception as e:print(f"程序运行错误:{str(e)}")finally:if 'ser' in locals() and ser.is_open:ser.close()print("串口已关闭")

这段代码实现了一个通过 MQTT 协议将串口设备数据上传到服务器的功能。它从串口读取温湿度和重量数据,然后将这些数据封装成 JSON 格式发布到 MQTT 服务器。以下是对代码的详细解释:

模块导入和配置

import json
import time
import paho.mqtt.client as mqtt
import serial# 配置
MQTT_BROKER = "115.28.209.116"
MQTT_PORT = 1883
MQTT_USERNAME = "bkrc"
MQTT_PASSWORD = "88888888"
CLIENT_ID = "1c097bc15129e3e2ef44f88c286b4475"
DEVICE_ID = "29c9c7bf1dafd9ca"TOPIC_UP = f"device/{DEVICE_ID}/up"
TOPIC_DOWN = f"device/{DEVICE_ID}/down"SERIAL_PORT = "COM4"
BAUDRATE = 115200
TIMEOUT = 1

  • 模块导入:导入了处理 JSON、时间、MQTT 通信和串口通信的模块。
  • MQTT 配置:设置了 MQTT 服务器的地址、端口、用户名、密码以及客户端 ID 和设备 ID,并定义了上下行消息的主题
  • 串口配置:设置了串口的端口号、波特率和超时时间

MQTT 回调函数

# 连接成功回调
def on_connect(client, userdata, flags, reason_code, properties):if reason_code == 0:print("已连接到MQTT服务器")client.subscribe(TOPIC_DOWN)else:print(f"连接失败,错误码:{reason_code}")def on_message(client, userdata, msg):print(f"收到下行消息:{msg.topic} -> {msg.payload.decode()}")

  • on_connect:当成功连接到 MQTT 服务器时被调用,订阅下行消息主题。
  • on_message:当收到 MQTT 服务器的消息时被调用,打印收到的消息内容。

串口数据读取函数

# 从串口读取温度和湿度数据
def read_data_from_serial(ser):"""从串口读取温湿度数据,格式:26.7C24.0 %RH"""if ser and ser.is_open:raw_data = ser.readline().decode('utf-8').strip()  # 读取串口数据if raw_data:try:temperature = Nonehumidity = Noneweight = None# 判断是温度if raw_data.endswith("C"):temperature = float(raw_data[:-1])  # 去掉 C# 湿度:如 24.5 %RH 或 24.5%%RHelif "%RH" in raw_data:humi_str = raw_data.replace("%RH", "").replace("%%RH", "").strip()humidity = float(humi_str)# 重量:如 25.7g(独立上报)elif raw_data.endswith("g"):weight = float(raw_data[:-1])  # 去掉 greturn temperature, humidity,weightexcept ValueError:print("无法解析串口数据:", raw_data)return None, None,Nonereturn None, None,None

  • 该函数从串口读取一行数据,并根据数据的后缀(C、% RH、g)来判断数据类型(温度、湿度、重量)。
  • 处理了可能出现的格式错误,确保数据能够被正确解析。

MQTT 客户端初始化和连接

# 创建MQTT客户端
client = mqtt.Client(client_id=CLIENT_ID, protocol=mqtt.MQTTv5)
client.username_pw_set(MQTT_USERNAME, MQTT_PASSWORD)
client.on_connect = on_connect
client.on_message = on_messageclient.connect(MQTT_BROKER, MQTT_PORT, keepalive=60)
client.loop_start()
  • 创建 MQTT 客户端实例,设置用户名和密码,绑定回调函数。
  • 连接到 MQTT 服务器并启动后台线程处理网络通信

串口连接和数据处理主循环

# 串口连接
try:ser = serial.Serial(SERIAL_PORT, BAUDRATE, timeout=TIMEOUT)print(f"成功连接串口 {SERIAL_PORT}")temperature_from_sensor = Nonehumidity_from_sensor = Noneweight_from_sensor = Nonewhile True:# 获取温度和湿度数据t, h, w = read_data_from_serial(ser)if t is not None:temperature_from_sensor = tif h is not None:humidity_from_sensor = hif w is not None:weight_from_sensor = w  # 缓存最新重量# 只要温湿度都有数据,就上传if temperature_from_sensor is not None and humidity_from_sensor is not None:data = {"sign": DEVICE_ID,"type": "1","data": {"Temp": {"temp": str(temperature_from_sensor)},"Humi": {"humi": str(humidity_from_sensor)},}}if w is not None:data["data"]["Weight"] = {"weight": str(weight_from_sensor)}weight_from_sensor = None  # 上传后清空缓存client.publish(TOPIC_UP, json.dumps(data, ensure_ascii=False))print(f"上报数据:{json.dumps(data, ensure_ascii=False)}")# 立刻清空温湿度数据,避免重复上传同样数据temperature_from_sensor = Nonehumidity_from_sensor = Nonetime.sleep(0.1)except KeyboardInterrupt:print("程序终止")client.loop_stop()client.disconnect()except serial.SerialException as e:print(f"串口错误:{str(e)}")except Exception as e:print(f"程序运行错误:{str(e)}")finally:if 'ser' in locals() and ser.is_open:ser.close()print("串口已关闭")

  • 串口连接:尝试打开指定的串口。
  • 数据处理循环
    • 不断从串口读取数据,并更新缓存的温湿度和重量数据。
    • 当同时有温度和湿度数据时,将它们封装成 JSON 格式并发布到 MQTT 服务器。
    • 如果有重量数据,也一并封装到 JSON 中,并在上传后清空重量缓存
    • 上传数据后清空温湿度缓存,避免重复上传相同数据
  • 异常处理:捕获键盘中断、串口异常和其他异常,确保程序能够优雅地退出,并在退出前关闭串口和 MQTT 连接。


http://www.hkcw.cn/article/ZEFWuPlQFS.shtml

相关文章

Ubuntu安装Docker命令清单(以20.04为例)

在你虚拟机上完成Ubuntu的下载后打开终端!!! Ubuntu安装Docker终极命令清单(以20.04为例) # 1. 卸载旧版本(全新系统可跳过) sudo apt-get remove docker docker-engine docker.io containerd …

数据结构:递归:自然数之和

目录 递归解法 🔹第一步:定义本质问题 🔹第二步:分解问题结构 🔹第三步:定义初始条件 🔹第四步:递归思想的自然生成 循环解法 🔹第 1 步:定义问题最小…

Pandas 技术解析:从数据结构到应用场景的深度探索

序 我最早用Python做大数据项目时,接触最早的就是Pandas了。觉得对于IT技术人员而言,它是可以属于多场景的存在,因为它的本身就是数据驱动的技术生态中,对于软件工程师而言,它是快速构建数据处理管道的基石&#xff1…

CRM管理软件的数据可视化功能使用技巧:让数据驱动决策

在当今数据驱动的商业环境中,CRM管理系统的数据可视化功能已成为企业优化客户管理、提升销售效率的核心工具。据企销客研究显示,具备优秀可视化能力的CRM系统,用户决策效率可提升47%。本文将深入解析如何通过数据可视化功能最大化CRM管理软件…

数据结构:递归的种类(Types of Recursion)

目录 尾递归(Tail Recursion) 什么是 Loop(循环)? 复杂度分析 头递归(Head Recursion) 树形递归(Tree Recursion) 线性递归(Linear Recursion)…

Redis底层数据结构之字典(Dict)

Dict基本结构 Dict我们可以想象成目录,要翻看什么内容,直接通过目录能找到页数,翻过去看。如果没有目录,我们需要一页一页往后翻,这样时间复杂度就与遍历的O(n)一样了,而用了Dict我们就可以在O(1)的时间复杂…

高通SoC阵列服务器

高通SoC阵列服务器是基于高通系统级芯片(SoC)构建的高密度计算解决方案,核心特点为低功耗、高算力集成与模块化设计,主要应用于边缘计算和云服务场景。以下是其技术特性和应用方向的综合分析: 一、核心技术特性 架构…

Linux系统下Google浏览器无法使用中文输入的临时解决方案

文章目录 前言方案描述Edge如何兼容 前言 这个AlamaLinux的ibus-libpinyin确实是让人琢磨不透,就只是无法在Chrome浏览器中、Edge浏览器中使用,而在VSCode、Xfce4-Terminal中使用良好。尝试了很多办法都没有效果,最后在Reddit里面找到了相应…

【AI论文】空间多模态大型语言模型(Spatial-MLLM):增强基于视觉的空间智能中多模态大型语言模型(MLLM)的能力

摘要:多模态大语言模型(MLLM)的最新进展显著提高了2D视觉任务的性能。 然而,提高他们的空间智能仍然是一个挑战。 现有的3D MLLM总是依赖于额外的3D或2.5D数据来加入空间感知,限制了它们在只有2D输入(如图像…

黑马Java面试笔记之 微服务篇(业务)

一. 限流 你们项目中有没有做过限流?怎么做的? 为什么要限流呢? 一是并发的确大(突发流量) 二是防止用户恶意刷接口 限流的实现方式: Tomcat:可以设置最大连接数 可以通过maxThreads设置最大Tomcat连接数,实现限流,但是适用于单体架构 Nginx:漏桶算法网关,令牌桶算法自定…

AWS App Mesh实战:构建可观测、安全的微服务通信解决方案

摘要:本文详解如何利用AWS App Mesh统一管理微服务间通信,实现精细化流量控制、端到端可观测性与安全通信,提升云原生应用稳定性。 一、什么是AWS App Mesh? AWS App Mesh 是一种服务网格(Service Mesh)解…

《云原生安全攻防》-- K8s网络策略:通过NetworkPolicy实现微隔离

默认情况下,K8s集群的网络是没有任何限制的,所有的Pod之间都可以相互访问。这就意味着,一旦攻击者入侵了某个Pod,就能够访问到集群中任意Pod,存在比较大的安全风险。 在本节课程中,我们将详细介绍如何通过N…

吃透 Golang 基础:数据结构之 Map

文章目录 Map概述初始化删除访问不存在的 key 返回 value 的零值遍历 mapmap 自身的零值map 索引时返回的第二个参数使用 map 实现 set Map Hash Map 是无序的 key/value 对集合,其中所有的 key 都是不同的。通过给定的 key 可以在常数时间复杂度内完成检索、更新或…

手机邮箱APP操作

收发电子邮件方式 邮箱可以在网络段登录,也可以在手机端登录。 大学网络服务 收发电子邮件有三种方式: 1、Web方式: 1)登录“网络服务”(https://its.pku.edu.cn),点页面顶端“邮箱”。 2&…

Spring AI之RAG入门

目录 1. 什么是RAG 2. RAG典型应用场景 3. RAG核心流程 3.1. 检索阶段 3.2. 生成阶段 4. 使用Spring AI实现RAG 4.1. 创建项目 4.2. 配置application.yml 4.3. 安装ElasticSearch和Kibana 4.3.1. 安装并启动ElasticSearch 4.3.2. 验证ElasticSearch是否启动成功 …

Spring AI Alibaba + Nacos 动态 MCP Server 代理方案

作者:刘宏宇,Spring AI Alibaba Contributor 文章概览 Spring AI Alibaba MCP 可基于 Nacos 提供的 MCP server registry 信息,建立一个中间代理层 Java 应用,将 Nacos 中注册的服务信息转换成 MCP 协议的服务器信息&#xff0c…

19-项目部署(Linux)

Linux是一套免费使用和自由传播的操作系统。说到操作系统,大家比较熟知的应该就是Windows和MacOS操作系统,我们今天所学习的Linux也是一款操作系统。 我们作为javaEE开发工程师,将来在企业中开发时会涉及到很多的数据库、中间件等技术&#…

2025.6.3学习日记 Nginx 基本概念 配置 指令 文件

1.初始nginx Nginx(发音为 “engine x”)是一款高性能的开源 Web 服务器软件,同时也具备反向代理、负载均衡、邮件代理等功能。它由俄罗斯工程师 Igor Sysoev 开发,最初用于解决高并发场景下的性能问题,因其轻量级、高…

SpringCloud——Nacos注册中心、OpenFeign

一、Nacos注册中心 1.注册中心原理 2.服务注册 添加依赖&#xff1a; <!--nacos 服务注册发现--> <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dep…

WAF绕过,网络层面后门分析,Windows/linux/数据库提权实验

一、WAF绕过文件上传漏洞 win7&#xff1a;10.0.0.168 思路&#xff1a;要想要绕过WAF&#xff0c;第一步是要根据上传的内容找出来被拦截的原因。对于文件上传有三个可以考虑的点&#xff1a;文件后缀名&#xff0c;文件内容&#xff0c;文件类型。 第二步是根据找出来的拦截原…