C#串口通信SeriPort 电表DLT645 RS234/RS485
难受,三个多月前有一个电表电量监控的项目。做完了就没再管了。今天有需求需要改一些地方,但是....我想不起来干了啥,怎么干的啦。真的完全忘了.....项目名称叫啥都忘了.找了半天
不知道有没有和我一样的贵人程序员......
首先回顾一下大致的网络结构如下,每个电表通过USB的总线,连接到PC上,可能302车间的所有电表,划分为组1,连接到C0M0串口,303车间,划分位组2,连接到COM1串口

首先是串口通信的一些基础知识https://blog.csdn.net/xiaobaixiongxiong/article/details/83998436
大致来说,电表是通过串口,经一个USB转串口来连接到电脑的,这里我一直不大明白,明明是通过USB,为啥叫串口通讯那。其实,早一点的电脑,笔记本,都是有一个9针的真正的串口插座的。后来笔记本越来越薄,那个插口基本都没了,换成了
现在我们看到的通过USB转串口,但是串口通信的基本概念仍然是那一套
首先是串口通过高低电平来传输0和1的比特流的理论基础
起始位,数据位,奇偶校验位,停止位,波特率。这些,为一条线(其实表示高低电平可以是1条线如RS232,也可能是多条线如RS485)通过高低电平变化来传输数据,提供理论基础。

波特率其实就是每秒钟,电平的变化频率。比如波特率1200.那么每一个0(低电平)1(高电平)持续的时间是1/1200秒。如果波特率是9600.那么持续时间是1/9600.那么 波特率越高,每秒能传输的数据就越多。
在这个基础上,诞生了一些不同的实现,形成了常见的标准 RS232 RS485等。
我个人的不是很准确的理解,理论基础都是这一套,都是用高低电平来表示0和1达到传输比特流的目的
但是实现有所区别,
比如RS232的高低电平,使用3-15v有效电平,使用一根线,有电压表示1,无电压表示0,使用一根线就能完成传输0和1的比特流
而RS485使用差分电平。它的高低电平需要两根线的电压差值来表示,这样的话,虽然都是通过高低电平来传输0和1,但是实现方式是不一样的,特性也不一样。比如RS485的传输距离更长,抗干扰性更好等
(或者将来也可能诞生了一种新的标准RS200,使用100V-200V来表示高低电平)。这样是否对RS232和RS485到底是啥有更明白一点的理解
那么串口通信的基础,我们了解了大概,其实这部分都是别人给我们做好的啦,不需要自己去实现。
真正到了与我们使用息息相关的部分,则是更上层的电表的通讯协议 DLT645-1997 DLT645-2007,通信协议可以参考https://blog.csdn.net/u013184273/article/details/98083050
如果说RS232,RS485为我们提供了与电表通讯的基础,那么DLT645-1997 DLT645-2007则是明确了与电表通讯的交互方式,就像规定我给你发 HOW are you , 你给我回复 fine and you
这里其实没有啥好讲的,总的来讲就是数据格式,按下图的数据格式,拼装出一个byte[] 往串口写数据,那么电表就会按照我们的请求,返回对应的响应结果。

返回数据:68 78 56 34 12 00 00 68 91 08 33 33 34 33 A4 56 79 38 F5 16
注意,这里面没有前导字节FE,并不代表所有的电表厂家都没有,而且还是不固定的,所以一定小心写程序,因为不同厂家电表回的前导字节个数不一样。
其中:78 56 34 12 00 00 是表地址,传输次序是低在前,高在后,而且是十六进制。
91-为从返回命令
08-共8个字节
33 33 34 33-数据块,可以理解成寄存器地址,表示读电表总电流。
A4 56 79 38-具体数据,分析时,应减33,所以为:
A4-33=71
56-33=23
79-33=46
38-33=5
实际的电表数为:54623.71度
下面我以C# 为例,来讲讲编程中的一些坑
1 对于返回的数据,FE FE FE FE这四个前导字节可能有,也可能没有,也可能1个,2个 3个 。。。。。。就是说看电表厂家的心情。所以我们编码要对他做特殊处理
2 C# 的SerialPort 串口,比较坑,怎么个坑法那。
我们以同步读写为列。假设我发送 12345678 ,返回 abcdefgh。那我SerialPort.write(12345678)后,去读SerialPort.read(out result) 按我们的理解,result 应该是 abcdefgh了把?
事实上,它可能是abcdefgh,也可能是abcde 也可能是abc . 就是说,我们read一次,它不一定完全返回,如果只返回了一部分,那么我们还要再读,第一次返回abc ,第二次有可能返回剩下的defgh,也可能还是只返回部分def。
就是说write一次,我可能要读N次,而且N还不固定,才能接收到完整的数据。
而SerialPort 的异步读接口(其实就是回调函数),也是问题多多
SerialPort .ReceivedBytesThreshold =15; //表示接收到15 byte的数据后触发 SerialPort .DataReceived . 但其实有问题,接收到1个,两个,3个都有可能触发,就是说等15个接受完,可能会触发N次
SerialPort .DataReceived +=new System.IO.Ports.SerialDataReceivedEventHandler(spReceive_DataReceived);
可能这是C#封装串口的一些问题,不知道是我用的不对还是大家都是这样,有懂的人可以指教一下。
好在知道有这种问题,解决的方法并不难。可以参考这个博客https://www.cnblogs.com/royenhome/archive/2010/03/23/1692440.html
也可以像我这样,不是很严谨,仅供参考
/// <summary>
/// 暂时没考虑返回可能包含的FEFE前缀,1秒超时
/// </summary>
/// <param name="RetLength">完整返回帧的长度</param>
/// <param name="buffer"></param>
/// <returns></returns>
private int ReadCicle(int RetLength, ref byte[] buffer)
{
TimeSpan overtime = new TimeSpan(TimeSpan.TicksPerSecond);
DateTime dt = DateTime.Now;
int length = 0;
while (true)
{
try
{
length += mySerialPort.Read(buffer, length, buffer.Length - length);
}
catch (TimeoutException e)
{
//超时不处理
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
if (length >= RetLength || DateTime.Now - dt > overtime)
break;
} return length;
}
如果不想用SeriPort接口,nuget里面还是有好多第三方编写的串口类可用的,也可以尝试一下

C#串口通信SeriPort 电表DLT645 RS234/RS485的更多相关文章
- Python编程实现USB转RS485串口通信
---作者吴疆,未经允许,严禁转载,违权必究--- ---欢迎指正,需要源码和文件可站内私信联系--- -----------点击此处链接至博客园原文----------- 功能说明:Python编程 ...
- Java实现RS485串口通信,发送和接收数据进行解析
最近项目有一个空气检测仪,需要得到空气检测仪的实时数据,保存到数据库当中.根据了解得到,硬件是通过rs485进行串口通讯的,需要发送16进制命令给仪器,然后通过轮询来得到数据. 需要先要下载RXTX的 ...
- Java实现RS485串口通信
前言 前段时间赶项目的过程中,遇到一个调用RS485串口通信的需求,赶完项目因为楼主处理私事,没来得及完成文章的更新,现在终于可以整理一下当时的demo,记录下来. 首先说一下大概需求:这个项目是机器 ...
- C#串口介绍以及简单串口通信程序设计实现
C#串口介绍以及简单串口通信程序设计实现 周末,没事干,写个简单的串口通信工具,也算是本周末曾来过,废话不多,直接到主题 串口介绍 串行接口简称串口,也称串行通信接口或串行通讯接口(通常指COM接口) ...
- mfc 调用Windows的API函数实现同步异步串口通信(源码)
在工业控制中,工控机(一般都基于Windows平台)经常需要与智能仪表通过串口进行通信.串口通信方便易行,应用广泛. 一般情况下,工控机和各智能仪表通过RS485总线进行通信.RS485的通信方式是半 ...
- LabVIEW串口通信
Instrument I/O 利用LabVIEW内置的驱动程序库和具有工业标准的设备驱动软件,可对 GPIB(通用接口总线).Ethernet(以太网)接口.RS-232(标准串行接口总线)/RS-4 ...
- C#中的串口通信
关于串行接口 串行接口(Serial port)又称“串口”,主要用于串行式逐位数据传输.常见的有一般电脑应用的RS-232(使用 25 针或 9 针连接器)和工业电脑应用的半双工RS-485与全双工 ...
- ARM学习笔记15——串口通信基本原理【转】
计算机串口基本理论 1.什么是串口? 2,什么是RS-232? 3,什么是RS-422? 4,什么是RS-485? 5,什么是握手? 1,什么是串口? 串口是计算机上一种非常通用的设备通信的协议(不要 ...
- 【GMT43智能液晶模块】例程二:串口通信实验
实验原理: GMT43智能液晶模块的串口包括USB_UART(CH340),TTL,RS-232,RS-485/ RS-422等四部分,USB_UART部分通过CH340芯片与STM32F429的US ...
随机推荐
- C语言:fopen函数
在C语言中,操作文件之前必须先打开文件:所谓"打开文件",就是让程序和文件建立连接的过程.打开文件之后,程序可以得到文件的相关信息,例如大小.类型.权限.创建者.更新时间等.在后续 ...
- clickhouse分布式集群
一.环境准备: 主机 系统 应用 ip ckh-01 centos 8 jdk,zookeeper,clickhouse 192.168.205.190 ckh-02 centos 8 jdk,zoo ...
- Linux上生产环境源码方式安装配置postgresql12
1.Linux上源码方式安装postgresql12 01.准备操作系统环境 echo "192.168.1.61 tsepg61" >> /etc/hosts mou ...
- 禁用ipv6的两种方法
1 通过系统配置文件/etc/sysctl.conf 在sysctl.conf文件中添加行 # 禁用整个系统所有接口的IPv6 net.ipv6.conf.all.disable_ipv6 = 1 # ...
- 【动画消消乐】HTML+CSS 自定义加载动画:怦然心跳 066
前言 Hello!小伙伴! 非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出- 自我介绍 ଘ(੭ˊᵕˋ)੭ 昵称:海轰 标签:程序猿|C++选手|学生 简介:因C语言结识编程,随后转入计 ...
- MySQL检查与性能优化示例脚本
最近在玩python,为了熟悉一下python,写了个mysql的检查与性能优化建议的脚本. 虽然,真的只能算是一个半成残次品.也拿出来现眼一下. 不过对于初学者来说,还是有一定的参考价值的.比如说如 ...
- Django中ORM是啥?
ORM是啥是许多Django新手的苦恼. ORM中的"O"就是object,也就是我们说的对象:R指的是relations关系:M指的是mapping也就是映射.所以ORM是对象- ...
- Python脚本:批量将.doc文件转化为.docx文件
将.doc转换为.docx文件有几种常用的方法: Microsoft Word 和 WPS 自带.doc转换.docx功能,但只能一个文件一个文件转换,批量转换要会员 在线网页 Office-Conv ...
- jvm源码解读--02 Array<u1>* tags = MetadataFactory::new_writeable_array<u1>(loader_data, length, 0, CHECK_NULL); 函数引入的jvm内存分配解析
current路径: #0 Array<unsigned char>::operator new (size=8, loader_data=0x7fd4c802e868, length=8 ...
- 模版引擎RazorEngine简介
ASP.NET MVC的Razor想必大家都比较熟悉,这里介绍一个独立于ASP.NET的RazorEngine. RazorEngine是一个开源的项目,它的基础就是ASP.NET MVC的Razor ...