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

news2025/6/6 9:06:24

针对串口错误 “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 = None
                humidity = None
                weight = 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%%RH
                elif "%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])  # 去掉 g
                return temperature, humidity,weight
            except ValueError:
                print("无法解析串口数据:", raw_data)
                return None, None,None
    return 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_message

client.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 = None
    humidity_from_sensor = None
    weight_from_sensor = None
    while True:
        # 获取温度和湿度数据
        t, h, w = read_data_from_serial(ser)

        if t is not None:
            temperature_from_sensor = t
        if h is not None:
            humidity_from_sensor = h
        if 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 = None
            humidity_from_sensor = None

    time.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 = None
                humidity = None
                weight = None
                # 判断是温度
                if raw_data.endswith("C"):
                    temperature = float(raw_data[:-1])  # 去掉 C

                # 湿度:如 24.5 %RH 或 24.5%%RH
                elif "%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])  # 去掉 g
                return temperature, humidity,weight
            except ValueError:
                print("无法解析串口数据:", raw_data)
                return None, None,None
    return 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_message

client.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 = None
    humidity_from_sensor = None
    weight_from_sensor = None
    while True:
        # 获取温度和湿度数据
        t, h, w = read_data_from_serial(ser)

        if t is not None:
            temperature_from_sensor = t
        if h is not None:
            humidity_from_sensor = h
        if 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 = None
            humidity_from_sensor = None

        time.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.coloradmin.cn/o/2398594.html

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

相关文章

谷歌地图苹果版v6.138.2 - 前端工具导航

谷歌地图(Google maps)苹果版是是由谷歌官方推出的一款手机地图应用。软件功能强大,支持本地搜索查找世界各地的地址、地点和商家;支持在街景视图中查看世界各地的360度全景图;支持查找乘坐火车、公交车和地铁的路线,或者查找步行…

NSSCTF [LitCTF 2025]test_your_nc

[复现]绕过学的还是太差了&#xff0c;多积累吧 ​​​​​​题目 题目: 给了一个python文件 #!/bin/python3 import osprint("input your command")blacklist [cat,ls, ,cd,echo,<,${IFS},sh,\\]while True:command input()for i in blacklist:if i in com…

Qwen3高效微调

高效微调 场景、模型、数据、算力 高效微调的应用场景 对话风格微调&#xff1a;高效微调可以用于根据特定需求调整模型的对话风格。例如&#xff0c;针对客服系统、虚拟助理等场景&#xff0c;模型可以通过微调来适应不同的 语气、礼貌程度 或 回答方式&#xff0c;从而在与…

Gitee Wiki:重塑关键领域软件研发的知识管理范式

在数字化转型浪潮席卷全球的当下&#xff0c;关键领域软件研发正面临前所未有的知识管理挑战。传统文档管理模式的局限性日益凸显&#xff0c;知识传承的断层问题愈发严重&#xff0c;团队协作效率的瓶颈亟待突破。Gitee Wiki作为新一代知识管理平台&#xff0c;正在通过技术创…

redis的哨兵模式和Redis cluster

目录 一. redis的主从复制 二. 哨兵模式 2.1 定义 2.2 作用 2.3 配置实例 三. Redis cluster 3.1 定义 3.2 作用 3.3 配置实例 1. 新建集群文件目录 2. 准备可执行文件到每个文件夹 3. 开启群集功能 4. 启动redis节点 5. 查看是否启动成功 6. 启动集群 7. 测试…

农业机器人的开发

农业机器人的开发 喷农药机器人 番茄采摘机器人 葡萄采摘机器人 黄瓜采摘机器人 西瓜采摘机器人 蘑菇采摘机器人 草莓采摘机器人 草莓采摘机器人综述 视觉系统 CCD摄像机&#xff0c;距离传感器&#xff0c;PC计算机 其中CCD摄像机的作用是进行彩色图像的采集和进行果…

Swift 解锁 LeetCode 热门难题:不改数组也能找出重复数字?

文章目录 摘要描述题解答案题解代码分析解读&#xff1a; 示例测试及结果时间复杂度空间复杂度总结实际场景类比可运行 Demo&#xff08;Swift Playground&#xff09;未来展望 摘要 在数组中找出唯一的重复数字&#xff0c;听起来像一道简单的题目&#xff0c;但如果你不能修…

【深度学习】15. Segment Anything Model (SAM) :基于提示的分割新时代

Segment Anything Model (SAM) &#xff1a;基于提示的分割新时代 基本介绍 The first foundation model for promptable segmentation. Segment Anything Model&#xff08;简称 SAM&#xff09;是 Meta AI 于 2023 年提出的一种通用型图像分割基础模型。与以往分割模型不同&…

Java从入门到精通 - 常用API(一)

常用 API 此笔记参考黑马教程&#xff0c;仅学习使用&#xff0c;如有侵权&#xff0c;联系必删 文章目录 常用 API1. 包代码演示 2. String2.1 String 概述代码演示总结 2.2 String 的常用方法代码演示 2.3 String 使用时的注意事项第一点第二点代码演示 总结题目 2.4 String…

实现Cursor + Pycharm 交互

效果演示&#xff1a; 直接可以在cursor或Pycharm中点击右键点击&#xff0c;然后就可以跳转到另一个应用的对应位置了 使用方法&#xff1a; 分别在两个应用中安装插件【Switch2Cursor Switch2IDEA&#xff0c;这两个插件分别安装在 IDEA 和 Cursor 中】&#xff1a; Switc…

C++标准模板库

C标准库参考&#xff1a; C 标准库-CSDN博客 标准模板库STL C 标准库 和 STL 的关系 1. 严格来说&#xff0c;STL ≠ C 标准库 STL&#xff08;Standard Template Library&#xff09; 是 C 标准库的一个子集&#xff0c;主要提供泛型编程相关的组件&#xff08;如容器、迭代器…

dvwa6——Insecure CAPTCHA

captcha&#xff1a;大概是“我不是机器人”的一个勾选框或者图片验证 LOW: 先输入密码正常修改试一下&#xff08;123&#xff09;&#xff0c;发现报错 查看源码&#xff1a; <?phpif( isset( $_POST[ Change ] ) && ( $_POST[ step ] 1 ) ) {// Hide the C…

【学习笔记】On the Biology of a Large Language Model

On the Biology of a Large Language Model 1 Introduction 目标是对这些模型的内部工作机制进行逆向工程&#xff0c;从而更好地理解它们&#xff0c;并评估它们是否适合特定用途。 正如细胞是生物系统的基本构建单元&#xff0c;我们假设特征是模型内部计算的基本单位。仅仅…

飞腾D2000,麒麟系统V10,docker,ubuntu1804,小白入门喂饭级教程

#下载docker Index of linux/static/stable/ 根据电脑的CPU类型选择&#xff1a; Intel和AMD选x86_64飞腾D2000选aarch64 #选择较新的版本 #在包含下载的docker-XX.X.X.tgz的文件夹中右键->打开终端 # 解压安装包&#xff08;根据实际下载的文件&#xff09; tar -zxvf …

星野录(博客系统)测试报告

目录 一. 项目背景 二、项目功能 三、测试计划 1. 功能测试 1.1 测试用例 1.2 执行测试部分操作截图 2. 使用selenium进行自动化测试 2.1 添加相关依赖 2.2 登录页面测试 3.3 注册页面测试 3.4 博客列表页面测试 3.5 博客详情页测试 3.6 博客编辑页面测试 3.7 个人…

使用 Java 实现一个简单且高效的任务调度框架

目录 一、任务调度系统概述 (一)任务调度的目标 (二)任务调度框架的关键组成 二、任务状态设计 (一)任务状态流转设计 (二)任务表设计(SQL) 三、单机任务调度实现 (一)获取待处理任务 (二)执行任务 代码实现(单线程版本) (三)多线程提高吞吐量 四…

2022—2025年:申博之路及硕士阶段总结

文章目录 1 前景概要2 打造神兵利器2.1 夺天地之精2.2 锻兵魂之形2.3 契人兵之命 3 潜心闭关修炼3.1 第一阶段&#xff1a;苦心智3.2 第二阶段&#xff1a;劳筋骨3.3 第三阶段&#xff1a;摧意志 4 突破晋级4.1 突破失败4.2 聚气凝神4.3 心魔再现4.4 新起点 5 回顾及深思 1 前景…

项目执行中缺乏灵活应对机制,如何增强适应性?

项目执行中缺乏灵活应对机制可以通过建立风险预警机制、培养团队快速响应能力、制定动态调整方案、加强团队沟通协作、引入敏捷管理理念来增强适应性。 其中&#xff0c;培养团队快速响应能力尤为重要。这种能力意味着当项目遇到突发状况时&#xff0c;团队能迅速评估问题、确定…

Agentic Workflow是什么?Agentic Workflow会成为下一个AI风口吗?

无论是想要学习人工智能当做主业营收&#xff0c;还是像我一样作为开发工程师但依然要运用这个颠覆开发的时代宠儿&#xff0c;都有必要了解、学习一下人工智能。 近期发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;入行门槛低&#x…

BUUCTF[极客大挑战 2019]EasySQL 1题解

[极客大挑战 2019]EasySQL题解 分析解题过程漏洞原理分析明确注入点&#xff1a;尝试万能密码法法一法二 总结 分析 从题目分析&#xff0c;这道题应该与SQL注入有关&#xff0c;启动靶机之后&#xff0c;访问url是一个登录界面&#xff0c;随便输入用户名密码之后&#xff0…