1. 程式人生 > >c#串列埠seralport接收發送資料,生成chart折線圖,並儲存

c#串列埠seralport接收發送資料,生成chart折線圖,並儲存

剛剛從頭開始學習c#,在查詢資料過程中,感覺各位大神寫的太高深了,這裡是我寫的一個串列埠程式,希望與同我一樣的小白們一同努力,不要放棄,向更深一步加油吧;

程式要求:與兩個串列埠進行通訊,定時發出資料,對返回的資料進行處理(幀頭幀尾識別),經過演算法,得到一組資料,並將其輸出到chart圖表上(折線圖),最後儲存圖表。以下為程式碼:using System;
using System.IO.Ports;
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.Text.RegularExpressions;
using System.Diagnostics;
using System.Timers;
using System.Windows.Forms.DataVisualization.Charting;
namespace 接收完整版
{
 public partial class Form1 : Form
 {
  private SerialPort sp1 = new SerialPort();                //建立串列埠sp1
  private SerialPort sp2 = new SerialPort();              //建立串列埠sp2 
  public static double shuchu1;                               //sp1輸出資料
  public static double shuchu2;                               //sp2輸出資料
  public static double max0 = 0;                             //專案演算法中引數
  public static double c;                                          //同上
  public static double d;                                           //同上  public static int cishu=0;                                        //定時器執行次數  static System.Timers.Timer t;                                 //定時器宣告  Series series = new Series("Spline");                     //chart圖示  public Form1()
  {
   InitializeComponent();                                          
  }  private void Form1_Load(object sender, EventArgs e)
  {
   sp1.ReceivedBytesThreshold = 1;       //sp1引數設定,這裡是接收1個數據便促發接收處理程式;接下來是串列埠號,波特率,奇偶位,停止位,資料位數設定;
   sp1.PortName = "COM5";
   sp1.BaudRate = 115200;
   sp1.Parity = Parity.None;
   sp1.StopBits = StopBits.One;
   sp1.DataBits = 8;
   sp1.Open();                                        //sp1串列埠開啟
   sp1.DataReceived += new SerialDataReceivedEventHandler(sp1_DataReceived);   //sp1接收資料事件
   sp2.ReceivedBytesThreshold = 1;     //sp2引數設定
   sp2.PortName = "COM6";
   sp2.BaudRate = 115200;
   sp2.Parity = Parity.None;
   sp2.StopBits = StopBits.One;
   sp2.DataBits = 8;
   sp2.Open();//開啟串列埠
   sp2.DataReceived += new SerialDataReceivedEventHandler(sp2_DataReceived);
   Control.CheckForIllegalCrossThreadCalls = false;                 執行緒間檢測關閉(即跨執行緒呼叫不報錯)
   chart1.Series.Clear();
   series.ChartType = SeriesChartType.Spline;      //圖型別Spline
   chart1.Series.Add(series);                      //新增一個圖表序列
   this.chart1.ChartAreas[0].AxisY.Minimum = 0;           //設定設定縱座標的最小值0
   this.chart1.ChartAreas[0].AxisY.Maximum = 0.2;           //設定設定縱座標的最大值0.2
   this.chart1.ChartAreas[0].AxisX.Minimum = 0;           //設定設定縱座標的最小值0
   this.chart1.ChartAreas[0].AxisX.Maximum = 2000;           //設定設定縱座標的最大值0.2
   this.chart1.ChartAreas[0].AxisX.Interval = 100;          //設定橫座標間隔為50,使得每個刻度間均勻分開的
   this.chart1.ChartAreas[0].AxisY.Interval = 0.01;
   this.chart1.ChartAreas[0].AxisX.MajorGrid.LineColor = System.Drawing.Color.Green;   //背景網格線顏色為銀色
   this.chart1.ChartAreas[0].AxisY.MajorGrid.LineColor = System.Drawing.Color.Green;    //背景網格線顏色為銀色
   this.chart1.ChartAreas[0].AxisX.Title = "次數/次";              //設定下方橫座標名稱
   this.chart1.ChartAreas[0].AxisY.Title = "同軸度/mm";          //設定左邊縱座標的名稱
   chart1.ChartAreas[0].Area3DStyle.Enable3D = true;           //以3D形式展示
   
   chart1.Series[0].Color = Color.Red;               //線條顏色
  }  private List<byte> buffer = new List<byte>(1048576);     //sp1接收事件
  void sp1_DataReceived(object sender, SerialDataReceivedEventArgs e)
  (
   int n = sp1.BytesToRead;//待讀位元組個數
   byte[] buf = new byte[n];//建立n個位元組的快取
   byte[] ReceiveBytes = new byte[9];
   sp1.Read(buf, 0, n);//讀到在資料儲存到buf   //快取資料
   buffer.AddRange(buf);//不斷地將接收到的資料加入到buffer連結串列中   while (buffer.Count >= 6) //至少包含幀頭(1位元組)、資料(3位元組)、幀尾(1位元組)、效驗位(1位元組);
   {    if (buffer[0] == 0x02) //到幀頭  02H
    {     if (buffer.Count < 6) //資料區尚未接收完整,
     {
      break;//跳出接收函式後之後繼續接收資料
     }
     //得到完整的資料,複製到ReceiveBytes中進行校驗
     buffer.CopyTo(0, ReceiveBytes, 0, 6);//複製資料
     byte check; //開始校驗
     check = 0x03;//幀尾     if (check != ReceiveBytes[4]) //幀尾驗證位失敗  
     {
      buffer.RemoveRange(0, 6);//從連結串列中移除接收到的校驗失敗的資料,      continue;                //繼續執行while迴圈程式,
     }
 
     buffer.RemoveRange(0, 6);     string strRcv = null;
     for (int i = 1; i < 4; i++) //窗體顯示
     {
      strRcv += ReceiveBytes[i].ToString("X2");  //16進位制顯示
     }     //                專案演算法    //
    }
    else //幀頭不正確時,清除
    {
     buffer.RemoveAt(0);//清除第一個位元組,繼續檢測下一個。
    }
   }  }  private List<byte> buffer2 = new List<byte>(1048576);     //sp2接收事件
  void sp2_DataReceived(object sender, SerialDataReceivedEventArgs e)
  {
   int n = sp2.BytesToRead;//待讀位元組個數
   byte[] buf2 = new byte[n];//建立n個位元組的快取
   byte[] ReceiveBytes2 = new byte[11];
   sp2.Read(buf2, 0, n);//讀到在資料儲存到buf   //快取資料
   buffer2.AddRange(buf2);//不斷地將接收到的資料加入到buffer連結串列中   while (buffer2.Count >= 9) //至少包含幀頭(1位元組)、資料(7位元組)、幀尾(1位元組);
   {    if (buffer2[0] == 0x02) //到幀頭  02H
    {     if (buffer2.Count < 9) //資料區尚未接收完整,
     {
      break;//跳出接收函式後之後繼續接收資料
     }
     //得到完整的資料,複製到ReceiveBytes中進行校驗
     buffer2.CopyTo(0, ReceiveBytes2, 0, 9);//
     byte check2; //開始校驗
     check2 = 0x03;     if (check2 != ReceiveBytes2[8]) //幀尾驗證位失敗  
     {
      buffer2.RemoveRange(0, 9);//從連結串列中移除接收到的校驗失敗的資料,      continue;                //繼續執行while迴圈程式,
     }     buffer2.RemoveRange(0, 9);
     char[] c = new char[9];
     int a;     for (int i = 1, j = 0; i < 8; i++, j++)
     {
      a = Convert.ToInt32(ReceiveBytes2[i]);
      c[j] = Convert.ToChar(a);
     }
     string b = new string(c);
     txb2.Text = b;
     shuchu2 = float.Parse(b);
    }
    else                                                       //幀頭不正確,清除
    {
     buffer2.RemoveAt(0);                                   //清除第一個位元組,繼續檢測下一個。
    }
   }  }  private void button1_Click(object sender, EventArgs e)              //點選開始按鈕觸發時間;這裡需要取初值;
  {
   System.Timers.Timer t0 = new System.Timers.Timer(50);           //例項化Timer類,設定間隔時間為50毫秒;  
   t0.Elapsed += new System.Timers.ElapsedEventHandler(theout0);     //到達時間的時候執行事件;  
   t0.AutoReset = false;                                             //設定是執行一次(false)還是一直執行(true);  
   t0.Enabled = true;                                               //是否執行System.Timers.Timer.Elapsed事件; 
  }  public void theout0(object source, System.Timers.ElapsedEventArgs e)  //到達時間的時候執行事件;  {
   string strFrame = "024D3F0371";                                  //sp1 傳送單次讀取指令;   byte[] hFrame = new byte[strFrame.Length / 2];
   for (int i = 0; i < strFrame.Length / 2; i++)
   {
    hFrame[i] = Convert.ToByte(strFrame.Substring(i * 2, 2), 16);    //資料格式轉換
   }
   sp1.Write(hFrame, 0, 5);
   string strFrame2 = "024D454153555245204103";                    //sp2 傳送單次讀取指令;   byte[] hFrame2 = new byte[strFrame2.Length / 2];
   for (int i = 0; i < strFrame2.Length / 2; i++)
   {
    hFrame2[i] = Convert.ToByte(strFrame2.Substring(i * 2, 2), 16);
   }
   sp2.Write(hFrame2, 0, 11);      t = new System.Timers.Timer(20);           //例項化Timer類,設定間隔時間為20毫秒;  
      t.Elapsed += new System.Timers.ElapsedEventHandler(theout);     //到達時間的時候執行事件;  
   t.AutoReset = true;                                             //設定是執行一次(false)還是一直執行(true);  
   t.Enabled = true;                                               //是否執行System.Timers.Timer.Elapsed事件; 
        }
  public void theout(object source, System.Timers.ElapsedEventArgs e)  //到達時間的時候執行事件;
  {   cishu = cishu + 1;
   string strFrame = "024D3F0371";                                  //sp1 傳送單次讀取指令;   byte[] hFrame = new byte[strFrame.Length / 2];
   for (int i = 0; i < strFrame.Length / 2; i++)
   {
    hFrame[i] = Convert.ToByte(strFrame.Substring(i * 2, 2), 16);
   }
   sp1.Write(hFrame, 0, 5);
   string strFrame2 = "024D454153555245204103";                    //sp2 傳送單次讀取指令;   byte[] hFrame2 = new byte[strFrame2.Length / 2];
   for (int i = 0; i < strFrame2.Length / 2; i++)
   {
    hFrame2[i] = Convert.ToByte(strFrame2.Substring(i * 2, 2), 16);
   }
   sp2.Write(hFrame2, 0, 11);  
   double max;                                                                                        //專案需要的演算法,不用管它
   max = System.Math.Abs((shuchu1 - c) + (shuchu2 - d));

   txb32.Text  = max.ToString("0.0000") ;
   if (shuchu1 != 0)                                   
   {
    if(shuchu2 !=0)
    {
           if (max > max0)
      {
                         max0 = max;
         };
     
      txb6.Text = max0.ToString("0.000");
 
       txb31.Text = cishu.ToString("0");
                series.Points.AddXY(cishu, max);                                             //生成圖表,因為實時生成會卡,所以這裡接收完資料後,一起生成                }
   }  }   private void button2_Click(object sender, EventArgs e)         //暫停鍵                      
  {  
   t.Stop();
   chart1.Series[0].Points.Clear();
   Application.Exit();
  }
  private void button3_Click(object sender, EventArgs e)                //停止鍵
  {
      t.Stop();
   sp1.Close();
   sp2.Close();
  }  private void button4_Click(object sender, EventArgs e)               //待測品放置完成後,讀取初值
  {   string strFrame = "024D3F0371";                                  //sp1 傳送單次讀取指令;   byte[] hFrame = new byte[strFrame.Length / 2];
   for (int i = 0; i < strFrame.Length / 2; i++)
   {
    hFrame[i] = Convert.ToByte(strFrame.Substring(i * 2, 2), 16);
   }
   sp1.Write(hFrame, 0, 5);
   string strFrame2 = "024D454153555245204103";                    //sp2 傳送單次讀取指令;   byte[] hFrame2 = new byte[strFrame2.Length / 2];
   for (int i = 0; i < strFrame2.Length / 2; i++)
   {
    hFrame2[i] = Convert.ToByte(strFrame2.Substring(i * 2, 2), 16);
   }
   sp2.Write(hFrame2, 0, 11);   //
      專案中輸出顯示到textbox //
  }  private void button5_Click(object sender, EventArgs e)                  //重置即停止並清楚現有資料
  {      t.Stop();
   chart1.Series[0].Points.Clear();
   sp1.Close();
   sp2.Close();
   sp1.Open();
   sp2.Open();   max0 = 0;
   txb6.Text = max0.ToString("0.000");
   cishu = 0;
   txb31.Text = cishu.ToString("0");
  }  private void btn6_Click(object sender, EventArgs e)                     //儲存影象至C:/Users/Administrator/Desktop/同軸度
  {
   DateTime d = DateTime.Now;                                                       //讀取當前時間,作為影象儲存名稱
   string fileName = d.ToString("yyyyMMddHHmmss");                     //將時間轉為字串,並去掉空格,冒號等
   string GR_Path = @"C:/Users/Administrator/Desktop/同軸度/同軸度影象";        
   string fullFileName = GR_Path + "\\" + fileName + ".jpeg";
   chart1.SaveImage(fullFileName, ChartImageFormat.Jpeg);
   chart1.SaveImage("C:/Users/Administrator/Desktop/同軸度/同軸度影象.jpeg", ChartImageFormat.Jpeg);                                                                                                     //儲存影象路徑:桌面/同軸度/同軸度影象.jpeg
  }
 }
}原始碼地址:https://download.csdn.net/download/yunsongblue/10277693