C# modbus 图表

控件:chart1(图表),cartesianChart1(第三方添加图表),timer(时间)

添加第三方:

效果:图标会根据连接的温度,湿度用timer时间进行改变

Chart1控件样式:Series添加线条,颜色,名称等数据

cs 复制代码
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        //1 安装livecharts第三方; 安装livechartswinform第三方;
        timer1.Interval = 1000;
        timer1.Start();

        //给图表添加系列
        //new LineSeries() 添加一个线性的系列
        // values 指的是线性系列图表值是 ChartValues类型当中的float类型
       
        cartesianChart1.Series.Add(new LineSeries() { Values = new ChartValues<double>() }); //温度
        cartesianChart1.Series.Add(new LineSeries() { Values = new ChartValues<double>() });//湿度


        
        //给x轴加时间
       cartesianChart1.AxisX.Add(new LiveCharts.Wpf.Axis() { Labels = times });


       //创建客户端对象
        tcp = new TcpClient();//创建客户端对象
        tcp.Connect("192.168.107.5", 8014);
        stream = tcp.GetStream(); //获取网络基础流

    }
    TcpClient tcp;
    NetworkStream stream;


    public List<string> times = new List<string>();
    Random r = new Random();// 随机数对象
    double 温度;
    double 湿度;
    //实时更新数据
    private void timer1_Tick(object sender, EventArgs e)
    {


        // 模拟数据
        //float 温度 = r.Next(-100, 410) / 10F;//模拟请求 请求温度数据
        //float 湿度 = r.Next(-100, 410) / 10F; //读取湿度
        refresh();


        //给chart1 添加数据
        // 给系列1添加xy轴 ,x轴是时间,y轴是温度数据
        chart1.Series[0].Points.AddXY(DateTime.Now.ToString("HH:mm:ss"), 温度);
        chart1.Series[1].Points.AddXY(DateTime.Now.ToString("HH:mm:ss"), 湿度);

        //超出一定数值之后 删除一部分图表?
        if (chart1.Series[0].Points.Count>=10)
        {
            chart1.Series[0].Points.RemoveAt(0);
            chart1.Series[1].Points.RemoveAt(0);
            
        }
        // 给cartesianChart1添加数据
        times.Add(DateTime.Now.ToString());
        cartesianChart1.Series[0].Values.Add(温度);
        cartesianChart1.Series[1].Values.Add(湿度);
    }

    async void refresh()
    {
        try
        {

            //请求帧
            byte[] buffer = null;
            //响应帧
            byte[] res = null;
            //设备地址
            byte address = Convert.ToByte("1");
            //响应数据的个数
            int resCount = -1;
            //响应帧的crc
            byte[] crc;
            buffer = new byte[] { address, 0x03, 0x00, 0x02, 0x00, 0x02 };
            buffer = buffer.Concat(CRCCalc(buffer)).ToArray();

            //异步发请求。发送请求帧
            await stream.WriteAsync(buffer, 0, buffer.Length);

            //接收数据 响应帧。[地址码 功能码 有效个数,0x00,0x01,0x00,0x01,高位 地位]
            res = new byte[9];
            resCount = await stream.ReadAsync(res, 0, res.Length);

            //数据验证

            // 数据验证
            if (resCount == 0 || resCount != res.Length)
            {
                Console.WriteLine("读取湿度、温度时,数据长度不正确");
                return;
            }
            // 验证地址码和功能码
            if (res[0] != buffer[0] || res[1] != buffer[1])
            {
                Console.WriteLine("读取湿度、温度时,设备地址或功能码不匹配");
                return;
            }
            // 验证CRC
            crc = CRCCalc(res, 0, res.Length - 2);
            if (crc[0] != res[res.Length - 2] || crc[1] != res[res.Length - 1])
            {
                Console.WriteLine("读取湿度、温度时,CRC验证失败");
                return;
            }

            //数据解析 读取数据
            double humidity = (res[3] * 256 + res[4]) * 0.1; //湿度
            double wendu = (res[5] * 256 + res[6]) * 0.1;
            湿度 = humidity;
            温度 = wendu;


        }
        catch
        {
            MessageBox.Show("获取数据失败");
        }

    }
    public static byte[] CRCCalc(byte[] data)
    {
        //crc计算赋初始值
        int crc = 0xffff;
        for (int i = 0; i < data.Length; i++)
        {
            //XOR
            //(1) 0^0=0,0^1=1  0异或任何数=任何数
            //(2) 1 ^ 0 = 1,1 ^ 1 = 0  1异或任何数-任何数取反
            //(3) 1 ^ 1 = 0,0 ^ 0 = 0  任何数异或自己=把自己置0
            //异或操作符是^。异或的特点是相同为false,不同为true。
            crc = crc ^ data[i]; //和^表示按位异或运算。
                                 //0x0fff ^ 0x01 Console.WriteLine(result.ToString("X")); 
                                 // 输出结果为4094,即十六进制数1001
            for (int j = 0; j < 8; j++)
            {
                int temp;
                temp = crc & 1; // & 运算符(与) 1 & 0 为 0  ;0 & 0 为0;1 & 1 为1

                //右移 (>>) 将第一个操作数向右移动第二个操作数所指定的位数,空出的位置补0。右移相当于整除. 右移一位相当于除以2;右移两位相当于除以4;右移三位相当于除以8。
                //int i = 7;
                //int j = 2;
                //Console.WriteLine(i >> j);   //输出结果为1
                crc = crc >> 1;
                crc = crc & 0x7fff;
                if (temp == 1)
                {
                    crc = crc ^ 0xa001;
                }
                crc = crc & 0xffff;
            }
        }
        //CRC寄存器的高低位进行互换
        byte[] crc16 = new byte[2];
        //CRC寄存器的高8位变成低8位,
        crc16[1] = (byte)((crc >> 8) & 0xff);
        //CRC寄存器的低8位变成高8位
        crc16[0] = (byte)(crc & 0xff);
        return crc16;
    }
    public static byte[] CRCCalc(byte[] data, int offset, int length)
    {
        byte[] Tdata = data.Skip(offset).Take(length).ToArray();
        return CRCCalc(Tdata);
    }

}
相关推荐
Jasmine_llq34 分钟前
《 火星人 》
算法·青少年编程·c#
亽仒凣凣1 小时前
Windows安装Redis图文教程
数据库·windows·redis
炫彩@之星1 小时前
Windows和Linux安全配置和加固
linux·windows·安全·系统安全配置和加固
小奥超人1 小时前
RAR压缩算法的文件修复功能详解
windows·经验分享·winrar·办公技巧
军训猫猫头2 小时前
20.抽卡只有金,带保底(WPF) C#
ui·c#·wpf
Clockwiseee12 小时前
php伪协议
windows·安全·web安全·网络安全
向宇it13 小时前
【从零开始入门unity游戏开发之——C#篇25】C#面向对象动态多态——virtual、override 和 base 关键字、抽象类和抽象方法
java·开发语言·unity·c#·游戏引擎
数据的世界0113 小时前
.NET开发人员学习书籍推荐
学习·.net
唐宋元明清218813 小时前
.NET 阻止系统睡眠/息屏
windows·电源
向宇it14 小时前
【从零开始入门unity游戏开发之——C#篇24】C#面向对象继承——万物之父(object)、装箱和拆箱、sealed 密封类
java·开发语言·unity·c#·游戏引擎