C#中的WinFrom技術實現串口通訊助手(附源碼)


C#中的WinFrom技術實現串口通訊助手(附源碼)

  實現的功能:
1、實現自動加載可用串口。
2、打開串口,並且使用C#狀態欄顯示串口的狀態。
3、實現了串口的接收數據和發送數據功能。
4、串口使用定時器進行定時發送數據。
5、可以打開文件夾,選擇文件進行發送,並且將發送文件的內容顯示在發送文本框中。
6、可以清空發送和接收文本框中的內容。
7、可以實時計算發送和接收的字節數。
8、實現打開文件夾保存發送和接收的文件內容(目前只支持.txt文件)。
9、實時顯示當前時間。
  功能演示
1、界面功能介紹:
在這里插入圖片描述
2、打開串口演示:
在這里插入圖片描述
3、發送數據演示:
在這里插入圖片描述
動態演示
在這里插入圖片描述
4、定時發送數據演示:
在這里插入圖片描述
動態演示
在這里插入圖片描述
5、發送文件內容演示:
在這里插入圖片描述
動態演示
在這里插入圖片描述
6、接收數據演示:
在這里插入圖片描述
動態演示
在這里插入圖片描述
7、保存數據演示:
在這里插入圖片描述
動態演示
在這里插入圖片描述

主要使用的技術:

1、數據保存和讀取。
2、定時器的操作。
3、串口模塊的使用。
4、委托和事件解決線程沖突問題。

工程源代碼:

using System;
using System.Drawing;
using System.IO;   // 導入輸入輸出文件框
using System.IO.Ports;   // 串口模塊
using System.Text;
using System.Windows.Forms;

namespace MainSender
{
    // 解決線程訪問問題
    public delegate void SerialPortEventHandler(Object sender, SerialPortEventArgs e);    // 定義委托

    
    public partial class SerialDebug : Form
    {
        private string FilePath = null;    // 打開文件路徑

        private object thisLock = new object();    // 鎖住線程

        public event SerialPortEventHandler comReceiveDataEvent = null;  // 定義串口接收數據響應事件
        // 數據狀態
        private static int sendCount = 0;    // 發送數據量
        private static int receCount = 0;    // 接收數據量


        public SerialDebug()
        {
            InitializeComponent();
            InitializeSerialSet(); // 初始化串口設置          

        }

        /// <summary>
        /// 串口初始化設置
        /// </summary>

        public void InitializeSerialSet()
        {
            InitializePorts();   // 初始化串口號
            // 初始化波特率
            comboBox_BandRate.Text = comboBox_BandRate.Items[6].ToString();
            // 初始化校驗位
            comboBox_Check.Text = comboBox_Check.Items[0].ToString();
            // 初始化數據位
            comboBox_Data.Text = comboBox_Data.Items[0].ToString();
            // 初始化停止位
            comboBox_Stop.Text = comboBox_Stop.Items[0].ToString();

        }

        /// <summary>
        /// 可用串口掃描,並且顯示
        /// </summary>
        public void InitializePorts()
        {
            comboBox_Serial.Items.Clear();   // 清空原來的信息
            // 返回可用串口號,形式:COM3
            string[] arraysPostsNames = SerialPort.GetPortNames();  // 獲取所有可用的串口號

            // 檢查串口號是否正確
            if (arraysPostsNames.Length > 0)
            {

                Array.Sort(arraysPostsNames);  // 使用默認進行排序,從小到大腎虛
                for (int i = 0; i < arraysPostsNames.Length; i++)
                {
                    comboBox_Serial.Items.Add(arraysPostsNames[i]);  // 將所有可用串口加載到串口顯示框當中
                }
                comboBox_Serial.Text = arraysPostsNames[0];   // 默認選擇第一個串口

                comboBox_Serial.Enabled = true;   // 打開選擇框
                // 設置狀態欄屬性
                toolStripStatus_Port.Text = "串口號:" + comboBox_Serial.Text;  // 設置狀態欄的情況                   
                toolStripStatus_Port.ForeColor = Color.Black; // 設置為紅色

            }
            else
            {
                toolStripStatus_Port.Text = "沒有可用串口";  // 設置狀態欄的情況                   
                toolStripStatus_Port.ForeColor = Color.Red; // 設置為紅色
                comboBox_Serial.Text = "None";   // 提示沒有可用串口
                comboBox_Serial.Enabled = false;   // 禁止打開串口選擇框
            }
        }

        /// <summary>
        /// 串口讀取數據響應方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void serialPortMonitor_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            ReceiveData();
        }

        private void SerialDebug_Load(object sender, EventArgs e)
        {

            comReceiveDataEvent += new SerialPortEventHandler(ComReceiveDataEvent);  // 訂閱事件
            toolStripStatus_Time.Text = "時間:" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss");  // 顯示當前時間
        }

        public void ComReceiveDataEvent(Object sender, SerialPortEventArgs e)
        {

            if (this.InvokeRequired)
            {
                try
                {
                    Invoke(new Action<Object, SerialPortEventArgs>(ComReceiveDataEvent), sender, e);
                }
                catch (Exception)
                {

                }
                return;
            }


            if (richTextBox_Receive.Text.Length > 0)
            {
                richTextBox_Receive.AppendText(" ");  // 中間使用 隔開,也可以使用-隔開
            }
            richTextBox_Receive.AppendText(System.Text.Encoding.Default.GetString(e.receivedBytes));

            // 更新狀態顯示框
            receCount += e.receivedBytes.Length;
            toolStripStatus_recestatus.Text = "收到數據: " + receCount.ToString();


        }
        /// <summary>
        /// 串口選擇框改變
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Select_Ports_Change(object sender, EventArgs e)
        {
            // 設置狀態欄屬性
            toolStripStatus_Port.Text = "串口號:" + comboBox_Serial.Text;  // 設置狀態欄的情況                   
            toolStripStatus_Port.ForeColor = Color.Black; // 設置為黑色
        }
        /// <summary>
        /// 更新狀態欄
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Update_StatusTime(object sender, EventArgs e)
        {
            
            toolStripStatus_Time.Text = "時間:" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss");  // 顯示當前時間 
        }
        /// <summary>
        /// 保存文件加載方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SaveData_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveDataSend = new SaveFileDialog();
            saveDataSend.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);   // 獲取文件路徑
            saveDataSend.Filter = "*.txt|txt file";   // 文本文件
            saveDataSend.DefaultExt = ".txt";   // 默認文件的形式
            saveDataSend.FileName = "SendData.txt";   // 文件默認名

            if (saveDataSend.ShowDialog() == DialogResult.OK)   // 顯示文件框,並且選擇文件
            {
                FilePath = saveDataSend.FileName;   // 獲取文件名
                // 參數1:寫入文件的文件名;參數2:寫入文件的內容
                try
                {
                    System.IO.File.WriteAllText(FilePath, richTextBox_Send.Text);   // 向文件中寫入內容
                }
                catch
                {
                    MessageBox.Show("保存文件失敗", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); ;
                }

            }

        }
        /// <summary>
        /// 選擇發送文件響應函數
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void textBox_Filepath_Click(object sender, EventArgs e)
        {
            OpenFileDialog fileDialog = new OpenFileDialog();
            fileDialog.Multiselect = false;   // 是否可以選擇多個文件
            fileDialog.Title = "請選擇文件";     // 標題
            fileDialog.Filter = "所有文件(*.*)|*.*";   // 顯示所有文件
            if (fileDialog.ShowDialog() == DialogResult.OK)   // 打開文件選擇框
            {
                FilePath = fileDialog.FileName;   // 絕對路徑
                textBox_Filepath.Text = FilePath;   // 在窗口中顯示文件路徑
            }
            checkBox_Sendfile.Checked = true;   // 設置發送文件框選項狀態
            ReadFile(FilePath);   // 將文件內容顯示在發送框當中
        }

        /// <summary>
        /// 將文件內容顯示在發送數據顯示框中
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void ReadFile(string filepath)
        {
            try
            {
                richTextBox_Send.Text = "";  // 清空顯示框

                StreamReader sr = new StreamReader(filepath, Encoding.Default);
                string content;
                while ((content = sr.ReadLine()) != null)   // 按行讀取顯示在發送數據框中
                {
                    richTextBox_Send.Text += (content.ToString() + "\r\n");   // ReadLine默認不會讀取換行符
                }
            }
            catch (Exception)
            {

            }

        }

        /// <summary>
        /// 清除發送數據
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button_ClcSendData_Click(object sender, EventArgs e)
        {
            richTextBox_Send.Text = "";  // 清空顯示框
            sendCount = 0;
            toolStripStatus_sendstatus.Text = "發送數據:" + sendCount.ToString();
        }
        /// <summary>
        /// 清除接收數據
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button_ClcReceData_Click(object sender, EventArgs e)
        {
            richTextBox_Receive.Text = "";   // 清空接收數據
            receCount = 0;
            toolStripStatus_recestatus.Text = "收到數據:" + receCount.ToString();
        }
        /// <summary>
        /// 發送數據按鍵點擊響應函數
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button_SendData_Click(object sender, EventArgs e)
        {
            string senddata = richTextBox_Send.Text;
            byte[] data = System.Text.Encoding.Default.GetBytes(senddata);   // 將發送的數據轉化為字節數組            
            SendData(data);    // 發送數據
            sendCount += senddata.Length;
            toolStripStatus_sendstatus.Text = "發送數據:" + sendCount.ToString();

        }
        /// <summary>
        /// 保存發送數據,保存發送數據菜單響應函數
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MenuItem_ReceData_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveDataSend = new SaveFileDialog();
            saveDataSend.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);   // 獲取文件路徑
            saveDataSend.Filter = "*.txt|txt file";   // 文本文件
            saveDataSend.DefaultExt = ".txt";   // 默認文件的形式
            saveDataSend.FileName = "ReceData.txt";   // 文件默認名

            if (saveDataSend.ShowDialog() == DialogResult.OK)   // 顯示文件框,並且選擇文件
            {
                FilePath = saveDataSend.FileName;   // 獲取文件名
                // 參數1:寫入文件的文件名;參數2:寫入文件的內容
                try
                {
                    System.IO.File.WriteAllText(FilePath, richTextBox_Receive.Text);   // 向文件中寫入內容
                }
                catch
                {
                    MessageBox.Show("保存文件失敗", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); ;
                }

            }
        }
        /// <summary>
        /// 串口狀態響應函數
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button_OK_Click(object sender, EventArgs e)
        {
            if (serialPort1 == null)
            {
                return;
            }

            if (serialPort1.IsOpen == false)
            {
                serialPort1.PortName = comboBox_Serial.Text;
                serialPort1.BaudRate = Convert.ToInt32(comboBox_BandRate.Text);
                serialPort1.Parity = (Parity)Enum.Parse(typeof(Parity), comboBox_Check.Text);   // 強制類型轉換
                serialPort1.DataBits = Convert.ToInt32(comboBox_Data.Text);
                serialPort1.StopBits = (StopBits)Enum.Parse(typeof(StopBits), comboBox_Stop.Text);
                try
                {
                    serialPort1.Open();

                    // 設置按鍵的使用權限
                    comboBox_Serial.Enabled = false;
                    comboBox_BandRate.Enabled = false;
                    comboBox_Check.Enabled = false;
                    comboBox_Data.Enabled = false;
                    comboBox_Stop.Enabled = false;
                    button_Refresh.Enabled = false;

                    button_SendData.Enabled = true;
                    checkBox_SendData.Enabled = true;
                    textBox_selectTime.Enabled = true;
                    checkBox_Sendfile.Enabled = true;
                    textBox_Filepath.Enabled = true;

                    // 打開屬性變為關閉屬性
                    button_OK.Text = "關閉串口";

                    toolStripStatus_Port.Text = "連接串口:" + comboBox_Serial.Text;
                    toolStripStatus_Port.ForeColor = Color.Green; // 設置為綠色

                }
                catch (Exception)
                {
                    toolStripStatus_Port.Text = "連接失敗:" + comboBox_Serial.Text;
                    toolStripStatus_Port.ForeColor = Color.Red; // 設置為紅色
                    MessageBox.Show("串口連接失敗!\r\n可能原因:串口被占用", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }


            }
            else
            {
                serialPort1.Close();   // 關閉串口

                // 設置按鍵的使用權限
                comboBox_Serial.Enabled = true;
                comboBox_BandRate.Enabled = true;
                comboBox_Check.Enabled = true;
                comboBox_Data.Enabled = true;
                comboBox_Stop.Enabled = true;
                button_Refresh.Enabled = true;

                button_SendData.Enabled = false;
                checkBox_SendData.Enabled = false;
                textBox_selectTime.Enabled = false;
                checkBox_Sendfile.Enabled = false;
                textBox_Filepath.Enabled = false;

                // 打開屬性變為關閉屬性
                button_OK.Text = "打開串口";
                toolStripStatus_Port.Text = "斷開連接:" + comboBox_Serial.Text;
                toolStripStatus_Port.ForeColor = Color.Red; // 設置為紅色

            }

        }
        /// <summary>
        /// 向串口中發送數據
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public bool SendData(byte[] data)
        {
            if (serialPort1 == null)
            {
                return false;
            }
            if (serialPort1.IsOpen == false)
            {
                return false;
            }

            try
            {
                serialPort1.Write(data, 0, data.Length);
            }
            catch (Exception)
            {
                //提示信息
                MessageBox.Show("數據發送失敗!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return false;
            }

            return true;
        }
        /// <summary>
        /// 串口接收數據
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public bool ReceiveData()
        {

            if (serialPort1 == null)
            {
                return false;
            }
            if (serialPort1.IsOpen == false)
            {
                return false;
            }
            if (serialPort1.BytesToRead <= 0)   // 串口中沒有數據
            {
                return false;
            }
            lock (thisLock)   // 鎖住串口
            {
                int len = serialPort1.BytesToRead;
                byte[] data = new Byte[len];
                try
                {
                    serialPort1.Read(data, 0, len);   // 向串口中讀取數據
                }
                catch (Exception)
                {
                    MessageBox.Show("數據接收失敗!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return false;
                }


                SerialPortEventArgs args = new SerialPortEventArgs();
                args.receivedBytes = data;
                if (comReceiveDataEvent != null)
                {
                    comReceiveDataEvent.Invoke(this, args);
                }

            }


            return true;
        }
        /// <summary>
        /// 刷新串口參數
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button_Refresh_Click(object sender, EventArgs e)
        {
            InitializeSerialSet(); // 刷新串口設置
        }
        /// <summary>
        /// 定時發送數據
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void timerSend_Tick(object sender, EventArgs e)
        {
            if (checkBox_SendData.Checked)
            {
                string datastr = richTextBox_Send.Text;
                if (datastr == "")
                {
                    return;
                }
                timerSend.Interval = int.Parse(textBox_selectTime.Text);  // 將字符串轉化為整型數字
                byte[] data = System.Text.Encoding.Default.GetBytes(datastr);   // 字符串轉化為字節數組
                SendData(data);
                sendCount += datastr.Length;
                toolStripStatus_sendstatus.Text = "發送數據:" + sendCount.ToString();

                // 控件設置
                button_SendData.Enabled = false;

            }
            else
            {
                button_SendData.Enabled = true;
            }
        }
        /// <summary>
        /// 退出菜單
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MenuItem_Quit_Click(object sender, EventArgs e)
        {
            this.Close();   // 關閉窗體,然后退出
        }
        /// <summary>
        /// 關於菜單
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MenuItem_About_Click(object sender, EventArgs e)
        {
            About about = new About();
            about.Show();   // 顯示關於窗體

        }
    }

    public class SerialPortEventArgs : EventArgs
    {
        public byte[] receivedBytes = null;   // 用來接收串口讀取的數據
    }

}

如果你對本工程感興趣可以下載源代碼


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM