中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

利用C# 項目實現一個串口監視上位機功能

發布時間:2020-11-21 14:42:48 來源:億速云 閱讀:181 作者:Leah 欄目:開發技術

這篇文章將為大家詳細講解有關利用C# 項目實現一個串口監視上位機功能,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

  實現上位機和下位機之間的通信,通常使用的是串口通信,接下來實現一個通過上位機和串口調試助手來完成串口通信測試。

  首先創建一個WInfrom窗體應用工程文件,在創建好的工程下面,通過工具箱中已有的控件完成界面的搭建,如下圖所示,為了方便初學者容易看懂程序,下圖將控件的命名一并標注出來:

利用C# 項目實現一個串口監視上位機功能

  直接進入正題,將完整的工程代碼黏貼出來:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
using System.Diagnostics;

namespace Tem_Hum_Monitorring
{

 public partial class Form1 : Form
 {
 //實例化串口
 SerialPort s = new SerialPort();

 public Form1()
 {
  InitializeComponent();
  Control.CheckForIllegalCrossThreadCalls = false;
  button1.Text = "打開串口";
  int[] item = { 9600,115200}; //遍歷
  foreach (int a in item)
  {
  comboBox2.Items.Add(a.ToString());
  }
  comboBox2.SelectedItem = comboBox2.Items[1];
 }

 private void Form1_Load(object sender, EventArgs e)
 {
  portInit();
 }

 /// <summary>
 /// 串口初始化
 /// </summary>
 private void portInit()
 {
  string[] ports = SerialPort.GetPortNames();
  comboBox1.Items.AddRange(ports);
  comboBox1.SelectedItem = comboBox1.Items[0];
 }

 #region 開關串口
 private void button1_Click(object sender, EventArgs e)
 {
  try
  {
  if (!s.IsOpen)
  {
   s.PortName = comboBox1.SelectedItem.ToString();
   s.BaudRate = Convert.ToInt32(comboBox2.SelectedItem.ToString());
   s.Open();
   s.DataReceived += s_DataReceived; //"+="代表指定響應事件時要調用的方法
   button1.Text = "關閉串口";
  }
  else
  {
   s.Close();
   s.DataReceived -= s_DataReceived;
   button1.Text = "打開串口";
  }
  }
  catch(Exception ee)
  {
  MessageBox.Show(ee.ToString());
  }
 }
 #endregion

 #region 串口接收
 void s_DataReceived(object sender, SerialDataReceivedEventArgs e)
 {
  int count = s.BytesToRead;
  string str = null;
  if (count == 8)
  {
  //數據解析
  byte[] buff = new byte[count];
  s.Read(buff, 0, count);
  foreach (byte item in buff)
  {
   str += item.ToString("X2") + " ";
  }
  richTextBox1.Text = "[" + System.DateTime.Now.ToString() + "] " + str + "\n" + richTextBox1.Text;
  if (buff[0] == 0x04)
  {
   ID.Text = buff[0].ToString();
   switch (buff[2])
   {
   case 0x01:
    {
    Tem.Text = (buff[5] * 4 + buff[4] * 0.05 - 30).ToString();
    Hum.Text = (buff[6] + buff[7]).ToString();
    break;
    }
   case 0x02:
    {
    Light.Text = (buff[6] + buff[7]).ToString();
    break;
    }
   case 0x04:
    {
    Dust.Text = (buff[6] + buff[7]).ToString();
    break;
    }
   default:
    break;
   }
  }
  }
  else
  {
  //當接收數據不在設定的數據位范圍之內時,會出現接受到的數據一直保存在接收緩存區之內,后續每次接手數據都會將上一次的數據進行疊加,造成只能通過關閉串口的方法來清除緩沖區的數據
  s.DiscardInBuffer(); //丟棄來自串行驅動程序的接收緩沖區的數據
  }
 }
 #endregion

 #region 串口發送
 private void button3_Click(object sender, EventArgs e)
 {
  string[] sendbuff = richTextBox2.Text.Split();
  Debug.WriteLine("發送字節數:" + sendbuff.Length);
  foreach (string item in sendbuff)
  {
  int count = 1;
  byte[] buff = new byte[count];
  buff[0] = byte.Parse(item, System.Globalization.NumberStyles.HexNumber);
  s.Write(buff,0,count);
  }
 }
 #endregion

 private void button2_Click(object sender, EventArgs e)
 {
  int count = 1;
  byte[] buff = new byte[count];
  buff[0] = byte.Parse("04", System.Globalization.NumberStyles.HexNumber);
  s.Write(buff, 0, count);
 }
 }
}

  在Winfrom窗體設計中,實現串口可以通過工具箱中的串口控件來實現,不過一般推薦直接通過代碼來實例化串口,實例化串口需使用如下代碼來實現:

 //實例化串口
    SerialPort s = new SerialPort();

  串口初始化可以在窗體的Load函數中實現,以下初始化可以自動化取當前設備中的存在的串口,包括真實串口和虛擬串口:

private void Form1_Load(object sender, EventArgs e)
 {
  portInit();
 }

 /// <summary>
 /// 串口初始化
 /// </summary>
 private void portInit()
 {
  string[] ports = SerialPort.GetPortNames();
  comboBox1.Items.AddRange(ports);
  comboBox1.SelectedItem = comboBox1.Items[0];
 }

  通過對開關按鍵button1控件的點擊事件,實現串口的開關,通過對控件的文字修改,可以實現一個控件機能實現開又能實現關串口的作用:

#region 開關串口
 private void button1_Click(object sender, EventArgs e)
 {
  try
  {
  if (!s.IsOpen)
  {
   s.PortName = comboBox1.SelectedItem.ToString();
   s.BaudRate = Convert.ToInt32(comboBox2.SelectedItem.ToString());
   s.Open();
   s.DataReceived += s_DataReceived; //"+="代表指定響應事件時要調用的方法
   button1.Text = "關閉串口";
  }
  else
  {
   s.Close();
   s.DataReceived -= s_DataReceived;
   button1.Text = "打開串口";
  }
  }
  catch(Exception ee)
  {
  MessageBox.Show(ee.ToString());
  }
 }
 #endregion

  串口數據接收和數據解析,首先獲取數據接收緩存區數據的字節長度,通過確認長度是否是設定中的長度大小,如果是設定的8位數據長度則對接收的數據進行解析:

#region 串口接收
 void s_DataReceived(object sender, SerialDataReceivedEventArgs e)
 {
  int count = s.BytesToRead;
  string str = null;
  if (count == 8)
  {
  //數據解析
  byte[] buff = new byte[count];
  s.Read(buff, 0, count);
  foreach (byte item in buff)
  {
   str += item.ToString("X2") + " ";
  }
  richTextBox1.Text = "[" + System.DateTime.Now.ToString() + "] " + str + "\n" + richTextBox1.Text;
  if (buff[0] == 0x04)
  {
   ID.Text = buff[0].ToString();
   switch (buff[2])
   {
   case 0x01:
    {
    Tem.Text = (buff[5] * 4 + buff[4] * 0.05 - 30).ToString();
    Hum.Text = (buff[6] + buff[7]).ToString();
    break;
    }
   case 0x02:
    {
    Light.Text = (buff[6] + buff[7]).ToString();
    break;
    }
   case 0x04:
    {
    Dust.Text = (buff[6] + buff[7]).ToString();
    break;
    }
   default:
    break;
   }
  }
  }
  else
  {
  //當接收數據不在設定的數據位范圍之內時,會出現接受到的數據一直保存在接收緩存區之內,后續每次接手數據都會將上一次的數據進行疊加,造成只能通過關閉串口的方法來清除緩沖區的數據
  s.DiscardInBuffer(); //丟棄來自串行驅動程序的接收緩沖區的數據
  }
 }
 #endregion

  當接收到的數據長度不等于8的時候,將丟棄來自串行驅動程序的接收緩沖區的數據,接下來通過斷點調試來分析丟棄緩沖區和不丟棄緩沖區數據兩種情況進行仿真,分析如下幾點。

使用串口助手給上位機發送數據數據位長度為8位的數據,串口調試助手和上位機的終端的顯示界面如下,發送端數據和接收端數據一樣,并未出現異常:

利用C# 項目實現一個串口監視上位機功能

將串口調試助手發送數據位修改成9位之后,進行發送,可以發現上位機并未接收到相關的數據:

利用C# 項目實現一個串口監視上位機功能

接著修改串口調試助手的發送數據位,修改成8位,可以發現上位機尚未能接收到來自串口調試助手發來的數據,這是為什么呢?

利用C# 項目實現一個串口監視上位機功能

接下來將通過斷點逐步進行調試,來解釋是為啥上位機沒有接收到調試助手發來的數據,當串口調試助手發來的數據長度位9位時,通過監視器可以查看到接收緩沖器中的數據長度長度是9

利用C# 項目實現一個串口監視上位機功能

第一次點擊完發送之后,上位機未能成功接收到數據,我們就會好奇,并且一般都會點擊第二次、第三次、甚至一直點下去,觀察是否會出現啥異常現象,當點擊第二次時,通過監視窗口,可以觀察到到串口緩沖區的數據長度變成了18,這是因為緩沖區將上一次接收的數據給保留了下來并沒有刪除,就算下次發送的數據長度為8位的時候,也一樣是通過疊加的方式將其保存到緩沖區,這樣就會造成緩沖區的數據位長度會一直大于8;如果不通過s.DiscardInBuffer()方法丟棄來自串行驅動程序的接收緩沖區的數據,就只能通過關閉串口然后重新打開相應的串口來實現緩沖區的數據清除。

利用C# 項目實現一個串口監視上位機功能

使用s.DiscardInBuffer()對不符合長度的數據進行丟棄,實現的效果如下所示:

利用C# 項目實現一個串口監視上位機功能

關于利用C# 項目實現一個串口監視上位機功能就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

苏尼特左旗| 乌拉特前旗| 共和县| 亳州市| 湖口县| 内丘县| 丰镇市| 英吉沙县| 萨嘎县| 池州市| 延边| 华容县| 北宁市| 开封市| 乌审旗| 景德镇市| 五家渠市| 太仓市| 樟树市| 扶绥县| 通海县| 芷江| 廊坊市| 五大连池市| 石河子市| 汉中市| 华蓥市| 夏河县| 嘉黎县| 德庆县| 普兰店市| 垣曲县| 兴仁县| 沾化县| 文水县| 疏勒县| 祁阳县| 馆陶县| 大足县| 新营市| 莒南县|