RS485电工详解

news2025/2/24 3:43:19

串口数据帧我们学过,但到RS485是不是就卡壳了?

空闲状态:AB线悬浮在2.3V的样子。GND是0V,+5V是4.75v

工作时,AB线在2.3v上做逻辑01(-2v,+2v)跳变。

这图是不是还不太好理解?我把B线下移3伏,给大家看看。

黄色是A相,绿色是B相。值是0x71

电平逻辑正好相反。永远对称。

RS-485的电气特性:逻辑“1”以两线间的电压差为  正(2~6)V 表示;逻辑“0”以两线间的电压差为    负(2~6)V 表示。

我们来看下:

逻辑正: A(2.3v+2v)约4v      B(2.3v-2v)约0v    差值   正4V

逻辑负: A(2.3v-2v)约0v      B(2.3v+2v)约4v    差值   负4V

所以 B相 是电平参考线。

//===========================

电压的问题讲完了,就该讲时序了。 

我们先把示波器的GND接到B相上。

 这2图是同一个波形,只是GND参考线换成了B相。

空闲时:AB都是2.3V相当于没电压,是0伏。逻辑正负切换时,波形振幅放大了。一个格子是2v,逻辑1正3.5v,逻辑0负3.5v

RS-485的电气特性:逻辑“1”以两线间的电压差为  正(2~6)V 表示;逻辑“0”以两线间的电压差为    负(2~6)V 表示。

我们来看下:

逻辑正: A(2.3v+2v)约4v      B(2.3v-2v)约0v    差值   正4V

逻辑负: A(2.3v-2v)约0v      B(2.3v+2v)约4v    差值   负4V

B相 是电平参考线。这样,逻辑就对上了。起始位要保持一个低电平,0伏怎么保持低电平呢?所以要先拉高4v,再拉低 (负4v)并保持一位长度

我们来看下数据帧:

n长度高电平,一个起始位低电平,8个数据位电平,一个校验位,一个停止位。

所以,空闲是n长的0v。

一个起始位低电平:为了这个条件,所以至少拉高1个位的高电平再保持一个位的低电平。

8个数据位电平,D0D1D2D3D4D5D6D7  我发的是0xF1

这个是(96N81)的时序图,你会发现,没有校验位的电平宽度,因为你是无校验,所以校验电平宽度就没有。

为了看校验位,我发的值要改成0x71(0111 0001),串口(96o81)奇校验

 为了看校验位,我发的值要改成0x71(0111 0001),串口(96E81)偶校验

 0x71(0111 0001)括号里的1数量,加 校验位电平值,是偶数就是偶校验   4+0等于4是偶数

好,下面看个无校验的(96N81) 

可以看到,校验位的电平长度没了。 

 校验位,实际还可以强制:一直为1,或者一直为0;

注意:串口刚打开后,发送的第2帧有延迟,之后会没这个问题。

打开串口,连续发送3次字节,看下时序图

 我也不明白,为什么刚打开串口后,发送的第2帧会延迟。之后再连续发送就不会再延迟。可能是C#底层类库的问题。

接收:出现数据帧过短字节,可以用 com.ReceivedBytesThreshold = 1;// 单帧最低字节数

com.ReceivedBytesThreshold = 5;// 单帧最低字节数

设置5后,间歇发送的字节必须达到5字节,才能触发串口接收事件。

发送部分:

虽然是连续发单字节,实际代码有延迟。还是要用示波器,逻辑分析仪,监视

com.Write(by, 0, 1) ;

 

上位机上也能明显看出第3帧有延迟,我精确到毫秒4位。电脑还是不如单片机那样精准控制时间,实时性太差了。

txshow(by, DateTime.Now.ToString("ss's'ffffff':'"));




  void txshow(byte[] bs, string tim)//日志
        {
            string num = string.Empty;
            foreach (var item in bs)
            {
                num += item.ToString("X2") + " ";
            }

            listBox2.Items.Insert(0, tim + num);
            //if (this.InvokeRequired)
            //{
            //    this.Invoke(new Action(
            //        () => { listBox2.Items.Insert(0, tim + num); }
            //    ));
            //}
            //else
            //{
            //    listBox2.Items.Insert(0, tim + num);
            //}

        }

数据包发送才可以实现 连续字节发送

 private void button9_Click(object sender, EventArgs e)
        {
            com.Write(new byte[3] { 0x30, 0x31, 0x32 }, 0, 3);
        }

这3字节没出现等待情况。 

总之,电脑的时间实时性比较差,频繁读写,会造成卡顿。可能线程的问题。会出现字节帧过短,过长,空字节触发串口接收事件。

要么发送后,等待固定的时间,再去读取接收数据帧。或者判断载波检测,空字节可以再等待一会,再去读字节。

以下是我对串口的简单调试,写的C#,可以参考下

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace portDemo
{
    public partial class Form1 : Form
    {
        SerialPort com;

        static int wait=0;

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            com = new SerialPort();
            com.PortName=comboBox1.Text;
            com.BaudRate=int.Parse(comboBox2.Text );// 96
            switch (comboBox3.Text)// n
            {
                case "无": com.Parity = Parity.None; break;
                case "奇": com.Parity = Parity.Odd; break;
                case "偶": com.Parity = Parity.Even; break;
                case "高": com.Parity = Parity.Mark; break;
                case "低": com.Parity = Parity.Space; break;
               
                default:
                    break;
            }
            com.DataBits=int.Parse(comboBox4.Text);
            switch (comboBox5.Text)// n
            {
                case "1": com.StopBits = StopBits.One; break;
                case "1.5": com.StopBits = StopBits.OnePointFive; break;
                case "2": com.StopBits = StopBits.Two; break;
                
                default:
                    break;
            }

            com.ReceivedBytesThreshold = 1;// 单帧最低字节数
            com.ReadTimeout = 5;


            com.DataReceived += Com_DataReceived;//接收事件

            com.Open();
            button1.BackColor = Color.Green;
        }

        private void Com_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            string tim = DateTime.Now.ToString("ss's'ffffff ':'"); // 毫秒
            
            byte[ ] rxbuff= new byte[com.BytesToRead];
            com.Read(rxbuff, 0, rxbuff.Length );


            rzshow(rxbuff ,tim);

            
        }

        private void button2_Click(object sender, EventArgs e)
        {
            com?.Close();
            com = null;
            button1.BackColor = Color.Gray;
        }

        private void button3_Click(object sender, EventArgs e)
        {
            string tim = DateTime.Now.ToString("ss's'fffff ':'"); // 毫秒
            byte by = Convert.ToByte(textBox1.Text, 16);
            com.Write(new byte[1]{ by },0,1);
        }

        void rzshow(byte[] bs,string tim)//日志
        {
            string num = string.Empty;
            foreach (var item in bs)
            {
                num += item.ToString("X2")+" ";
            }
            
            if(this.InvokeRequired)
            {
                this.Invoke(new Action(
                    ()=> { listBox1.Items.Insert(0, tim +num); }
                ));
            }
            else
            {
                listBox1.Items.Insert(0, tim + num);
            }
            
        }

        private void button4_Click(object sender, EventArgs e)
        {// ↑
            com.ReadTimeout+=1;
            label7.Text= com.ReadTimeout.ToString();
        }

        private void button5_Click(object sender, EventArgs e)
        {
            com.ReadTimeout -= 1;
            label7.Text = com.ReadTimeout.ToString();
        }

        private async void button6_Click(object sender, EventArgs e)
        {//3tx
            listBox2.Items.Clear();
            label8.Text = wait.ToString();
            byte[] by = new byte[1] { Convert.ToByte(textBox1.Text, 16) };
            txshow(by, DateTime.Now.ToString("ss's'ffffff':'"));
            com.Write(by, 0, 1) ;
            
            await Task.Delay(wait);
            txshow(by, DateTime.Now.ToString("ss's'ffffff':'"));
            com.Write(by, 0, 1);
            
            await Task.Delay(wait);
            txshow(by, DateTime.Now.ToString("ss's'ffffff':'"));
            com.Write(by, 0, 1);
            
            await Task.Delay(wait);
        }

        void txshow(byte[] bs, string tim)//日志
        {
            string num = string.Empty;
            foreach (var item in bs)
            {
                num += item.ToString("X2") + " ";
            }

            listBox2.Items.Insert(0, tim + num);
            //if (this.InvokeRequired)
            //{
            //    this.Invoke(new Action(
            //        () => { listBox2.Items.Insert(0, tim + num); }
            //    ));
            //}
            //else
            //{
            //    listBox2.Items.Insert(0, tim + num);
            //}

        }

        private void button7_Click(object sender, EventArgs e)
        {// ↑
            wait += 1;
            label8.Text = wait.ToString();

        }

        private void button8_Click(object sender, EventArgs e)
        {
            wait -= 1;
            label8.Text = wait.ToString();
        }

        private void button9_Click(object sender, EventArgs e)
        {
            com.Write(new byte[3] { 0x30, 0x31, 0x32 }, 0, 3);
        }
    }
}

 

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

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

相关文章

Spring事务数据库连接池流程原理详细分析

文章目录 文章目录文章目录[toc]▌Spring事务管理环境搭建标准配置声明式事务总结▌SqlSessionFactoryXML 中构建 SqlSessionFactory获得 SqlSession 的实例代码实现▌作用域(Scope)和生命周期SqlSessionFactoryBuilder(构造器)Sq…

Android App开发中OpenGL三维投影的讲解及实现(附源码和演示 简单易懂)

运行有问题或需要源码请点赞关注收藏后评论区留言~~~ 一、三维投影 OpenGL,定义了跨语言跨平台的图形程序接口,对于Android开发者来说,OpenGL就是用来绘制三维图形的技术手段。当然OpenGL并不仅限于展示静止的三维图形,也能用来播…

【0基础百日刷题】洛谷刷题知识拾遗

百日刷题一.洛谷刷题得1.P1420差分数组2.P2669数列求和3.P1307数字反转4.P5725三角形5.P1980计数问题6.P1217回文质数刷题得意义: 有时候会发现一个简单的题目总是通不过测试,调试一次 就能找出一处bug。这都是我们编程时对逻辑的思考不充分而导致的失误…

听说,清华毕业分享出Redis实战视频及文档,共2.3G

前言 首先我们先来看一下redis的概念: Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010…

【App自动化测试】(三)使用Appium进行自动化用例录制

目录1. Appium Inspctor 功能2. Appium inspector 页面结构3. 使用Appium Inspctor 进行用例录制3.1 获取 app 的信息3.2 配置待测应用3.3 使用Appium Inspector进行自动化脚本录制3.3.1 操作步骤3.3.2 自动化测试用例结构分析3.3.2.1 Appium Inspector生成用例脚本3.3.2.2 对A…

数据结构-难点突破(C++实现并查集+路径优化,详解哈夫曼编码树)

文章目录1. 并查集2. 哈夫曼编码树1. 并查集 并查集是一个多棵树的集合(森林)。 并查集由多个集合构成,每一个集合就是一颗树。 并:合并多个集合。查:判断两个值是否再一个集合中。 每棵树存在数组中,使…

js 中的 Event Loop 以及 宏任务 与 微任务

目录前言1、JS 的 执行引擎 与 执行环境2、js 是单线程的一、事件循环(Event Loop)二、任务队列三、宏任务 与 微任务1、宏任务2、微任务3、宏任务与微任务的运行机制四、Event Loop 实例案例一案例二前言 1、JS 的 执行引擎 与 执行环境 简单来说&…

SpringCloud微服务(八)——OpenFeign服务调用

OpenFeign服务调用 SpringCloud github官网:https://github.com/spring-cloud/spring-cloud-openfeign Feign是一个声明式的Web Service客户端。它的出现使开发Web Service客户端变得很简单。使用Feign只需要创建一个接口加上对应的注解,比如&#xf…

基于java+springboot+mybatis+vue+elementui的人职匹配推荐系统

项目介绍 随着科学技术的飞速发展,各行各业都在努力与现代先进技术接轨,通过科技手段提高自身的优势,对于人职匹配推荐系统当然也不能排除在外,随着网络技术的不断成熟,带动了人职匹配推荐系统,它彻底改变…

分享一下前几个月我做的超炫的登录页面

先给大家看看登录页面的效果演示 这个登录页面分为三个部分(页面切换:连续按五次V,大小写都可以) 第一个(最初的鱼儿游动页面) 登录、切换页面、和鱼儿游动这个页面的代码就不放在这里了,这个虽…

RabbitMQ 入门案例项目

写在前面 本文不作消息队列的实现原理、异步处理优劣、rabbitmq安装说明、消息工作模式等内容分析,只讲述rabbitmq实际开发中的步骤说明,帮助同学快速上手体验消息队列的使用。 本文使用SpringAMQP,并非rabbitmq官方文档上的原生http请求连…

Jupyter notebook在超算平台上使用的详细教程

Jupyter Notebook 的本质是一个 Web 应用程序,便于创建和共享文学化程序文档,支持实时代码,数学方程,可视化和 markdown。 用途包括:数据清理和转换,数值模拟,统计建模,机器学习等等…

LeetCode 数据结构与算法:最大子数组和

打开我的题库,调为简单难度。 计算最大子数,直接给我难住。 报错铺满屏幕,凝望没有思路。 缝缝补补做出,击败零个用户。 翻阅评论找补,令我勃然大怒。 打开思维第一步,编写代码求数组, …

报错解决:Process finished with exit code -1073741819 (0xC0000005)

简单记录一下程序异常终止,抛出 Process finished with exit code -1073741819 (0xC0000005) 的解决方法。 一、程序中文件位置错误/缺少文件 位置错误1:如果使用相对路径的话,推荐换成绝对路径进行排查。位置错误2:如果使用了o…

CAN总线协议测试拓扑图

记录测试CAN总线协议, CAN总线目前主要应用在汽车。 记录在PC使用USB-CAN连接测试

Talk预告 | Salesforce AI研究院研究科学家徐嘉诚:文本生成中的结构化解码

本期为TechBeat人工智能社区第457期线上Talk! 北京时间11月23日(周三)20:00,Salesforce AI研究院研究科学家——徐嘉诚的Talk将准时在TechBeat人工智能社区开播! 他与大家分享的主题是: “文本生成中的结构化解码”,届时将详细讲解…

学会用数据分析汇报工作,升职加薪指日可待

你是否每天的八小时工作时长,分成八瓣用,却仍被领导安排众多工作?明明做了很多事,领导依旧认为工作量不饱和?这样的现象在职场中早已司空见惯,不足为奇了,但是究其原因是什么呢?工作…

Android App网络通信中通过runOnUiThread快速操纵界面以及利用线程池Executor调度异步任务实战(附源码 简单易懂)

运行有问题或需要源码请点赞关注收藏后评论区留言私信~~~ 一、通过runOnUiThread快速操纵界面 因为Android规定分线程不能够直接操纵界面,所以它设计了处理程序工具,由处理程序负责在主线程和分线程之间传递数据,如果分线程想刷新界面&#…

精心整理16条MySQL使用规范,减少80%问题

1. 禁止使用select * 阿里开发规范中,有这么一句话: **select *** 会查询表中所有字段,如果表中的字段有更改,必须修改SQL语句,不然就会执行错误。 查询出非必要的字段,徒增磁盘IO和网络延迟。 2. 用小表…

小学生python游戏编程arcade----敌人精灵上方显示方框及子弹显示问题

小学生python游戏编程arcade----敌人精灵上方显示方框及子弹显示问题前言1、敌人精灵上方显示方框1.1 修改enemy_tank类1.2 引用1.3 效果图2、调整方法2.1 类方法2.2 类的引用2.3 效果图2.4 大小位置调整后3、子弹过线自动消失3.1 子弹的更新中3.2 原因查到,把以下代…