使用winform实现串口转网口接收传递Modbus报文信息(包含心跳设置)

在实际工作中使用到了类似于485模块的功能想着与大家分享一下,此篇用TCP与UDP两种连接,使用串口连接主/从站,实现报文以网口发送串口获取再返回给网口展示,同时使用Timer实现心跳操作。

1.TCP/UDP在winform中的页面布局

TCP代码 

using System;
using System.Configuration;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace 空气质量变送器
{
    public partial class Form1 : Form
    {
        TcpClient tcpClient;
        System.Windows.Forms.Timer timer;
        CancellationTokenSource cts;
        public Form1()
        {
            InitializeComponent();
            txtIP.Text = ConfigurationManager.AppSettings["IPAddress"];
            txtPort.Text = ConfigurationManager.AppSettings["Port"];

            timer = new System.Windows.Forms.Timer();
            timer.Interval = 1000;
            timer.Tick += Timer_Tick;
        }

        #region 连接及关闭
        private async void btnConnOrClose_Click(object sender, EventArgs e)
        {
            if (btnConnOrClose.Text == "连接")
            {
                try
                {
                    tcpClient = new TcpClient();
                    await tcpClient.ConnectAsync(IPAddress.Parse(txtIP.Text), int.Parse(txtPort.Text));

                    btnConnOrClose.Text = "关闭";
                    txtIP.Enabled = false;
                    txtPort.Enabled = false;
                    if (cbRealTimeRead.Checked)
                    {
                        timer.Enabled = true;
                    }
                    else
                    {
                        AcceptData(); // 只接收一次数据
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
            }
            else
            {
                cts?.Cancel();
                tcpClient?.Close();
                btnConnOrClose.Text = "连接";
                txtIP.Enabled = true;
                txtPort.Enabled = true;
            }
        }
        #endregion

        #region 接收数据
        private void AcceptData()
        {
            if (tcpClient == null || !tcpClient.Connected) return;
            cts = new CancellationTokenSource();
            Task.Run(async () =>
            {
                if (cts.IsCancellationRequested) return;

                // 准备数据
                byte[] data = new byte[] { 0x01, 0x03, 0x00, 0x00, 0x00, 0x04 };
                byte[] crc = CreateCRC16(data);
                byte[] buffer = new byte[8];
                Array.Copy(data, 0, buffer, 0, 6);
                Array.Copy(crc, 0, buffer, 6, 2);

                NetworkStream stream = tcpClient.GetStream();
                stream.Write(buffer, 0, buffer.Length); // 发送数据
                await Task.Delay(50);

                // 接收数据
                byte[] bufferReceive = new byte[13];
                int length = stream.Read(bufferReceive, 0, bufferReceive.Length);
                if (length != 13) return;// 防止数据丢包

                int pm2_5 = BytesToUshort(bufferReceive[3], bufferReceive[4]);//PM2.5
                int pm10 = BytesToUshort(bufferReceive[5], bufferReceive[6]); //PM10
                float sd = BytesToUshort(bufferReceive[7], bufferReceive[8]) * 0.1F;   //湿度
                float wd = BytesToUshort(bufferReceive[9], bufferReceive[10]) * 0.1F;  //温度

                // 准备数据0
                data = new byte[] { 0x01, 0x03, 0x0, 0x08, 0x00, 0x02 };
                crc = CreateCRC16(data);
                buffer = new byte[8];
                Array.Copy(data, 0, buffer, 0, 6);
                Array.Copy(crc, 0, buffer, 6, 2);
                stream.Write(buffer, 0, buffer.Length);//发送数据
                await Task.Delay(50);

                // 接收数据
                bufferReceive = new byte[9];
                length = stream.Read(bufferReceive, 0, bufferReceive.Length);
                if (length != 9) return;

                int eyht = BytesToUshort(bufferReceive[3], bufferReceive[4]); //二氧化碳
                float jq = BytesToUshort(bufferReceive[5], bufferReceive[6]) * 0.01F;//甲醛

                // 展示
                Invoke(new Action(() =>
                {
                    txtPM2_5.Text = pm2_5.ToString();
                    txtPM10.Text = pm10.ToString();
                    txtSD.Text = sd.ToString();
                    txtWD.Text = wd.ToString();
                    txtEYHT.Text = eyht.ToString();
                    txtJQ.Text = jq.ToString();
                }));
            }, cts.Token);
        }
        #endregion

        #region 定时器事件及切换
        private void Timer_Tick(object sender, EventArgs e)
        {
            AcceptData();
        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            timer.Enabled = cbRealTimeRead.Checked;
        }
        #endregion

        #region 窗体关闭
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            cbRealTimeRead.Checked = false;
            cts?.Cancel();
            tcpClient?.Close();
        }
        #endregion

        #region 生成CRC
        public byte[] CreateCRC16(byte[] data)
        {
            //crc计算赋初始值
            int crc = 0xffff;
       
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值