背景

电厂有多组监控设备,需要在指定的设备上显示某些数据(其他设备对接过来的)。通信协议是modbus主从结构。

源码:

http://download.csdn.net/download/wolf12/8931267

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using System.Threading;
using System.Net.Sockets;
using System.Net; namespace ModsDataCtl
{
public partial class Form1 : Form
{
System.IO.Ports.SerialPort com; public Form1()
{
InitializeComponent(); } private void Form1_Load(object sender, EventArgs e)
{
Microsoft.VisualBasic.Devices.Computer pc = new Microsoft.VisualBasic.Devices.Computer(); foreach (string s in pc.Ports.SerialPortNames)//遍历本机所有串口
{
this.comboBox1.Items.Add(s);
} com = new System.IO.Ports.SerialPort();
} private void button1_Click(object sender, EventArgs e)
{
try
{
com.PortName = comboBox1.Items[comboBox1.SelectedIndex].ToString(); com.BaudRate = 9600;//波特率
com.Parity = Parity.None;//无奇偶校验位
com.StopBits = StopBits.One;//两个停止位
// com.Handshake = Handshake.RequestToSendXOnXOff;//控制协议
com.ReadTimeout = 2000;
com.WriteTimeout = 2000;
//com.ReceivedBytesThreshold = 4;//设置 DataReceived 事件发生前内部输入缓冲区中的字节数
// com.NewLine = "/r/n";
com.RtsEnable = true;
com.Open(); //打开串口 MessageBox.Show("串口打开成功");
}
catch
{
MessageBox.Show("串口已打开!");
}
}
/// <summary>
/// 监听com端口接收的报文
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
StringBuilder strBuilder = new StringBuilder();
while (com.BytesToRead > 0)
{
char ch = (char)com.ReadByte();
strBuilder.Append(ch);
}
strBuilder = new StringBuilder();
}
catch (Exception ex)
{
Console.Write(ex.Message.ToString());
}
}
private void button2_Click(object sender, EventArgs e)
{
//发送指令
byte[] sendbyte = new byte[8] { 01, 03, 0x0F, 0xA0, 00, 24, 46, 0xE7 }; com.Write(sendbyte, 0, sendbyte.Length);
MessageBox.Show("成功");
}
Thread thread;
private void button3_Click(object sender, EventArgs e)
{
com.DataReceived += new SerialDataReceivedEventHandler(com_DataReceived); MessageBox.Show("发送成功");
} private void button4_Click(object sender, EventArgs e)
{ com.Close(); //关闭串口
}
/// <summary>
/// 测试
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button5_Click(object sender, EventArgs e)
{
TcpClient tcp = new TcpClient();
UdpClient udp = new UdpClient();
udp.Connect("127.0.0.1", 7102);
// tcp.Connect("192.168.1.101", 7101);
// NetworkStream ns = ud
byte[] sendbyte = new byte[8] { 01, 03, 0x0F, 0xA0, 0x00, 0x24, 0x46, 0xE7 };
// byte[] sendbyte = new byte[8] { 01, 03, 10, 00, 00,02, 0xC0, 0xCB};
// 01 0F 00 01 00 04 01 00 03 56
// 01 06 00 01 00 17 98 04
//01 03 10 00 00 02 C0 CB
// ns.Write(sendbyte, 0, sendbyte.Length);
udp.Send(sendbyte, sendbyte.Length);
//System.Net.IPEndPoint ip = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 7101);
//var fff = udp.Receive(ref ip);
} #region CRC /// <summary>
/// 计算CRC-16
/// </summary>
/// <param name="data"></param>
/// <returns>高位在前</returns>
public byte[] CRC_16(string data)
{
if ((data.Length % 2) != 0) { throw new Exception("参数\"data\"长度不合法"); }
byte[] tmp = StrToByte(data); /*
1、预置16位寄存器为十六进制FFFF(即全为1)。称此寄存器为CRC寄存器;
2、把第一个8位数据与16位CRC寄存器的低位相异或,把结果放于CRC寄存器;
3、把寄存器的内容右移一位(朝低位),用0填补最高位,检查最低位;
4、如果最低位为0:重复第3步(再次移位); 如果最低位为1:CRC寄存器与多项式A001(1010 0000 0000 0001)进行异或;
5、重复步骤3和4,直到右移8次,这样整个8位数据全部进行了处理;
6、重复步骤2到步骤5,进行下一个8位数据的处理;
7、最后得到的CRC寄存器即为CRC码。
*/
UInt16 CRCREG = (UInt16)0xffff;
for (int i = 0; i < tmp.Length; i++)
{
CRCREG = (UInt16)(CRCREG ^ (UInt16)tmp[i]);//<< 8;
for (int j = 0; j < 8; j++)
{
UInt16 CRCtmp = (UInt16)(CRCREG & (UInt16)0x0001);
CRCREG = (UInt16)(CRCREG >> (UInt16)1);
if (CRCtmp == (UInt16)1)
{
CRCREG = (UInt16)(CRCREG ^ (UInt16)0xA001);
}
}
} string strtmp = CRCREG.ToString("X4");
byte[] retunBtye = new byte[8];
tmp.CopyTo(retunBtye, 0);
retunBtye[6] = StrToByte(strtmp.Substring(2, 2))[0];
retunBtye[7] = StrToByte(strtmp.Substring(0, 2))[0];
return retunBtye;
} public byte[] StrToByte(string data)
{
byte[] bt = new byte[data.Length / 2];
for (int i = 0; i < data.Length / 2; i++)
{
bt[i] = Convert.ToByte(data.Substring(i * 2, 2), 16);
}
return bt;
} #endregion private void timer1_Tick(object sender, EventArgs e)
{
//byte f = Convert.ToByte('\0');
//string dd = "wefef\0";
//byte[] fef = System.Text.Encoding.Default.GetBytes(dd); // MessageBox.Show(com.BytesToRead.ToString()); //01 03 48 01 F4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E3 59 /*
16:05:16.859 回复(no=077): 01 03 48 01 F4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E3 59
16:05:16.859 收到(no=008): 01 03 0F A0 00 24 46 E7------CRC正确
*
* 16:07:09.406 收到(no=008): 01 03 0F A0 00 24 46 E7------CRC正确
*/ /*
从机
16:07:26.484 回复(no=077): 01 03 48 01 F4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E3 59
16:07:26.484 收到(no=008): 01 03 0F A0 00 24 46 E7------CRC正确
*/
} void com_DataReceived(object sender, SerialDataReceivedEventArgs e)
{ this.Invoke(new Action(() =>
{ byte[] buffer = new byte[com.BytesToRead]; com.Read(buffer, 0, com.BytesToRead); string instr = ""; foreach (byte b in buffer)
{
instr += b.ToString("X2");
}
if (instr != "")
{
this.listBox1.Items.Add("收到:" + instr);
} // byte[] sendbyte = new byte[] { 0x01, 0x03, 0x48, 0x01, 0xF4, 0x00, 0x00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 0xE3, 0x59 };
byte[] sendbyte = new byte[] { 01,03,02,01,0xF4,0xB8,0x53}; com.Write(sendbyte, 0, sendbyte.Length); string wri = ""; foreach (byte b in sendbyte)
{
wri += b.ToString("X2");
}
if (wri != "")
{
this.listBox1.Items.Add("回复:" + wri);
} })); } }
}

C# MODBUS 通信的更多相关文章

  1. 物联网无线数传应用中的Modbus通信网关协议到底是什么?

    什么是物联网 通信Modbus网关 Modbus协议无线通信网关就是将一种Modbus协议帧转换为其他物联网无线数传协议帧. 比如将Modbus RTU的数据与Modbus TCP数据进行相互转换:也 ...

  2. PC和单片机通过MODBUS RTU通信

    最近研究了一下MODBUS通信,在STC12C5A60S2单片机上实现了MODBUS协议的部分功能,方便上位机从单片机系统上获取数据,比如由单片机获取的温度.湿度.或者控制信号的状态等.有了MODBU ...

  3. 【应用笔记】【AN001】VC#开发环境下基于以太网的4-20mA电流采集(基于modbus tcp 协议)

    版本:第一版 作者:毛鹏 杨帅 日期:20151108 简介 4-20mA电流环具有广泛的应用前景,在许多行业中都发挥着重要作用.本文主要介绍了以太网接口的4-20mA电流采集模块在VC#环境下进行温 ...

  4. 推荐一本书:清华出版的《Modbus软件开发实战指南》

    前言: 最近在研究Modbus开发,如果只是简单的了解了一些modbus基础知识,但是不够系统和全面. 其实,modbus虽然比较简单,但是如果不注意有很多坑,特别是寄存器的位数,大小端处理,浮点数, ...

  5. 写出稳定的Modbus代码之点滴经验

    1.引言 Modbus是工业领域重要的协议,物理层有常见的RS485双绞线和TCP,所以又常说Modbus 485开发和Modbus TCP开发. 前者就是串口通信,比较简单.后者涉及到网络协议,复杂 ...

  6. modbus串口通讯C#

    简介 公司给的一个小任务,这篇文章进行详细讲解 题目: modbus串口通讯 主要内容如下: 1.实现使用modbus通讯规约的测试软件: 2.具有通信超时功能: 3.分主站从站,并能编辑报文.生成报 ...

  7. Modbus

    Modbus 串行链路协议是一个主-从协议.在同一时刻,只有一个主节点连接于总线,一个或多个子节点 (最大编号为 247 ) 连接于同一个串行总线. Modbus 通信总是由主节点发起.子节点在没有收 ...

  8. modbus tcp 入门详解

    Modbus tcp 格式说明 通讯机制 附C#测试工具用于学习,测试   前言: 之前的博客介绍了如何用C#来读写modbus tcp服务器的数据,文章:http://www.cnblogs.com ...

  9. Modbus tcp 格式说明 通讯机制 附C#测试工具用于学习,测试

    前言: 之前的博客介绍了如何用C#来读写modbus tcp服务器的数据,文章:http://www.cnblogs.com/dathlin/p/7885368.html 当然也有如何创建一个服务器文 ...

随机推荐

  1. 编写高质量代码改善C#程序的157个建议——建议19:使用更有效的对象和集合初始化

    建议19:使用更有效的对象和集合初始化 依赖于属性和FCL 3.5之后的语法规则,现在我们有了更加简洁有效的对象和集合初始化机制:对象和集合初始化设定项. 对象初始化: class Person { ...

  2. 使用 Windows Phone 8 文件和 URI 关联的自动启动应用

    更详细,猛撸这里:http://msdn.microsoft.com/zh-cn/library/windowsphone/develop/jj206987(v=vs.105).aspx 在WMApp ...

  3. .net core MVC Filters 过滤器介绍

    一.过滤器的优级依次介绍如下(逐次递减): Authorization Filter ->  Resource Filter -> Acton Filter -> Exception ...

  4. C# 中请使用Contains判断字符串是否包含另一段字符串

    ∵ :使用Contains 比 IndexOf 的性能要高很多. 因为 Contains 是判断某个字符串是否在该字符串里面,而IndexOf是返回对应下标值 但是在使用contains的时候,注意转 ...

  5. 关于bootstrap模态框的初始化事件

    转:https://blog.csdn.net/u010181136/article/details/77579823

  6. C语言/C++编程学习三种循环用法和区别

    C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构.C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现 ...

  7. Vue 父组件向子组件传值,传方法,传父组件整体

    父子组件传值 1.父组件调用子组件时绑定属性,例如-> :title="title" 2.子组件中在props中声明title:props:['title','msg'] 3 ...

  8. WPF的Image控件图片不能显示出来的问题探究

    在wpf项目中,用Image来显示资源图片,在界面是可以显示,但是在运行的时候却显示不出来. <Image Source=" HorizontalAlignment="Lef ...

  9. IT学习资源

    介绍个人微信公众平台:Web开发笔记 含有免费学习资源,个人学习笔记,技术文章分享  资源篇 1.webapp书城开发 链接: https://pan.baidu.com/s/1pMHGKrh 密码: ...

  10. 老司机图文教程教你如何免费下载腾讯视频的视频mp4(直接下载到,不用qlv格式转mp4格式,亲测)

    关于如何下载到腾讯视频的mp4这个问题,大家想必经过多翻搜索,都未必找到满意的答案吧. 下载微信公众号文章中引用的腾讯视频的方法也是一样适用本方法. 因为用腾讯视电脑客户端和手机APP下载到的都是QL ...