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的延时就会导致数据错乱。

总结

  1. 严谨细致。在问题发生时,我也去量过主控和和MCU 485控制管脚的电平,只看到了两者是反向的,但是并没有放大去看最后一段电平的细节。导致遗漏了解决问题的线索。
  2. 一切问题发生都是有原因的。偶现问题并不好排查,但是我们可以尝试制作偶现问题发生的条件,看有没有可能成为必现问题。如果不能必现,可尝试通过脚本去不断运行在问题发生的场景,使其出现的概率提升。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/594202.shtml

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

相关文章

基于BP神经网络的模型建立,然后用多目标优化进行寻优

目录 背影 遗传算法的原理及步骤 基本定义 编码方式 适应度函数 运算过程 代码 结果分析 完整代码下载: 基于BP神经网络的模型建立,然后用多目标优化进行寻优(代码完整,数据齐全)资源-CSDN文库 https://download.csdn.net/download/abc991835105/88689232 背影 基于BP神…

Unity3D 锁帧与垂直同步的不同处详解

前言 Unity3D是一款强大的游戏开发引擎,而锁帧与垂直同步是其中两个重要的概念。本文将详细解释锁帧与垂直同步的不同之处,并给出相关的技术详解和代码实现。 对惹,这里有一个游戏开发交流小组,希望大家可以点击进来一起交流一下…

什么是聚合支付,又能带来哪些好处?

随着科技的飞速发展,人们的支付方式也在不断地发生变革。从最初的现金支付、银行卡支付,到现在的移动支付、扫码支付等,支付方式已经变得越来越便捷。聚合支付作为一种新型的支付方式,也在逐渐改变着人们的生活方式。那么&#xf…

CMake入门教程【核心篇】添加子目录(add_subdirectory)

文章目录 1.概述2.添加子目录3.指定二进制目录4.排除子目录5.使用别名6.传递变量7.检查子目录是否存在 1.概述 add_subdirectory是 CMake 中的一个命令,用于向当前项目添加一个子目录。它的语法如下: #mermaid-svg-9zKJ3AvoVRln9hon {font-family:"…

本科生自学PYTHON路线

博主为本科生,想要自学python,期待得到意见 基础知识:首先学习Python的基本语法和语法规则。学习Python的基本数据类型(数字、字符串、列表、元组、字典等),掌握基本的控制流语句(条件语句、循环语句)和函数…

金和OA jc6 ntko-upload 任意文件上传漏洞

产品简介 金和网络是专业信息化服务商,为城市监管部门提供了互联网监管解决方案,为企事业单位提供组织协同OA系统升开发平台,电子政务一体化平台智慧电商平合等服务 漏洞概述 金和OA jc6系统ntkoUpload接口处存在任意文件上传漏洞&#xf…

每日一练:LeeCode-503. 下一个更大元素 II (中)【单调栈】

本文是力扣LeeCode-503. 下一个更大元素 II 学习与理解过程,本文仅做学习之用,对本题感兴趣的小伙伴可以出门左拐LeeCode。 给定一个循环数组 nums ( nums[nums.length - 1] 的下一个元素是 nums[0] ),返回 nums 中每个…

宏预处理器的非直译解释备忘

宏 非直译解释: 计算机科学里的宏指的是,在未执行程序运算前,预先把数据存入内存生成一张存有数据的表格结构体,以方便汇编机器指令读取修改表格地址中的数据参数。 macro n.宏指令; adj.巨大的;极厚的;特别突出的…

c++_运算符重载(时钟加减)

介绍 本文主要介绍 减号( - )、加号( )、加等()运算符重载并复现了时钟运行方式 源码 #include<iostream>using namespace std;class Time { public://加号计算函数void t_add(int& temp, const int& Right, bool& b){//判断时间是否大于 60if ((temp Rig…

c语言-浮点型数据在内存中的存储

目录 前言一、浮点数存储例子二、浮点数在内存的存储格式2.1 32位浮点数存储格式2.2 64位浮点数存储格式 三、IEEE 754对有效数字M和指数E的规定3.1 对存储有效数字M的规定3.2 对存储指数E的规定3.2.1 E在32位浮点数的存储格式3.2.2 E在64位浮点数的存储格式 3.3 对读取有效数M…

pythonnumpy六:高级功能:数组排序、数组连接、数组拆分等。

numpy是一个强大的Python库&#xff0c;提供了丰富的数组操作功能。下面我会详细介绍numpy中的数组排序、数组连接和数组拆分等功能。 1.数组排序&#xff1a; 使用np.sort()函数可以对数组进行升序排序。它返回一个新的已排序的数组。若要在原始数组上进行排序&#xff0c;可…

谷歌Gemini模型,碾压GPT-4!

谷歌Gemini 1.0革新&#xff0c;推出Gemini Ultra、Gemini Pro和Gemini Nano模型。Gemini Ultra强大但慢&#xff0c;Gemini Pro通用&#xff0c;Gemini Nano高效。Gemini模型在多领域与ChatGPT竞争&#xff0c;尤其Gemini Pro已应用于Bard。Gemini模型预计将在2024年通过Bard …

NLP论文阅读记录 - 2021 | SimCLS:抽象概括对比学习的简单框架

文章目录 前言0、论文摘要一、Introduction1.1目标问题1.2相关的尝试1.3本文贡献 二.相关工作2.1优势 三.本文方法——抽象概括的对比学习框架3.1 第一阶段&#xff1a;候选生成3.2 第二阶段&#xff1a;无参考评估3.3对比训练 四 实验效果4.1数据集4.2 对比模型4.3实施细节4.4…

【论文阅读】AADiff: Audio-Aligned Video Synthesis with Text-to-Image Diffusion

AADiff:基于文本到图像扩散的音频对齐视频合成。 code&#xff1a;没开源 paper&#xff1a;[2305.04001] AADiff: Audio-Aligned Video Synthesis with Text-to-Image Diffusion (arxiv.org) 一种新的T2V框架&#xff0c;额外使用音频信号来控制时间动态&#xff0c;使现成的…

MySQL中的六种日志你都懂么?不懂!那就必须看看

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

docker 安装可视化工具 Portainer 以及 汉化

安装portainer是最新版本&#xff0c;汉化指定版本2.9.1 。如果要安装汉化版&#xff0c;可直接跳转步骤四 一、拉去镜像 安装网址&#xff1a;Install Portainer BE with Docker on Linux - Portainer Documentation docker pull portainer/portainer二、根据portainer镜像创建…

常用rtmp、m3u8、flv、mp4直播流在线测试地址

✍️作者简介&#xff1a;小北编程&#xff08;专注于HarmonyOS、Android、Java、Web、TCP/IP等技术方向&#xff09; &#x1f433;博客主页&#xff1a; 开源中国、稀土掘金、51cto博客、博客园、知乎、简书、慕课网、CSDN &#x1f514;如果文章对您有一定的帮助请&#x1f…

CMake入门教程【基础篇】CMake+Linux gcc构建C++项目

文章目录 1.概述2.GCC与CMake介绍3.安装CMake和GCC4.代码示例 1.概述 在Linux环境下&#xff0c;使用CMake结合GCC&#xff08;GNU Compiler Collection&#xff09;进行项目构建是一种常见且高效的方法。CMake作为一个跨平台的构建系统&#xff0c;可以生成适用于不同编译器的…

面试经典150题(55-58)

leetcode 150道题 计划花两个月时候刷完&#xff0c;今天&#xff08;第二十四天&#xff09;完成了4道(55-58)150&#xff1a; 55.&#xff08;19. 删除链表的倒数第 N 个结点&#xff09;题目描述&#xff1a; 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff…

渗透第四天

常用的对称加密算法有&#xff1a;DES、3DES、RC2、RC4、AES 常用的非对称加密算法有&#xff1a;RSA、DSA、ECC 使用单向散列函数的加密算法&#xff08;摘要算法&#xff09;&#xff1a;MD5、SHA 密码存储加密 md5 32位或者16位 0-9 a-f 所组成的字符串 不可…