获取程序从串口发送的数据(软件实现)

获取程序从串口发送的数据(软件实现),第1张

或者用一条交叉串口线,连接两个串口,一个串口供被监控软件用,一个串口供串口助手用,串口助手可以接收发送过来的信息,串口助手可以使用格西烽火串口助手、SSCOM等软件。

根据200smart的通信协议和指令集。发送指令之后,200smart会回复一个响应报文,需要在串口调试工具上正确接收并打印出来,根据200smart的通信协议和指令集,可以解析出响应报文中的具体数据内容。报文解析不仅需要对200smart的协议和通信规则有深入了解,还需要对串口通信和相应的软件开发领域有足够的技术实力和经验。

使用SystemIOPortSerialPort类实现串口通信

SystemIOPortSerialPort类介绍

SystemIOPortSerialPort是NET Framework提供的 *** 作串行端口的类,里面提供了一些方法、属性和和事件供开发者调用 *** 作串口。

调用流程

1 直接调用SerialPort的静态方法GetPortNames()获取当前计算机的串行端口名称数组

2根据串口名称,初始化SerialPort对象,设置参数,调用Open()方法打开串口

3调用Write()方法发送数据

4注册接收数据的监听,获取数据(或者另起线程循环读取接收数据,本文使用注册监听方式接收数据)

具体代码实现

using System;  

using SystemIOPorts;  

using SystemText;

namespace PortControlDemo  

{

public class PortControlHelper

{

#region 字段/属性/委托

/// <summary>

/// 串行端口对象

/// </summary>

private SerialPort sp;

/// <summary>

/// 串口接收数据委托

/// </summary>

public delegate void ComReceiveDataHandler(string data);

public ComReceiveDataHandler OnComReceiveDataHandler = null;

/// <summary>

/// 端口名称数组

/// </summary>

public string[] PortNameArr { get; set; }

/// <summary>

/// 串口通信开启状态

/// </summary>

public bool PortState { get; set; } = false;

/// <summary>

/// 编码类型

/// </summary>

public Encoding EncodingType { get; set; } = EncodingASCII;

#endregion

#region 方法

public PortControlHelper()

{

PortNameArr = SerialPortGetPortNames();

sp = new SerialPort();

spDataReceived += new SerialDataReceivedEventHandler(DataReceived);

}

/// <summary>

/// 打开端口

/// </summary>

/// <param name="portName">端口名称</param>

/// <param name="boudRate">波特率</param>

/// <param name="dataBit">数据位</param>

/// <param name="stopBit">停止位</param>

/// <param name="timeout">超时时间</param>

public void OpenPort(string portName , int boudRate = 115200, int dataBit = 8, int stopBit = 1, int timeout = 5000)

{

try

{

spPortName = portName;

spBaudRate = boudRate;

spDataBits = dataBit;

spStopBits = (StopBits)stopBit;

spReadTimeout = timeout;

spOpen();

PortState = true;

}

catch (Exception e)

{

throw e;

}

}

/// <summary>

/// 关闭端口

/// </summary>

public void ClosePort()

{

try

{

spClose();

PortState = false;

}

catch (Exception e)

{

throw e;

}

}

/// <summary>

/// 发送数据

/// </summary>

/// <param name="sendData"></param>

public void SendData(string sendData)

{

try

{

spEncoding = EncodingType;

spWrite(sendData);

}

catch (Exception e)

{

throw e;

}

}

/// <summary>

/// 接收数据回调用

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void DataReceived(object sender, SerialDataReceivedEventArgs e)

{

byte[] buffer = new byte[spBytesToRead];

spRead(buffer, 0, bufferLength);

string str = EncodingTypeGetString(buffer);

if (OnComReceiveDataHandler != null)

{

OnComReceiveDataHandler(str);

}

}

#endregion

}  

}

View Code

三、编写Winform串口通信工具界面

界面预览

这类本地 *** 作,没有纯 web 解决方案

仅仅浏览器内页面脚本是无法做到的。

其核心是需要可跑在本地系统上的串口读取程序

不管 ActiveX、本地Node、或者本地其他应用程序都是如此

此外,还需要读取后可与浏览器页面交换数据的过程

所以,ActiveX (NAPAI)之类的浏览器 plugin 的确是比较直接的实现方式

而其他的方案,还需要本地启动服务(>

《串口硬件分类》 中已经说明了几种串口的类型,并在 《串口通信协议》 中说明了几种串口协议形式,这里就常用的串口协议进一步做一个说明。

工业上我们最常见的MODBUS RTU/ASCII通信协议是一种典型的起止型异步协议。之前在 《串口通信协议》 中已经解释过,起止型异步协议的特点是一个字符一个字符传输,并且传送一个字符总是以起始位开始,以停止位结束,字符之间没有固定的时间间隔要求。

这里需要强调的就是对于起止型通信协议,每一个字符的前面都有一位起始位(低电平,逻辑值0),字符本身有5~7位数据位组成,接着字符后面是一位校验位(也可以没有校验位),最后是一位,或一位半,或二位停止位,停止位后面是不定长度的空闲位。停止位和空闲位都规定为高电平(逻辑值),这样就保证起始位开始处一定有一个下跳沿。

这段话可能讲的有点理论了,对于我们工作中所常见的一个情况就是选择一个串口的校验位、数据位与停止位(这里没有起始位,因为起始位一般是默认的)。

对应到一个如上图的具体通信格式上,就是8个数据位,无校验位➕一位停止位。也就是我们说的8N1通信格式。当然,这里也会用到奇偶校验的变化,如西门子V90在使用串口通信控制时便要求为8O1(8位数据,偶校验,1位停止)。

不考虑串口的传输线数量,单以一根线来理解,即每传输(扫描)一个位,信号线上便给出一个(高或低)电平,即0或1。对于一个8N1格式的传输,每一次传输周期电平将扫描 1起始位+8数据位+1停止位 共10次电平变化,而扫描的频率就是串口的波特率。因此,虽然理论上说起止型协议依托于起止信号来判断数据的开始和结束,数据间没有固定的时间间隔要求,但在实际应用的过程中,对于一个既定的串口协议,通信站之间还是要保持相同的收发波特率的,否则扫描口将会对同样的电平变化做出可能完全不同的解读而导致通信失败。

综上,串口数据格式存在的意义是限定了串口传输数据的时间间隔、每次传输的数据量以及传输的起始和结束。它解决了“怎么传”的问题。

而串口通信报文,则是定义“传什么”的问题。

一个典型的modbus报文格式如下:

设备地址(8位)➕功能码(8位)➕起始 *** 作地址(16位)➕ *** 作数量(16位)➕CRC(16位)

我在工作中遇到一个比较多的就是关于数据格式与报文的概念混淆。如上述的一串格式报文,曾经被误解为与8N1的数据格式相矛盾,因为很明显,它完全就超出了我们所说的8位数据或10位数据的格式,那么怎么来解释这个问题呢?

澄清一个概念,数据格式中的8位,指的是8bit而不是8byte,对于上述modbus,当采取8N1格式通信时,串口将会以1byte(8位)为单位对报文进行包装并传输。比如最开始,串口芯片或发射端会将8位设备地址提出,然后对这个字节进行包装(加1位起始码,加1位停止码),形成一个10位的数据包,并将数据发送出去,然后继续提取功能码,进行同样的包装发送,以此类推,直至所有数据发送完毕。

因此,报文指的是数据字符,而数据格式,只是表明如何来包装这个数据字符。而我们通过各种软件所看到的,是经过计算机串口处理的数据,因而无法看到起始码停止码一类的信号,而仅有我们所需要的数据。

由此还可以推导出串口通信的效率。依旧以8N1格式来说,每个数据包的长度为10位,若选择波特率为9600,即每秒传输9600个位信号,那么8N1数据格式每传输1个数据包所需要的时间10/9600约为1ms,对于一串MODBUS典型报文,需要8个字节(根据指令决定),故信号发出时间为8ms。modbus规定从站必须在指定时间内反馈相应的数据方可认为通信成功,因而需要再加回报时间,如只 *** 作一个字节,那么往返数据时间应该在20ms左右,根据 *** 作的数据量通信时间会相应的加长。

因此,还可以了解到的是在多站轮询时需要根据数据量进行一次核算,若对实时性要求较高,则要考虑进行主站的独立处理。

经验之谈,欢迎指正。

以上就是关于获取程序从串口发送的数据(软件实现)全部的内容,包括:获取程序从串口发送的数据(软件实现)、用串口调试工具给200smart发送报文,怎样解析报文、c#如何实现串口通信读取数据等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/9731406.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-01
下一篇 2023-05-01

发表评论

登录后才能评论

评论列表(0条)

保存