- A+
前言:本文全部纯手工打造,如有疏漏之处,还请谅解!
如果需要查看更多文章,请微信搜索公众号 csharp编程大全,需要进C#交流群群请加微信z438679770,备注进群, 我邀请你进群! ! !
这篇文章涉及较多C#重要知识点,如果都能看懂,你至少可以算得上入门了!有兴趣的同志可以下载源码调试.
开始吧:
-》指令格式介绍
激光测距模块
UDP: 192.168.1.200 8008发往8010;192.168.1.201 8008发往8011;
协议:C3 00为195cm
光电开关模块
UDP:192.168.1.202 8008发往8012
帧头59 59
数据 01 01 01 01 为4个光电开关状态,依次为安检通道入口光电开关、安检门光电开关1、安检门光电开关2,安检通道出口光电开关。其中1为无人遮挡状态,0为有人遮挡状态
填充 44 55 66 77 88 99 00 12 23 34 45 56 67 ee
4个光电开关均无人
1、2、3光电开关有人 4光电开关无人
开发软硬件环境:
硬件:1. 4路光电开关,4路测距雷达,数据通过udp发送到主机192.168.1.119
软件:1. vs2017 + win10
-》重要知识点:
1. 多线程操作:thread和task的使用
2. winform的chart控件使用
3.队列Queue和list使用
4.双缓冲用法
5.定时器操作
6.线程中操作主窗体控件:
this.Invoke((EventHandler)delegate
{
richTextBoxEx1.Text += stringData + "rn";
}):
7.通过循环的方式遍历操作控件
8.数据类型转换:
Byte[] recv = client.Receive(ref endpoint);
string stringData = "0x" + BitConverter.ToString(recv).Replace("-", " 0x").ToLower();
-》开发难点:
1. chart需要绘制所有采集上来的数据点,光电开关1毫秒就一组数据,绘图时间得跟得上
2. 多线程的灵活使用
全部代码:
using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using System.Windows.Forms.DataVisualization.Charting; namespace lidarTest { public partial class mainForm : DevComponents.DotNetBar.Office2007Form { public mainForm() { this.DoubleBuffered = true;//设置本窗体 SetStyle(ControlStyles.UserPaint, true); SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景. SetStyle(ControlStyles.DoubleBuffer, true); // 双缓冲 this.EnableGlass = false; InitializeComponent(); InitChart(); checkBox2.Checked = false; checkBox1.Checked = false; } private Queue<int>[] dataQueue = new Queue<int>[8];//把Queue<double>看成一个类型 int[] a=new int [8] private List<int>[] dataList = new List<int>[8]; private Queue<string> dQueue = new Queue<string>(); bool isStart = false; int count = 0; private static readonly object Lock = new object(); Stopwatch elapsetime = new Stopwatch(); private void mainForm_Load(object sender, EventArgs e) { dataQueue[0] = new Queue<int>(); dataQueue[1] = new Queue<int>(); dataQueue[2] = new Queue<int>(); dataQueue[3] = new Queue<int>(); dataQueue[4] = new Queue<int>(); dataQueue[5] = new Queue<int>(); dataQueue[6] = new Queue<int>(); dataQueue[7] = new Queue<int>(); dataList[0] = new List<int>(); dataList[1] = new List<int>(); dataList[2] = new List<int>(); dataList[3] = new List<int>(); dataList[4] = new List<int>(); dataList[5] = new List<int>(); dataList[6] = new List<int>(); dataList[7] = new List<int>(); this.WindowState = FormWindowState.Normal; this.FormBorderStyle = FormBorderStyle.Sizable; this.Top = 0; this.Left = 0; this.Width = Screen.PrimaryScreen.WorkingArea.Width; this.Height = Screen.PrimaryScreen.WorkingArea.Height; Start(); //MessageBox.Show( DateTime.Now.ToString("yyyy_MM_dd_hh_mm_ss_fff")); } // 防止闪屏 //protected override CreateParams CreateParams //{ // get // { // CreateParams cp = base.CreateParams; // cp.ExStyle |= 0x02000000; // return cp; // } //} public void Start() { Thread t1 = new Thread(StartDataRevThread1); //第一路激光雷达数据接收线程 t1.Start(); t1.IsBackground = true; Thread t2 = new Thread(StartDataRevThread2); //第二路激光雷达数据接收线程 t2.Start(); t2.IsBackground = true; Thread t3 = new Thread(StartDataRevThread3);//第三路激光雷达数据接收线程 t3.Start(); t3.IsBackground = true; Thread t4 = new Thread(StartDataRevThread4);////第四路激光雷达数据接收线程 t4.Start(); t4.IsBackground = true; Thread t5 = new Thread(StartDataRevThread5);//四个广电开关数据接受线程 t5.Start(); t5.IsBackground = true; Thread t6 = new Thread(dataSaveThread6);//数据写入线程 t6.Start(); t6.IsBackground = true; } private void StartDataRevThread1() { try { UdpClient client = new UdpClient(8021); //IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, 0);// IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse("192.168.1.30"), 8008); //client.Client.ReceiveBufferSize = 40960;//40960 默认值是8192 while (true) { Byte[] recv = client.Receive(ref endpoint); string stringData = "0x" + BitConverter.ToString(recv).Replace("-", " 0x").ToLower(); this.Invoke((EventHandler)delegate { //richTextBoxEx1.Text += stringData + "rn"; chartShow( recv[2] + (recv[3]<<8),1); } ); } } catch(Exception ex) { MessageBox.Show(ex.Message + "n" + ex.StackTrace) ; } } private void StartDataRevThread2() { try { UdpClient client = new UdpClient(8022); IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse("192.168.1.40"), 8008); while (true) { Byte[] recv = client.Receive(ref endpoint); string stringData = "0x" + BitConverter.ToString(recv).Replace("-", " 0x").ToLower(); this.Invoke((EventHandler)delegate { //richTextBoxEx2.Text += stringData + "rn"; chartShow(recv[2] + (recv[3] << 8),2); } ); } } catch (Exception ex) { MessageBox.Show(ex.Message + "n" + ex.StackTrace); } } private void StartDataRevThread3() { try { UdpClient client = new UdpClient(8023); IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse("192.168.1.100"), 8008); while (true) { Byte[] recv = client.Receive(ref endpoint); string stringData = "0x" + BitConverter.ToString(recv).Replace("-", " 0x").ToLower(); this.Invoke((EventHandler)delegate { //richTextBoxEx3.Text += stringData + "rn"; chartShow( recv[2] + (recv[3] << 8),3); } ); } } catch (Exception ex) { MessageBox.Show(ex.Message + "n" + ex.StackTrace); } } private void StartDataRevThread4() { try { UdpClient client = new UdpClient(8024); IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse("192.168.1.200"), 8008); while (true) { Byte[] recv = client.Receive(ref endpoint); string stringData = "0x" + BitConverter.ToString(recv).Replace("-", " 0x").ToLower(); this.Invoke((EventHandler)delegate { //richTextBoxEx4.Text += stringData + "rn"; chartShow( recv[2] + (recv[3] << 8),4); } ); } } catch (Exception ex) { MessageBox.Show(ex.Message + "n" + ex.StackTrace); } } private void StartDataRevThread5() { try { UdpClient client = new UdpClient(8012); IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse("192.168.1.202"), 8008); client.Client.ReceiveBufferSize = 1024*1024;//默认值是8192 while (true) { Byte[] recv = client.Receive(ref endpoint); elapsetime.Restart();//计时开始 this.Invoke((EventHandler)delegate { //if (count >= 100) { count = 0; Task.Run(() => { chartShow(recv[2], 5); } ); Task.Run(() => { chartShow(recv[3], 6); } ); Task.Run(() => { chartShow(recv[4], 7); } ); Task.Run(() => { chartShow(recv[5], 8); } ); //chartShow(recv[2], 5); //chartShow(recv[3], 6); //chartShow(recv[4], 7); //chartShow(recv[5], 8); if (checkBox2.Checked == true) { string stringData = "0x" + BitConverter.ToString(recv).Replace("-", " 0x").ToLower(); dQueue.Enqueue(DateTime.Now.ToString("yyyy-MM-dd_HH:mm:ss:fff") + " " + stringData); } } count++; } ); elapsetime.Stop();//计时结束 this.Invoke((EventHandler)delegate { label1.Text = "接收数据耗时:"+ elapsetime.ElapsedMilliseconds.ToString("0000"); }); } } catch (Exception ex) { MessageBox.Show(ex.Message + "n" + ex.StackTrace); } } private void dataSaveThread6() { while (true) { if (checkBox2.Checked == true) { String LogPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Log"); if (dQueue.Count() > 0) strWrite(dQueue.Dequeue(), LogPath, "log.txt"); } } } private void InitChart() { Chart[] ch = new Chart[12] { chart1, chart2, chart3, chart4,chart5, chart6, chart7, chart8 , chart_1, chart_2, chart_3, chart_4 }; for (int i = 0; i < 4 ; i++) { ch[i].ChartAreas.Clear(); ChartArea chartArea1 = new ChartArea("C1"); ch[i].ChartAreas.Add(chartArea1); //定义存储和显示点的容器 ch[i].Series.Clear(); Series series1 = new Series("S1"); series1.ChartArea = "C1"; ch[i].Series.Add(series1); ch[i].ChartAreas[0].AxisY.IsStartedFromZero = false; ch[i].Legends[0].Enabled = false; ch[i].ChartAreas[0].AxisX.Interval = 100; ch[i].ChartAreas[0].AxisX.Maximum = 1000; //ch[i].ChartAreas[0].AxisX.ScaleView.Size = 8;//设置图表可视区域数据点数,说白了一次可以看到多少个X轴区域 ch[i].ChartAreas[0].Axes[0].MajorGrid.Enabled = false; ch[i].ChartAreas[0].Axes[1].MajorGrid.Enabled = false; //y轴上网格 //ct.ChartAreas[0].Axes[1].MajorGrid.Enabled = false; //ch[i].ChartAreas[0].AxisX.IsStartedFromZero = false; //ch[i].ChartAreas[0].AxisX.MajorGrid.LineColor = System.Drawing.Color.Silver; //ch[i].ChartAreas[0].AxisY.MajorGrid.LineColor = System.Drawing.Color.Silver; //设置标题 ch[i].Titles.Clear(); //ch[i].Titles.Add("S01"); //ch[i].Titles[0].Text = "通道" + (i + 1) + " 折线图显示"; //ch[i].Titles[0].ForeColor = Color.RoyalBlue; //ch[i].Titles[0].Font = new System.Drawing.Font("Microsoft Sans Serif", 12F); //设置图表显示样式 ch[i].Series[0].Color = Color.Red; //this.chart1.Titles[0].Text = string.Format("{0}折线图显示", ); ch[i].Series[0].ChartType = SeriesChartType.FastLine; ch[i].Series[0].Points.Clear(); } for (int i = 4; i < 12; i++) { ch[i].ChartAreas.Clear(); ChartArea chartArea1 = new ChartArea("C1"); ch[i].ChartAreas.Add(chartArea1); //定义存储和显示点的容器 ch[i].Series.Clear(); Series series1 = new Series("S1"); series1.ChartArea = "C1"; ch[i].Series.Add(series1); ch[i].ChartAreas[0].AxisY.IsStartedFromZero = false; ch[i].Legends[0].Enabled = false; //ch[i].ChartAreas[0].AxisX.Interval = 100; //ch[i].ChartAreas[0].AxisX.Maximum = 10000; //ch[i].ChartAreas[0].AxisX.ScaleView.Size = 8;//设置图表可视区域数据点数,说白了一次可以看到多少个X轴区域 ch[i].ChartAreas[0].Axes[0].MajorGrid.Enabled = false; ch[i].ChartAreas[0].Axes[1].MajorGrid.Enabled = false; //y轴上网格 //ct.ChartAreas[0].Axes[1].MajorGrid.Enabled = false; //ch[i].ChartAreas[0].AxisX.IsStartedFromZero = false; //ch[i].ChartAreas[0].AxisX.MajorGrid.LineColor = System.Drawing.Color.Silver; //ch[i].ChartAreas[0].AxisY.MajorGrid.LineColor = System.Drawing.Color.Silver; //设置标题 ch[i].Titles.Clear(); //ch[i].Titles.Add("S01"); //ch[i].Titles[0].Text = "通道" + (i + 1) + " 折线图显示"; //ch[i].Titles[0].ForeColor = Color.RoyalBlue; //ch[i].Titles[0].Font = new System.Drawing.Font("Microsoft Sans Serif", 12F); //设置图表显示样式 ch[i].Series[0].Color = Color.Red; //this.chart1.Titles[0].Text = string.Format("{0}折线图显示", ); ch[i].Series[0].ChartType = SeriesChartType.FastLine; ch[i].Series[0].Points.Clear(); } } public void chartShow(int y, int ch) { Chart[] chNum = new Chart[8] { chart_1, chart_2, chart_3, chart_4, chart5, chart6, chart7, chart8 }; if (ch <= 8) chartDisplay(chNum[ch - 1], ch, y); } delegate void ChartDelegate(Chart chart, int ch, int y); private void chartDisplay(Chart chart, int ch, int y) { if (chart.InvokeRequired) { ChartDelegate chartDelegate = chartDisplay; chart.Invoke(chartDelegate, new object[] { chart, ch, y }); } else { lock (Lock) { if (isStart == true) UpdateQueueValue(ch, y);//点击开启按钮后,开始采集收集数据,并更新到队列或列表中 } } } private void UpdateQueueValue(int ch, int y) { lock (Lock) { if (dataQueue[ch - 1].Count > 1000) //先出列 dataQueue[ch - 1].Dequeue(); dataQueue[ch - 1].Enqueue(y); //方法二 用list //if (dataList[ch - 1].Count > 20000) // dataList[ch - 1].RemoveAt(0); //dataList[ch - 1-4].Add(2); dataList[ch - 1].Add(y); } } private void btnStart_Click(object sender, EventArgs e) { if (!isStart) { dataQueue[0] = new Queue<int>(); dataQueue[1] = new Queue<int>(); dataQueue[2] = new Queue<int>(); dataQueue[3] = new Queue<int>(); dataQueue[4] = new Queue<int>(); dataQueue[5] = new Queue<int>(); dataQueue[6] = new Queue<int>(); dataQueue[7] = new Queue<int>(); dataList[0] = new List<int>(); dataList[1] = new List<int>(); dataList[2] = new List<int>(); dataList[3] = new List<int>(); dataList[4] = new List<int>(); dataList[5] = new List<int>(); dataList[6] = new List<int>(); dataList[7] = new List<int>(); chart_1.Series[0].Points.Clear(); chart_2.Series[0].Points.Clear(); chart_3.Series[0].Points.Clear(); chart_4.Series[0].Points.Clear(); chart5.Series[0].Points.Clear(); chart6.Series[0].Points.Clear(); chart7.Series[0].Points.Clear(); chart8.Series[0].Points.Clear(); btnStart.Text = @"停止采集"; btnStart.DisabledImage = btnStart.Image; btnStart.Image = (Image)btnStart.PressedImage.Clone(); isStart = !isStart; } else { btnStart.Text = @"开始采集"; btnStart.Image = btnStart.DisabledImage; isStart = !isStart; } } /*************文件写入函数**************/ private void strWrite(string str, string filePath, string fileName) { lock (Lock) { if (!Directory.Exists(filePath)) Directory.CreateDirectory(filePath); if (!File.Exists(filePath + "\" + fileName)) File.Create(filePath + "\" + fileName).Close(); //.Close 很关键,不然会有问题 StreamWriter sw = new StreamWriter(filePath + "\" + fileName, true);//true 追加数据 sw.WriteLine(str); sw.Close(); } } /*************chart图片保存函数**************/ private void imageSave( Chart chart, string filePath, string fileName) { lock (Lock) { if (!Directory.Exists(filePath)) Directory.CreateDirectory(filePath); chart.SaveImage(filePath +"\" + fileName, ChartImageFormat.Png); } } /*************定时器中更新chart**************/ private void timer1_Tick(object sender, EventArgs e) { Chart[] ch = new Chart[8] { chart1, chart2, chart3, chart4, chart5, chart6, chart7, chart8 }; Chart[] cha = new Chart[4] { chart_1, chart_2, chart_3, chart_4 }; string[] str = new string[8] { "chart1", "chart2", "chart3", "chart4", "chart5", "chart6", "chart7", "chart8" }; string[] stri = new string[4] { "chart_1", "chart_2", "chart_3", "chart_4", }; Label[] lb = new Label[4] { label2, label3, label4, label5 }; for (int j = 4; j < 8; j++) { Stopwatch sw = new Stopwatch(); var k = j;//参数需要传入task中,不然j一直是7 Task.Run(() => { sw.Start(); this.Invoke((EventHandler)delegate { //chart5.Series[0].Points.Clear(); for (int i = 0; i < dataList[k].Count; i++) ch[k].Series[0].Points.AddY(dataList[k][i]);//光电开关波形图-所有点 dataList[k].Clear(); ch[k-4].Series[0].Points.Clear(); for (int i = 0; i < dataQueue[k].Count; i++) ch[k - 4].Series[0].Points.AddY(dataQueue[k].ElementAt(i));//光电开关波形图-最近1000个点 for (int i = 0; i < dataList[k-4].Count; i++) cha[k - 4].Series[0].Points.AddY(dataList[k-4][i]);//激光测距雷达波形图--所有点 dataList[k-4].Clear(); if (checkBox1.Checked == true) { //保存曲线图片 String imagePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "image//" + str[k]); imageSave(ch[k], imagePath, DateTime.Now.ToString("yyyy_MM_dd_hh_mm_ss_fff") + ".png"); } sw.Stop(); lb[k - 4].Text = sw.ElapsedMilliseconds.ToString(str[k] + "耗时:" + "0000");//记录chart绘制的好事呢 }); }); } } } }
运行结果:
项目源码下载地址:
链接:https://pan.baidu.com/s/1QfoIVNarj-rgK449JM40yQ
提取码:v2nu
------------------------------------------------------------------------
如果需要查看更多文章,请微信搜索公众号 csharp编程大全,需要进C#交流群群请加微信z438679770,备注进群, 我邀请你进群! ! !