Linux 485驱动通信异常
背景
前段时间接到一个项目,要求用主控用485和MCU通信。将代码调试好之后,验证没问题就发给测试了。测试测的也没问题。
但是,到设备量产时,发现有几台设备功能异常。将设备拿回来排查,发现是485通信有问题,偶现通信失败。
排查思路
复现问题
发给测试之前,功能都验证了很多次,但是并没有发现通信失败的问题。设备拿到手,第一时间就尝试复现通信失败的问题,也没有成功。
于是,写了一个脚本,不断的和MCU通信,看什么情况下会失败。
果然,在通信若干次后,发现日志异常,主控接收数据出现了错乱。
接着,继续跑脚本,想看下什么情况下会失败。但是,每次通信异常的时机都是随机的,没有规律。
观察了下错乱的数据,和正确的数据做了对比,也没有什么发现。
清空buf
接收的数据出现了异常,第一个想到的是,是不是接收buffer不干净,有其他数据干扰呢?
尝试在接收buffer和发送buffer之前,手动清空下buf。确保不会有其它数据干扰。
重新跑脚本和MCU 通信,但是仍会失败。
收发时序
光看是什么办法了。上示波器看下主控和MCU的时序的。
正常来讲,主控和MCU的485控制管脚应该是正好反向的电平。即主控485控制管脚高电平发送的时候,MCU的485控制管脚应该是低电平。
问题复现时,对比了管脚的电平,确实是反向的,没有问题。这也排除了收发时序对不上的问题。
(绿色的是MCU的485控制管脚,黄色的是主控的485控制管脚)
收发数据正确
小示波器没有解码的功能,只能找硬件来量下主控的RX和MCU的TX。确认下,到底是主控接收的不对,还是MCU发的不对。
显然,是主控接收的数据有问题了。
仔细观察会发现,绿色波形这里有个半高电平,覆盖了黄色的低电平。导致第一帧出错了,后面的数据也都错乱了。
又重新复现了几次,发现每次失败时都是这种现象。那为什么这里会有个半高电平呢?
确认问题
和硬件对着原理图经过一番讨论,硬件给到的结论是,485芯片的RX管脚接了3.3V的上拉,只有当485芯片的使能管脚拉高时,RX才会有3.3V的半高电平出现。硬件怀疑是485控制管脚和MCU的时序没对上。
不过,我之前也量了主控和MCU的485控制管脚的电平,看了是对的?难道是我看错了?
接着又重新量了主控和MCU的485控制管脚,发现确实有问题,具体如下图。两者有1.5ms的高电平是重合的,这或许就是问题所在!
又重新复现了几次问题,发现每次通信失败时,都会有一段高电平是重合的。
到这里,基本也就明确了问题原因:主控和MCU的485控制管脚时序没对上!
寻找问题根因
从波形找出了问题所在,回归串口编程,继续看下代码吧。把重点放在了时序切换的代码上。
代码里面,在切换485管脚时有这样两段代码。
以下只是伪代码
代码一:
setdir(SEND) //切换为发送状态
write() //发送数据
tcdrain(fd) //判断是否写完
setdir(READ) //切换为读状态
代码二:
do
{ioctl(fd,TIOCSERGETLSR,&lsr) //判断发送buffer是否写完
}while(!(lsr&TIOCSER_TEMT)) //如果TX为空,返回TIOCSER_TEMT
这两段代码,都是和485管脚切换相关的,根据不同情况走不同逻辑,出问题的代码走的是代码一片段。
tcdrain 和 TIOCSERGETLSR
那这两段代码有什么区别呢?
tcdrain是应用层控制tty的一个函数,调用 tcdrain()函数后会使得应用程序阻塞, 直到串口输出缓冲区中的数据全部发送完毕为止。
ioctl(fd,TIOCSERGETLSR,&lsr)
是获取tty 设备的线路状态寄存器( LSR )的值。
这两段代码最大区别就是延时不同!
tcdrain()是等待fd所引用的串口设备数据传输完毕。虽然在物理上数据已传输完毕时,但Linux对硬件实时性高,对于用户请求的实时性较低。所以操作系统会有延时,导致tcdrain()多停留几ms,从而导致数据发送完后,485管脚的控制方向不能及时切换。
如果对接的485设备,接收和应答的延迟小于tcdrain()的延时,那方向切换不及时将导致数据接收丢失。这就是问题根因所在。
那为什么操作系统会有延时呢?
这个得说说Linux工作队列相关机制,对于硬件操作Linux处理的很及时,但是对于数据Linux可能将其交给系统的下半部的内核线程去处理,这就可能导致用户的系统调用存在一定的延时,而485通信对时间要求又很严格,1ms的延时就会导致数据错乱。
总结
- 严谨细致。在问题发生时,我也去量过主控和和MCU 485控制管脚的电平,只看到了两者是反向的,但是并没有放大去看最后一段电平的细节。导致遗漏了解决问题的线索。
- 一切问题发生都是有原因的。偶现问题并不好排查,但是我们可以尝试制作偶现问题发生的条件,看有没有可能成为必现问题。如果不能必现,可尝试通过脚本去不断运行在问题发生的场景,使其出现的概率提升。
相关文章:

Linux 485驱动通信异常
背景 前段时间接到一个项目,要求用主控用485和MCU通信。将代码调试好之后,验证没问题就发给测试了。测试测的也没问题。 但是,到设备量产时,发现有几台设备功能异常。将设备拿回来排查,发现是485通信有问题ÿ…...
mybatis配置与标签大全
文章目录 mybatis配置与标签大全mybatis的配置属性(properties)设置(settings)类型别名(typeAliases)类型处理器(typeHandlers)对象工厂(objectFactory)插件&…...

Mysql的基本用法(上)非常详细、快速上手
上篇结束了java基础,本篇主要对Mysql中的一些常用的方法进行了总结,主要对查询方法进行了讲解,包括重要的多表查询用到的内连接和外连接等,以下代码可以直接复制到可视化软件中,方便阅读以及练习; SELECT *…...
使用Vite创建React + TypeScript(node版本为16.17.0,含资源下载)
PC端 安装指令: npm create vitelatest react-ts-pro -- --template react-tsVite是一个框架无关的前端工具链,可以快速的生成一个React TS的开发环境,并且可以提供快速的开发体验说明: 1. npm create vitelatest固定写法&#…...

Springboot集成RabbitMq二
接上一篇:Springboot集成RabbitMq一-CSDN博客 1、搭建项目-消费者 与之前一样 2、创建配置类 package com.wym.rabbitmqconsumer.utils;import org.springframework.amqp.core.Binding; import org.springframework.amqp.core.BindingBuilder; import org.spring…...
机器学习笔记 - 基于Python的不平衡数据的欠采样技术
一、简述 随着从不同的来源生成和捕获大量数据。尽管信息量巨大,但它往往反映了现实世界现象的不平衡分布。数据不平衡的问题不仅仅是统计上的挑战,它对数据驱动模型的准确性和可靠性具有深远的影响。 以金融行业欺诈检测为例。尽管我们希望避免欺诈,因为其具有高度破坏性,…...
facebook广告的基础知识
Facebook广告是在Facebook、Instagram、Audience Network等与Facebook相关的SNS和服务上投放的广告。以下是关于Facebook广告的基础知识: 广告类型: 静态图片广告:主要通过Facebook的新闻提要投放的图片广告,可以张贴产品和服务…...
java常见面试题:什么是异常?Java中的异常有哪些分类?
异常是一个汉语词语,读音为y chng,指非正常的;不同于平常的;非常。在Java中,异常(Exception)是程序在运行过程中出现的不正常情况,例如除以零、数组越界等。异常分为两大类ÿ…...

类的加载顺序问题-demo展示
面试的的时候经常会被问到包含静态代码块、实例代码块和构造器等代码结构的加载顺序问题,下面借用一个面试题,回顾一下类的代码加载顺序。 public class AooTest {public static void main(String[] args) {AooTest.f1();}static AooTest test1 new Ao…...

[蓝桥杯2020国赛]答疑
答疑 题目描述 有 n 位同学同时找老师答疑。每位同学都预先估计了自己答疑的时间。 老师可以安排答疑的顺序,同学们要依次进入老师办公室答疑。 一位同学答疑的过程如下: 首先进入办公室,编号为 i 的同学需要 si 毫秒的时间。然后同学问…...

【AIGC表情prompt】提示词练习技巧
表情类提示词练习技巧 医疗机器人,男人笑脸景深,数据,座标,12k,c4d渲染,高分辨率,,暖色调,高清对比 医疗机器人,男人微笑,景深,数据,座标…...

SpringBoot项目的三种创建方式
手动创建方式: ①:新建maven项目 ②:引入依赖 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.10.RELEASE</version>&l…...

【docker实战】01 Linux上docker的安装
Docker CE是免费的Docker产品的新名称,Docker CE包含了完整的Docker平台,非常适合开发人员和运维团队构建容器APP。 Ubuntu 14.04/16.04(使用 apt-get 进行安装) # step 1: 安装必要的一些系统工具 sudo apt-get update sudo ap…...

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK设置相机的图像剪切(ROI)功能(C#)
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK设置相机的图像剪切(ROI)功能(C#) Baumer工业相机Baumer工业相机的图像剪切(ROI)功能的技术背景CameraExplorer如何使用图像剪切(ROI)…...

软件测试之安全测试
一、测试范围 管理系统:url、登录框、搜索框、输入框、文件上传、文件下载 客户端:搜索框、输入框、文件上传、系统功能 二、测试点 密码安全 XSS注入 SQL注入 操作越权 上传安全 下载安全 三、工具 fiddler sqlmap 同时,在这我为…...
【华为OD机试真题2023CD卷 JAVAJS】会议室占用时间
华为OD2023(C&D卷)机试题库全覆盖,刷题指南点这里 会议室占用时间 时间限制:1s 空间限制:256MB 限定语言:不限 题目描述: 现有若干个会议,所有会议共享一个会议室,用数组表示每个会议的开始时间和结束时间,格式:[[会议1开始时间,会议1结束时间], [会议2开始时间…...
UR5机器人的旋转向量转换到四元数,再从四元数转换到旋转向量python代码
能够通过接口获得UR5机器人末端在基坐标系下的位姿,姿态表示方法是用旋转向量表示的,一般会涉及到四元数和旋转向量之间的转换。 1、方法一 import numpy as np from pytransform3d import rotations as pr import copy # 输入旋转向量 quaternion2 n…...
MD5--加密原理及代码示例(C#)
1.MD5详述 MD5(Message-Digest Algorithm 5)是一种哈希算法,用于将任意长度的信息映射为固定长度的哈希值(128位)。MD5算法具有以下特点: 哈希值长度固定:MD5算法将任意长度的输入数据计算为128…...

理解 RPC 与 Protobuf:完整指南
一、Protobuf 数据格式简析 Protobuf 是什么? 在数据密集型应用领域,Google 开发的 Protobuf 作为一种高效数据编码方式而广受欢迎。它胜任于 JSON 及 XML 对比,不仅在体积和速度上表现出色,而且其结构化方式优化了网络传输中的…...

成为一名合格的前端架构师,前端知识技能与项目实战教学
一、教程描述 本套前端架构师教程,大小35.94G,共有672个文件。 二、教程目录 01.node介绍和环境配置(共6课时) 02.ES6语法(共5课时) 03.node基础(共29课时) 04.Express框架&am…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...

Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...

vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...

蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...

HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...

HDFS分布式存储 zookeeper
hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架,允许使用简单的变成模型跨计算机对大型集群进行分布式处理(1.海量的数据存储 2.海量数据的计算)Hadoop核心组件 hdfs(分布式文件存储系统)&a…...