C#做一個簡單的進行串口通訊的上位機

來源:互聯網
上載者:User

標籤:get   sele   try   多少   光照   close   exce   store   處理   

C#做一個簡單的進行串口通訊的上位機 1、上位機與下位機

上位機相當於一個軟體系統,可以用於接收資料、控制資料。即可以對接收到的資料直接發送操控命令來操作資料。上位機可以接收下位機的訊號。下位機是一個控制器,是直接控制裝置擷取裝置狀況的電腦。上位機發出的命令首先給下位機,下位機再根據此命令解釋成相應時序訊號直接控制相應裝置。下位機不時讀取裝置狀態資料(一般為類比量),轉換成數字訊號反饋給上位機。上位機不可以單獨使用,而下位機可以單獨使用。

2、串口通訊

串口相當於硬體類型的介面。比如無線感測節點發送訊號到匯聚節點,匯聚節點通過串口將資料傳到電腦中的上位機中,上位機接收資訊,並處理。

串口是按位(bit)發送和接收位元組。串口通訊最重要的參數是傳輸速率、資料位元、停止位和同位。對於兩個進行通訊的連接埠,這些參數必須匹配。

a,傳輸速率:這是一個衡量符號傳輸速率的參數。

b,資料位元:這是衡量通訊中實際資料位元的參數。

c,停止位:用於表示單個包的最後一位。典型的值為1,1.5和2位。

d,同位位元:在串口通訊中一種簡單的檢錯方式。

3、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 serial2{ public partial class Form1 : Form { SerialPort s = new SerialPort(); //執行個體化一個串口對象,在前端控制項中可以直接拖過來,但最好是在後端代碼中寫代碼,這樣複製到其他地方不會出錯。s是一個串口的控制代碼 public Form1() { InitializeComponent(); Control.CheckForIllegalCrossThreadCalls = false; //防止跨線程訪問出錯,好多地方會用到 button1.Text = "開啟串口"; int[] item = { 9600,115200}; //定義一個Item數組,遍曆item中每一個變數a,增加到comboBox2的列表中 foreach (int a in item) { comboBox2.Items.Add(a.ToString()); } comboBox2.SelectedItem = comboBox2.Items[1]; //預設為列表第二個變數 } private void Form1_Load(object sender, EventArgs e) //表單事件要先配置連接埠資訊。 { string[] ports = SerialPort.GetPortNames(); comboBox1.Items.AddRange(ports); comboBox1.SelectedItem=comboBox1.Items[0]; //Array.Sort(ports); } 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 = "關閉串口"; //MessageBox.Show("串口已開啟"); } else { s.Close(); s.DataReceived -= s_DataReceived; button1.Text = "開啟串口"; } } catch (Exception ee) { MessageBox.Show(ee.ToString()); } } void s_DataReceived(object sender, SerialDataReceivedEventArgs e) //資料接收事件,讀到資料的長度賦值給count,如果是8位(節點內部編程規定好的),就申請一個byte類型的buff數組,s控制代碼來讀資料 { 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) //讀取Buff中存的資料,轉換成顯示的十六進位數 { str += item.ToString("X2")+" "; } richTextBox1.Text =System.DateTime.Now.ToString()+": "+ str + "\n" + richTextBox1.Text; //這是跨線程訪問richtextbox,原程式和DataReceived事件是兩個不同的線程同時在執行 if (buff[0] == 0x04) //如果節點是04發來的資料 { ID.Text = buff[0].ToString(); //這下面是上位機右邊那一段,用來顯示處理好的資料的溫度、濕度、光照、灰塵、ID資訊的。buff【0】中存的是資料的ID資訊,顯示在ID的Label上面 switch (buff[2]) //判斷資料類型 buff【0】和buff【1】代表ID的低位和高位,同理2和3代表資料類型的低位和高位,當2和3的值為1時,4和5代表溫度,6和7代表濕度; { case 0x01: //當2和3的值為1,4和5是溫度,6和7是濕度 { Tem.Text = (buff[5] * 4 + buff[4] * 0.05 - 30).ToString(); Hum.Text = (buff[6] + buff[7]).ToString(); break; } case 0x02://6和7是光照 { Light.Text = (buff[6] + buff[7]).ToString(); break; } case 0x04://6和7是灰塵 { Dust.Text = (buff[6] + buff[7]).ToString(); break; } default: break; } } } } 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); } } 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);//這裡只顯示04節點的資訊 s.Write(buff, 0, count); } }}

(以上規則均是本實驗室節點內部自訂規則,測試的,外面的相應要改)

4、結果

5、補充四點知識

1)在程式可能會遇到錯誤的地方,用try+兩個Tab鍵,將代碼寫入try中。比如本例子中的代碼:

 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 = "關閉串口"; //MessageBox.Show("串口已開啟"); } else { s.Close(); s.DataReceived -= s_DataReceived; button1.Text = "開啟串口"; } } catch (Exception ee) { MessageBox.Show(ee.ToString()); } }

如果代碼沒有寫入try中,則可能出現的一種情況是比如有兩個上位機,同時佔用同一個串口,則就會衝突,會出錯。程式就會終止,整個進程結束。而如果寫入try中,並且把拋出異常的catch代碼執行個體化,即捕獲異常要執行個體化一個控制代碼,這樣程式遇到error就不會終止,而會出現報錯的原因。如,我的這個上位機和網上下載的一個上位機同時佔用COM3串口(網上下載的先佔用COM3),這時我的上位機在開啟串口時會出現報錯。

2)就我這個上位機而言,需要有開啟串口和關閉串口兩個button按鈕,但是考慮到佔地方,當然最重要的還是如果用兩個按鈕來表示,當你按下開啟串口,如果忘了是否開啟,則是看不出來是不是開啟的,所以可以合并為一個button控制項。(代碼還是用上面那一段的代碼)。(感覺很神奇啊)。在button1_Click事件中,先點擊button,如果串口是關閉的,則開啟串口,然後把button1.Text的值賦值為“關閉串口”,如果串口本來是關閉的,則點擊按鈕會把button1.Text的值賦值為“開啟串口”,同時把接收的資料清空。感覺這個方法真的很不錯!嘿嘿

3)當輸入一個變數或方法什麼的,它所有有的會自動出現在一個列表,這時,“正方體”代表“方法”,“小鉗子”代表“變數”,“閃電”代表“事件”。

4) 產生對象的事件時

比如輸入s.自動會出現DataReceived事件,再輸入“+=”就會有如提示,按Tab鍵。然後又會如提示


再次按tab鍵,就會自動產生DataReceived事件處理函數。

C#做一個簡單的進行串口通訊的上位機

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.