C# modbus 图表

avatar
作者
筋斗云
阅读量:4

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

添加第三方:

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

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

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);     }  }

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!