讀取串口數據畫圖

同學在用FPGA做讀卡器,上位機準備用labview做,因爲不熟悉所以讓我用C#做個備份,備不時之需。

菜鳥級別就跑去給人家幫忙,越幫越忙。他的要求是自定義串口屬性,上位機發送命令,然後讀取每次8096bytes的回覆數據,然後利用接收到的數據畫圖,做一些統計和計算。自己做的過程中將問題分解了下:

1、串口讀取數據

2、讀取的串口數據存儲到txt中

3、在winform中畫圖

從實習開始就有接觸到串口,控制GSM模塊的時候有用過,自以爲比較有點認識。首先是發現原來串口的可選擇的波特率是與電腦的配置有關的。我的直接使用主機自帶的串口最大支持的波特率爲115200;然後通過USB轉串口可以支持最高的256000。接着直接將ReceivedBytesThreshold設置成了8096,準備坐等其成。貌似需要加大ReadBufferSize。

直到sleep 2秒才能保證正確的數據接收,而且還會出現完成數據接收後還會觸發接收事件的現象,接收到的明顯是0,搞不清楚。去查各種C#書,想要看明白串口操作,結果發現C#貌似對網絡支持的很強大的樣子,串口幾乎沒有提及,發帖,qq羣 有的也就是之言片語。有說是開個線程專門去接收的,但是接收事件不是本身就是一個單獨的線程嗎。最後通過一直讀知道收到足夠的數據的方式加快了點速度。 但是同學的labview做出來的沒有什麼明顯的需要接收時間的問題,看來串口操作還是沒設置好啊

當還在讀數據的時候關閉串口,會報錯,添加了個標誌。


將接收數據存儲下來,網上抄襲各種代碼,結果總是得到亂碼。不解啊,看了下之前的一個人家的代碼,原來少了碼制轉換。總算可以存儲了。

畫圖,折騰了好久才知道是用graphics來做的,panel上面做圖片問題老是會有閃爍的很厲害的問題。picturebox的繪製不是說畫上去馬上就表現出來的。

順便貼上自己粗略的代碼,記憶一下。

using System;
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.IO;
using System.IO.Ports;
using System.Threading;


namespace UpperConputer
{
    public partial class Form1 : Form
    {
        private SerialPort m_serialport = new SerialPort();
        //private string fullData = "";
        private byte[] fulldata = new byte[8005];
        private List<byte> buffer = new List<byte>(8005);
        private uint[] intData = new uint[2001];
        private bool serialPortMark=false;
        private string xmark;
        public Graphics graphicsObject;
        private Thread threadshow;
        private bool portclosing = false;
        private bool localPortListening = false;
        private delegate void showdelegate();
        private DateTime begin, end;
        
        
        //private string selectedFrequency;
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            
            comboBoxSerialPortN.SelectedIndex = 3;
            comboBoxStopBit.SelectedIndex = 0;
            comboBoxDataBit.SelectedIndex = 3;
            comboBoxBuadRate.SelectedIndex = 6;
            comboBoxSelF.SelectedIndex = 7;
            //設置雙緩衝
            this.SetStyle(ControlStyles.UserPaint, true);
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            //newthread=new Thread(new ThreadStart(rec));
            //newthread.Start();
            CreateImage();        
            
        }
        private void showtext(string str)
        {
            textBox1.Text = str;
        }
   
        private void initializeSerialPort()
        {
            m_serialport.PortName = comboBoxSerialPortN.Text;
            m_serialport.BaudRate =Convert.ToInt32( comboBoxBuadRate.Text);
            m_serialport.DataBits = Convert.ToInt16(comboBoxDataBit.Text);
            m_serialport.Parity = Parity.None;
            //m_serialport.ReadTimeout = 1000;
            switch (comboBoxStopBit.Text)
            {
                case"1":
                    m_serialport.StopBits = StopBits.One;
                    break;
                case"1.5":
                    m_serialport.StopBits = StopBits.OnePointFive;
                    break;
                case"2":
                    m_serialport.StopBits = StopBits.Two;
                    break;
            }
            //can used
            m_serialport.ReadBufferSize = 10000;
            m_serialport.ReceivedBytesThreshold = 1;


            //thread_com_read();


        }
         private void m_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
           
            if (portclosing) return;
            try
            {
                
                localPortListening = true;
                byte firstByte = Convert.ToByte(m_serialport.ReadByte());
               
                int bytesRead = m_serialport.BytesToRead;
                byte[] bytesData = new byte[bytesRead + 1];
              
                bytesData[0] = firstByte;
                int count = buffer.Count();
                for (int i = 1; i <= bytesRead; i++)
                {
                    bytesData[i] = Convert.ToByte(m_serialport.ReadByte());


                }
                
                //MessageBox.Show(Convert.ToString(bytesRead));
                for (int j = 0; j <=bytesRead; j++)
                {
                    buffer.Add(bytesData[j]);
                }
                count = buffer.Count();
                if (buffer.Count() == 8004)
                {
                    for (int i = 0; i < 8004; i++)
                    {
                        fulldata[i] = buffer[i];
                    }
                    for (int i = 0, j = 0; i < 8004; i += 4, ++j)
                    {
                        intData[j] = System.BitConverter.ToUInt32(fulldata, i);
                    }
                    //Thread.Sleep(100);
                    drawImage(intData);
                    //Thread.Sleep(100);
                    buffer.Clear();
                 }


                string str = byteToHexStr(bytesData);
                File.WriteAllText("data1.txt", str);
           }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message+" At datareceived");
                //處理超時錯誤
            }
            finally
            {
                localPortListening = false;
            }


           //can used
            //if (portclosing) return;
            //try
            //{
            //    localPortListening = true;
            //    System.Threading.Thread.Sleep(2000);
            //    byte[] receivedData = new byte[m_serialport.BytesToRead];
            //    int count = m_serialport.Read(receivedData, 0, m_serialport.BytesToRead);
            //    //m_serialport.DiscardInBuffer();//清空接收緩衝區數據
            //    if (count == 8004)
            //    {
            //        for (int i = 0, j = 0; i < 8004; i += 4, ++j)
            //        {
            //            intData[j] = System.BitConverter.ToUInt32(receivedData, i);
            //        }
            //    }
            //    else
            //    {
            //        return;
            //    }
            //    for (int i = 0, j = 0; i < 8004; i += 4, ++j)
            //    {
            //        intData[j] = System.BitConverter.ToUInt32(receivedData, i);
            //    }
            //    drawImage(intData);
            //}
            //catch (Exception ex)
            //{
            //    MessageBox.Show(ex.Message);
            //}
            //finally
            //{
            //    localPortListening = false;
            //}
        }
         public string byteToHexStr(byte[] bytes)
         {
             string returnStr = "";
             if (bytes != null)
             {
                 for (int i = 0; i < bytes.Length; i++)
                 {
                     returnStr += bytes[i].ToString("X2");
                 }
             }
             return returnStr;
         }
        private void drawImage(uint[] intData)
        {
            float xcoordone,xcoordtwo;
            double xmax,ymax;
            double y1, y2;
            int count = 0;
            double centreFrequency;
            Graphics g = Graphics.FromImage(pictureBox1.Image);
            //pictureBox1.Refresh();
            //Graphics g = pictureBox1.CreateGraphics();
            if (xmark == "0")
            {
                xcoordone = 40;
                g.DrawString("0",new Font("Arial",16),Brushes.Red,new Point(30,378));
            }
            else
            {
                xcoordone = 100;
                g.DrawString(xmark, new Font("Arial", 16), Brushes.Red, new PointF(90, 378));
            }
            xmax = xcoordone;
            ymax = 0;
            xcoordtwo = xcoordone + (float)0.3;
            Pen mypen = new Pen(Brushes.Blue, 1);
            Pen dashLinePen = new Pen(Brushes.Red, 1);
            dashLinePen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
            //draw every point and using line to link each other
            for (int i = 0; i < intData.Count()-1; ++i)
            {


                y1 = (double)intData[i] / 16777216 * 300;
                y2=(double)intData[i+1]/16777216*300;
                // obtain the max point
                if (ymax < y1)
                {
                    ymax = y1;
                    xmax = xcoordone;
                    count=i;
                }
                g.DrawLine(new Pen(Color.Black,1),new PointF(xcoordone,(float)(378 - y1)),new PointF(xcoordtwo, (float)(378 - y2)));
                xcoordone += (float)0.3;
                xcoordtwo += (float)0.3;
            }
            //畫x軸第二個標示點
            int nextxcoord = int.Parse(xmark);
            nextxcoord=nextxcoord+2;
            g.DrawString(Convert.ToString( nextxcoord),new System.Drawing.Font("Arial",16),Brushes.Red,new PointF(xcoordone,378));
            //畫最高頻率線並加註釋
            nextxcoord -= 2;
            g.DrawLine(dashLinePen, (float)xmax, (float)(378-ymax), (float)xmax, 378);
            centreFrequency=nextxcoord+count*0.001;
            g.DrawString("f:" + Convert.ToString(centreFrequency),new Font("Arial",16), Brushes.Red, (float)xmax, 388);
            //尋找0.707兩點,畫線,計算Q值
            mypen.Dispose();
            dashLinePen.Dispose();
            g.Dispose();
            showdelegate show = new showdelegate(showpicture);
            this.Invoke(show);
            
            
        }
        private void showpicture()
        {
            pictureBox1.Visible = false;
            pictureBox1.Visible = true;
        }
        private void CreateImage()
        {
            pictureBox1.Refresh();
            int height = 418, width = 820;
            Image image = new Bitmap(820, 418);//定義圖象大小
            Graphics g = Graphics.FromImage(image); //定義gdi繪圖對象
            Pen mypen = new Pen(Brushes.DeepSkyBlue, 1);
            try
            {
                g.Clear(Color.White);//清除整個繪圖面並以指定背景色填充。 
                //g.FillRectangle(Brushes.WhiteSmoke, 0, 0, width, height);//填充由一對座標、一個寬度和一個高度指定的矩形的內部。 
                //畫邊框
                g.DrawRectangle(mypen, 0, 0, width - 9, height - 3);//繪製由座標對、寬度和高度指定的矩形。 
                g.DrawLine(new Pen(Brushes.Black, 1), 40, height - 40, width - 40, height - 40);//x軸
                g.DrawLine(new Pen(Brushes.Black, 1), width - 50, height - 30, width - 40, height - 40);//箭頭
                g.DrawLine(new Pen(Brushes.Black, 1), width - 50, height - 50, width - 40, height - 40);
                g.DrawLine(new Pen(Brushes.Black, 1), 40, height - 40, 40, 40);//y軸
                g.DrawLine(new Pen(Brushes.Black, 1), 30, 50, 40, 40);
                g.DrawLine(new Pen(Brushes.Black, 1), 50, 50, 40, 40);
                g.DrawString("頻率、Q值測試圖", new Font("宋體", 16), Brushes.Green, new PointF(300, 20));
                g.DrawString("電壓值", new Font("Arial", 16), Brushes.Aqua, new PointF(50, 40));
                g.DrawString("頻率", new Font("宋體", 16), Brushes.Aqua, new PointF(width - 90, height - 30));
                g.DrawString("中心頻率:", new Font("宋體", 16), Brushes.Aqua, new PointF(width - 190, 30));
                g.DrawString("Q值:", new Font("宋體", 16), Brushes.Aqua, new PointF(width - 140, 50));
                mypen.Dispose();
                g.Dispose();
                pictureBox1.Image = image;
            }
            catch
            { }
        }


        private void button1_Click(object sender, EventArgs e)
        {
            if (!m_serialport.IsOpen)
            {
                MessageBox.Show("打開串口!");
                return;
            }
            if (comboBoxSelF.Text == "")
            {
                MessageBox.Show("請選擇測試頻率!");
            }
            else
            {
                xmark = comboBoxSelF.Text;
                m_serialport.Write(comboBoxSelF.Text);
            }
        }


        private void button2_Click(object sender, EventArgs e)
        {
            
        }


        private void buttonOpen_Click(object sender, EventArgs e)
        {
            try
            {


                if (!m_serialport.IsOpen)
                {
                    //CreateImage();
                    initializeSerialPort();
                    m_serialport.Close();
                    m_serialport.Open();
                    //thread_com_read();
                    m_serialport.DataReceived += new SerialDataReceivedEventHandler(m_DataReceived);
                    serialPortMark = true;
                    buttonOpen.Text = "關閉串口";
                }
                else
                {
                    portclosing = true;
                    while (localPortListening) Application.DoEvents();


                    serialPortMark = false;
                    buttonOpen.Text = "打開串口";
                    m_serialport.DataReceived -= new SerialDataReceivedEventHandler(m_DataReceived);
                    m_serialport.Close();
                    portclosing = false;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        private void buttonRefresh_Click(object sender, EventArgs e)
        {
            CreateImage();


        }    

     }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章