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

2021-02-24 機器人配視覺

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事件處理函數。

文章來源:綜合網絡,如有侵權,聯繫刪除。

相關焦點

  • Matlab上位機開發(五)Matlab串口通信
    Matlab串口通信Matlab提供了串口通信的功能,串口通信的流程如下:1.1.創建串口對象創建一個串口對象的API如下:scom = serial('<串口號>');串口號為COM8的形式,這個API有個缺點:不能自動檢測目前電腦中存在中的串口。
  • 手把手教你用Labview寫一個串口上位機
    安裝LabVIEW軟體本文使用的是2018版本的,注意高版本軟體生成的程序低版本軟體無法打開。可以在官網下載也可以在文末下載。在LabVIEW的社區找到安裝包:ftp.ni.com/evaluation/labview/ekit/other/downloader/2018LV-WinChn.exe(複製到瀏覽器即可下載)。
  • QT5串口編程——編寫簡單的上位機
    在QT5中,串口通信是藉助一個QSerialPort的對象來實現的,在設置QSerialPort對象對串口的名稱、波特率、數據位、校驗位、停止位等參數後,方能對串口進行讀寫。下面,我總結了一下藉助QSerailPort對串口進行設置、打開、讀、寫和關閉的過程。
  • LabVIEW與RS232串口通信
    串口是一種常用的通信接口,許多儀器設備都採用串口進行通信,為了與這些儀器互聯,LabVIEW提供了VISA,實現LabVIEW與其他設備的串口通信
  • 怎麼用VB.NET進行串口通信
    、電路板、控制器、儀器儀表、軟體APP開發定製的(業務QQ2531263726),於是跟我說要把一個指紋模塊和他們公司的觸控螢幕結合起來做成一個系統,發來了資料看了一下,這個指紋模塊可以用串口和USB與上位機通信,為了做起來簡單一些優先選擇串口通信。
  • STM32串口通信基本原理
    常用的波特率有4800bps、9600bps、115200bps等。    在同步通訊中,數據信號所傳輸的內容絕大部分是有效數據,而異步通訊中會則會包含數據幀的各種標識符,所以同步通訊效率高,但是同步通訊雙方的時鐘允許誤差小,稍稍時鐘出錯就可能導致數據錯亂,異步通訊雙方的時鐘允許誤差較大。常見的串行通信接口
  • [ 附labview下載 ]LabVIEW與RS232串口通信
    通信是工業領域永恆的話題,前面我們以PLC為主,為大家分享了各種通信案例和方式,今天我們以Labview為例,來和大家說一說串口通訊,後續會繼續帶來MES系統中的數據採集——C#與條碼槍的串口通信串口是一種常用的通信接口,許多儀器設備都採用串口進行通信
  • LabVIEW串口通信詳解
    PCI-RS232一般至少能擴展2個串口,有些BT一點的可以擴展到8-16個,一堆線和接頭。轉接線和擴展卡一般是要裝驅動的。2,串口功能的確認在使用串口之前,最好先確認一下串口是否正常,特別是使用轉換接或擴展卡的。檢查的方法很簡單,就是將串口的2、3腳短接起來,腳是發送數據,2腳接收數據,就是這個串口自發自收。電腦上的串口軟體一般是用串口調試助手,很出名的,也好用。
  • 如何使用Python開發串口通訊上位機(一)
    用Python開發串口通訊型上位機,其實並非最優解,本系列更新只為個人學習與總結。如果有C語言底子,嵌入式層面的上位機開發,C++ Builder,C#才是更加好用的利器。什麼是上位機從事過嵌入式軟體開發或者工控機開發的,對上位機應該都不陌生。
  • C#串口編程示例
    上位機之間要進行數據通信的兩種方式都是基於串口的:上位機軟軟體開發主要包括以下兩種:1、Windows上位機(EXE可執行程序)在Windows上,最早用VB語言開發,後來由於C++的發展,採用MFC開發,近幾年,微軟發布了基於.NET框架的面向對象語言C#,更加穩定安全,再配合微軟強大的VS進行開發,效率奇高;另外,如果想要在Linux上跨平臺運行
  • C#上位機專題課程,計劃2月21號啟動
    應大部分學員要求,硬體家園啟動C#上位機專題教學。
  • 【原創】教你如何擁有自己的「串口」上位機
    對於串口工具想必大家也不陌生,比如sscom、putty、xshell等,做嵌入式的都會用到串口工具進行調試,8位的51單片機、32位的stm32
  • Qt 串口上位機開發《Rice 上位機 學習開發》
    前幾天分享了一個使用C#開發的串口上位機,那麼今天教你如何100行QT代碼實現一個串口上位機。
  • C#開發串口通信實例及串口基礎
    串口通信(Serial Communications)的概念非常簡單,串口按位(bit)發送和接收字節。儘管比按字節(byte)的並行通信慢,但是串口可以在使用一根線發送數據的同時用另一根線接收數據。串口通信最重要的參數是波特率、數據位、停止位和奇偶校驗。對於兩個進行通信的埠,這些參數必須匹配。  1.
  • 【C#上位機必看】你們想要的練手項目來了
    最近有越來越多做電氣的小夥伴開始學習C#來做上位機開發,很多人在學習一段時間後,都有這種感覺
  • VC++6.0串口通信技術資料:軟體/源碼/論文/書籍/視頻/控制項/程序
    、VC++中有兩種方法可以進行串口通信來實現虛擬終端的通信操作080、VC++最簡單的串口程序,具體文件在幫助081、VC++做的一個串口管理軟體 界面自己做了圖標自定義,比較漂亮082、VC編程實現的串口通信,界面簡潔,實現基本的串口通信的作用083、VC編的串口程序!
  • 上位機基於C#通過TCP/IP和庫卡機器人通訊
    上位機要想和庫卡機器人通訊,首先要給機器人安裝「ETHERNETKRL」這個軟體,ETHERNETKRL是KUKA提供的一個乙太網通信功能的軟體包
  • 使用python實現win10系統和arduino usb串口通信
    其次是按照從簡原則,先從最直接的方式入手,也就是使用usb串口通信當前的arduino就是使用usb連接到pc電腦,無需其他操作(如果使用藍牙,wifi,還需要對應的模塊和較多的程序開發)pc電腦通信完成後,再用arduino通信樹莓派,無縫對接,本質都是系統,都是usb連接,都可以使用python(當前環境為居家場景)測試上位機操作
  • 第5章 USART串口通信
    波特率表示每秒發送二進位數據位的速率,單位是bps,即位/秒,波特率越高,傳輸速度越快,常用的UART通信波特率有2400,4800,9600,115200等等。在進行串行通信之前,通信雙方需要設置波特率保持一致,否則不能正常通信。單片機標準串口進行通信時,沒有數據傳輸時通信線路保持高電平狀態。當要發送數據時,先發送一位0,用以表示開始發送,叫做起始位。
  • Delphi串口通信技術資料:軟體/源碼/論文/書籍/視頻/控制項/程序
    不像控制項功能強大,經測試還沒出過問題129、故障設置系統上位機程序,上位機通過串口向單片發送命令進行設置與操作130、漢顯模塊+kb3130秤重儀表測試程序,即可以實現漢顯模塊的漢字發送接收通訊,易可對toledo的kb3130型號儀表的通訊。