C# host computer development serial port use

Catalogue of series articles

preface

About the production of C# host computer software, I learned the blogger's code on the network and summarized and verified it after some actual combat. I set my own code style and introduced the idea of face object programming

  1. Development of C# host computer (I) -- basis of C# host computer
  2. Development of C# host computer (II) -- use of C# serial port
  3. Development of C# upper computer (III) -- C# drawing method
  4. C # upper computer development (III) -- C # screenshot saving picture

Tip: the following is the main content of this article. The following cases can be used for reference

1, What is a serial port?

In the development of single chip microcomputer project, the upper computer is also a very important part, which is mainly used for data display (waveform, temperature, etc.), user control (LED, relay, etc.), and the two ways of data communication between the lower computer (single chip microcomputer) and the upper computer are based on serial port: USB to serial port_ The upper computer and the lower computer are directly connected through the USB to serial port connection line for data interaction;

2, Use steps

1. Add serial port control in the interface

//Serial port setting function
this.serialPort1 = new System.IO.Ports.SerialPort(this.components);
//Serial port interrupt method function
this.serialPort1.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(this.serialPort1_DataReceived);
//Serial port IO function
private System.IO.Ports.SerialPort serialPort1;

2. Add your own defined serial port class to encapsulate your own functions:

2-1 create: Class_My_SerialPort class

be careful:
using System.Windows.Forms;
using System.IO.Ports;
These two classes are referenced in order to reference the form program exception.


code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
// New reference
using System.Windows.Forms;
using System.IO.Ports;

namespace Move_Robot
{
    class Class_My_SerialPort
    { 
    }
}

2-2 add scan serial port logic

Code analysis:
USART_Search() / /: returns the serial port name found and adds it to the string array
serial_Name = System.IO.Ports.SerialPort.GetPortNames();// Find serial port resources in the system
The following code is the code to obtain the system serial port information.
 private string[] USART_Search()//Return the found serial port name and add it to the combox of the serial port
{
    string[] serial_Name= null;
    try{
        serial_Name = System.IO.Ports.SerialPort.GetPortNames();//Find serial port resources in the system
    }
    catch{
        System.Media.SystemSounds.Hand.Play();
        MessageBox.Show("Serial port search failed!", "System error");
        return serial_Name;
    }
    if (serial_Name == null) { return serial_Name; }
    else {
        Array.Sort(serial_Name);  //sort
        return serial_Name;
    }
}
Code analysis:
search_port_is_exist: traverses whether the string is in the string
update_Serial_List: add the serial port information name to the drop-down list
private Boolean search_port_is_exist(string item, string[] port_list)
{
    for (int i = 0; i < port_list.Length; i++){
        if (port_list[i].Equals(item)) { return true; }
    }
    return false;
}

public void update_Serial_List(ComboBox Port_comboBox)
{ 
    int count = Port_comboBox.Items.Count;
    this_Serial_Name = USART_Search();
    
    if (count == 0){
        if (this_Serial_Name.Length == 0){
            Port_comboBox.Text = "";
        }
        else{ 
            Port_comboBox.Items.AddRange(this_Serial_Name); //If not, increase it
            Port_comboBox.Text = Port_comboBox.Items[0].ToString();
        }
    }
    else{//If there is a serial port, check whether the serial port has increased or decreased
        if (this_Serial_Name.Length == 0){
            Port_comboBox.Items.Clear();
            Port_comboBox.Text = "";
        }
        else {
            foreach (String str in this_Serial_Name){
                if (!Port_comboBox.Items.Contains(str)){ // If there is no current value in the serial port, a new serial port will be added
                    Port_comboBox.Items.Add(str);
                }
            }
            for (int i = 0; i < count; i++){// If there is in the serial port, delete the original record and re-enter it
                if (!search_port_is_exist(Port_comboBox.Items[i].ToString(), this_Serial_Name)){
                    Port_comboBox.Items.RemoveAt(i);
                    Port_comboBox.Text = Port_comboBox.Items[0].ToString();
                }
            }
        }
        
    }           
}

2-3 initialize serial port, configure baud rate and other parameters

Code analysis:
The following procedures are some initialization procedures, which will be used in the LOAD function. Generally, LOAD various setting parameter data of the serial port into the corresponding drop-down list
public void BaudRate_Init(ComboBox ParityRate_comboBox)
{   //Baud rate loading
    for (int i = 0; i < 5; i++){
        ParityRate_comboBox.Items.Add((2400 * (Math.Pow(2, i))).ToString());
    }
    for (int i = 0; i < 2; i++){
        ParityRate_comboBox.Items.Add((57600 * (Math.Pow(2, i))).ToString());
    }
    ParityRate_comboBox.Items.Add((128000).ToString());
    ParityRate_comboBox.Items.Add((230400).ToString());
    ParityRate_comboBox.Items.Add((256000).ToString());
    ParityRate_comboBox.Text = "9600";
}
public void Parity_Init(ComboBox Parity_comboBox)
{//Parity load settings
    Parity_comboBox.Items.Add("nothing");
    Parity_comboBox.Items.Add("odd");
    Parity_comboBox.Items.Add("even");
    Parity_comboBox.Text = "nothing";
}
public void Data_Init(ComboBox Data_comboBox)
{//Parity load settings
    for (int i = 5; i <= 8; i++){
        Data_comboBox.Items.Add((i).ToString());
    }
    Data_comboBox.Text = "8";
}
public void Stop_Data_Init(ComboBox Stop_comboBox)
{//Stop bit load setting            
    Stop_comboBox.Items.Add((1).ToString());
    Stop_comboBox.Items.Add((1.5).ToString());
    Stop_comboBox.Items.Add((2).ToString());
    Stop_comboBox.Text = "1";
}

2-4 serial port opening program

The most important is the following code:
start_USART (serial port control, baud rate, check bit, data bit, stop bit, coding format)
serialPort.IsOpen is used to determine whether the serial port is open.
The first half is to assign values to the configuration of various parameters of the serial port.
It is very important to remember the description of the coding format, which will directly affect the subsequent communication of serial port data in Chinese and English data formats.
After finishing the debugging, I finished it.
serialPort.Encoding

public Boolean start_USART(SerialPort serialPort, String PortName , String BaudRate, String Parity, String DataBits, String StopBits, String code_UTFSet)
{
    String this_PortName = PortName;
    String this_BaudRate = BaudRate;
    String this_Parity = Parity;
    String this_DataBits = DataBits;
    String this_StopBits = StopBits;
    String this_code_UTFSet = code_UTFSet;
    
    try
    {
        if (this_PortName == ""){
            System.Media.SystemSounds.Hand.Play();
            MessageBox.Show("No serial port available!", "error");
            return false;
        }
        if(serialPort.IsOpen){
            System.Media.SystemSounds.Hand.Play();
            MessageBox.Show("The serial port has been opened!", "error");
            return false;
        }
        //----------------------------Set the connection parameters of the serial port------------------------
        //Set serial port name
        serialPort.PortName = this_PortName;
        //set baud rate
        serialPort.BaudRate = Convert.ToInt32(this_BaudRate);
        //Set the check bit
        if (this_Parity.Equals("nothing")) { serialPort.Parity = System.IO.Ports.Parity.None; }
        else if (this_Parity.Equals("odd")) { serialPort.Parity = System.IO.Ports.Parity.Odd; }
        else { serialPort.Parity = System.IO.Ports.Parity.Even; }
        //set data bit
        serialPort.DataBits = Convert.ToInt32(this_DataBits);
        Set stop bit
        if (this_StopBits.Equals("1")) { serialPort.StopBits = System.IO.Ports.StopBits.One; }
        else if (this_StopBits.Equals("1.5")) { serialPort.StopBits = System.IO.Ports.StopBits.OnePointFive; }
        else { serialPort.StopBits = System.IO.Ports.StopBits.Two; }


        //-------------------------Here is the key -- Coding format setting---------------------
        serialPort.ReceivedBytesThreshold = 1; //An event is triggered when a character is received
        if (code_UTFSet.Equals("DEFAULT")) { serialPort.Encoding = Encoding.Default; }// Set encoding format
        else if (code_UTFSet.Equals("UTF-8")) { serialPort.Encoding = Encoding.UTF8; }// Set encoding format
        else if (code_UTFSet.Equals("GB232")) { serialPort.Encoding = Encoding.Default; }// Set encoding format
        else { serialPort.Encoding = Encoding.Default; }// Set encoding format

        //Officially open the serial port
        serialPort.Open();
    }
    catch
    {
        System.Media.SystemSounds.Hand.Play();
        MessageBox.Show("Failed to open serial port!", "error");
        return false;
    }  
    //System.Media.SystemSounds.Beep.Play();
    return true;
}

public Boolean stop_USART(SerialPort serialPort)
{
    //If it is already closed
    try{              
        serialPort.Close();
        return true;
    }
    catch{
        System.Media.SystemSounds.Hand.Play();
        MessageBox.Show("Serial port shutdown failed!", "error");
        return false;
    }
    
}

3. Add the called function to use the configuration to search the serial port:

3-1 add the serial port search function in the button pressing method

Add scan serial port logic
private void button8_Click(object sender, EventArgs e)  //Add this function to the button that opens and disconnects the device
{
    if (button1.Tag.Equals("0")) {
        if (Port_comboBox.Text == "") {
            System.Media.SystemSounds.Hand.Play();
            MessageBox.Show("There is no serial port at present. Please search the serial port!", "error");
            talk_String("There is no serial port at present. Please search the serial port!");
            return;
        }
        my_SerialPort.update_Serial_List(Port_comboBox);
        if (my_SerialPort.start_USART(serialPort1, Port_comboBox.Text, "9600", "nothing", "8", "1", "DEFAULT")) {
            talk_String("Serial port open completed!");
            button1.Text = "Device disconnected";
            button1.Tag = "1";
            groupBox101.Text = "device connected";
            button2.Enabled = false;
            Port_comboBox.Enabled = false;
            function_MainForm.Robot_state_set(2);

            return;
        }
    }
    else {
        my_SerialPort.stop_USART(serialPort1);
        talk_String("The serial port has been disconnected!");
        button1.Text = "Device connection";
        button1.Tag = "0";
        groupBox101.Text = "Device interrupted";
        button2.Enabled = Enabled;
        Port_comboBox.Enabled = Enabled;
        function_MainForm.Robot_state_set(-1);

    }
}

private void button2_Click(object sender, EventArgs e) // Device search
{
    my_SerialPort.update_Serial_List(Port_comboBox);
}

3-2 add serial port automatic search function in timer method

Timer start / stop control

Use the following code to set the timer time to 1s and start the timer:

timer1.Interval = 1000;
timer1.Start();
Add scan serial port logic

Add scan automatic serial port logic

private void timer1_Tick(object sender, EventArgs e)
{
    labelASCtime1.Text = "Time:" + DateTime.Now.ToString("HH:mm:ss");
    function_MainForm.Robot_state_show(pictureBox_state, label_state);//Device status display
    my_SerialPort.update_Serial_List(Port_comboBox);//Automatic loading and identification of serial port
    if ((button1.Tag == "1") && (serialPort1.PortName != Port_comboBox.Text)) {
        my_SerialPort.stop_USART(serialPort1);
        talk_String("The serial port has been disconnected!");
        button1.Text = "Device connection";
        button1.Tag = "0";
        groupBox101.Text = "Device interrupted";
        button2.Enabled = Enabled;
        Port_comboBox.Enabled = Enabled;
        function_MainForm.Robot_state_set(-1);
    }
}

4. Add serial port action function:

This is a function that reflects the serial port data reception and processing. It is very important

4-1 when sending data, pay attention to the conversion of data to Byte

Add serial port sending data logic
 public String SEND_DATA(SerialPort serialPort ,String data_Style, Boolean B_data_Line, String send_text) //send data
{
    long send_code_count = 0;
    byte[] Data = new byte[1];
    if (serialPort.IsOpen == false) {
        System.Media.SystemSounds.Hand.Play();
        MessageBox.Show("Serial port is not open", "error");
        return "";
    }
    if (send_text == "")
    {
        System.Media.SystemSounds.Hand.Play();
        MessageBox.Show("Send data cannot be empty", "error");
        return "";
    }
    if (data_Style.Equals("ASCLL")) // If the data sent is Classl data
    {    
        try
        {
            string send_str = send_text;
            if (B_data_Line == true) { send_str += "\r\n"; } // If the sending line is selected
            byte[] TxdBuf = Encoding.Default.GetBytes(send_str);//After converting data to Byte data
            //When the serial port is on, send the text in the sending area
            serialPort.Write(TxdBuf, 0, TxdBuf.Length); // Write data to serial port data
            send_code_count += TxdBuf.Length;  // Record the amount of data sent 
            return send_str;
        }
        catch
        {
            return "Send_error";  // Capture serial port sending exception
        }
           
    }
    else if (data_Style.Equals("HEX")) // If the data sent is HEX data
    {
        string send_str = send_text.Trim();               
        send_str = Regex.Replace(send_str, @"[\u4e00 - \u9fa5]", ""); //Remove Chinese characters
        send_str = Regex.Replace(send_str, @"[f-z]", "");//Remove the outside of HEX
        send_str = Regex.Replace(send_str, @"[F-Z]", "");//Remove HEX
        send_str = Regex.Replace(send_str, @"[\r\n\s\W]", "");//Get rid of the mess
        send_code_count += ((send_str.Length - (send_str.Length % 2)) / 2);
        try
        {
            for (int i = 0; i < ((send_str.Length - (send_str.Length % 2)) / 2); i++)
            { //The sending before the end of the remaining odd number is completed
                Data[0] = Convert.ToByte(send_str.Substring(i * 2, 2), 16);
                serialPort.Write(Data, 0, 1);
            }
            if ((send_str.Length) % 2 != 0)//The end data sent separately is not 2-bit data
            {
                Data[0] = Convert.ToByte(send_str.Substring(send_str.Length - 1, 1), 16);
                serialPort.Write(Data, 0, 1);
                send_code_count += 1;
            }
            return send_str;
        }
        catch {
            return "Send_error";
        }
            
    }
    else {
        return "Send_set_error";
    }
   
}

4-2 when receiving data, pay attention to the conversion of data to Byte

Because of my face object programming idea, I don't want to judge the data format and intercept the data format here according to the custom code value,
For intercepting and judging serial port instructions, I dynamically supplement them in another program

Add serial port receiving data logic
public String RECEIVE_DATA(SerialPort serialPort, String data_Style, Boolean need_tab)
{
    if (data_Style.Equals("ASCALL")){//If you are receiving Classl data
        try{
            string get_str = "";
            while (serialPort.BytesToRead > 0) // If the data is not empty, convert it
            {
                receive_code_count += serialPort.BytesToRead;
                get_str += serialPort.ReadExisting(); // read in data
            }
            return get_str;
        }
        catch{
            return "Receive_error";
        }
    }

    else if (data_Style.Equals("HEX")){
        try{
            string get_str = "";
            string receive_data = "";
            receive_code_count += serialPort.BytesToRead;

            byte[] data = new byte[serialPort.BytesToRead];
            serialPort.Read(data, 0, data.Length);

            foreach (byte get_data in data){
                get_str = Convert.ToString(get_data, 16).ToUpper();//Converts each bit to a hexadecimal string
                if (need_tab == true){//Does the read in data need space spacing
                    receive_data += ((get_str.Length == 1 ? "0" + get_str : get_str) + " "); // If it is 12a - > > 120a, automatically supplement 0
                }
                else{
                    receive_data += ((get_str.Length == 1 ? "0" + get_str : get_str));
                }
                if (get_str.Length == 1) { receive_code_count += 1; }//Automatic supplement
            }
            return receive_data;
        }
        catch{
            return "Receive_error";
        }

    }
    else {
        return "Receive_set_error";
    }
}

5. Add application function of serial port action function:

It's important to see how to use the function of package number

5-1 for serial port data processing, delete and truncate specific marks and segment data

Split with (00 00 0D 0A) mark AA 01 02 03 00 0d 0A AA 02 03 00 0d 0A

Add serial port data processing truncation function
public Class_Code_DATA[] Check_Data(MainForm mainForm, String s_data)
{
    int count_code = 0;
    Class_Code_DATA[] code_DATA = { };
    mainForm.Invoke((EventHandler)(delegate
    {
        String[] this_data = s_data.Split(new String[] { "00000D0A" }, StringSplitOptions.RemoveEmptyEntries);
        count_code = this_data.Count();
        code_DATA = new Class_Code_DATA[count_code];
        count_code = 0;
        foreach (String s in this_data)
        {
            Class_Code_DATA check_code = Check_code(s);
            code_DATA[count_code++] = check_code;
        }
        GC.Collect();
    }));
    return code_DATA;

}
Secondary identification of segmented serial port data (internal method)
private Class_Code_DATA Check_code(String check_s)
{
    /*
            {0xAA,0x01,X,X} //temperature
         {0xAA,0x02,X,X} //humidity
         {0xAA,0x03,X,X} //Sensing human coordinates							  
         {0xAA,0x04,X,X} //Current person coordinates 
         {0xAA,0x05,X,X} //Pause completion

         {0xAA,0x010,X,X} //Power on initialization completed 
         {0xAA,0x011,X,X} //Test complete
         {0xAA,0x012,X,X} //Reset complete							  
         {0xAA,0x013,X,X} //Move complete 

    Warning class:
         {0xAB,0xF0,0xFF,0xFF} //Host to slave data warning 
         {0xBA,0xF1,0xFF,0xFF} //Slave to host data warning
         {0xAA,0xF2,0xFF,0xFF} //Host to PC data warning
    Tail data 00000D0A
 * 
 */

    Class_Code_DATA code_DATA = new Class_Code_DATA();
    if (check_s.Length != 8) { code_DATA.set_Code_Aim("relay-host"); code_DATA.set_Code_Name("Host to PC Machine data warning,Please re-establish the link");
        code_DATA.set_Code_Data1(""); code_DATA.set_Code_Data2("");
        GC.Collect();
        GC.WaitForPendingFinalizers(); 
        return code_DATA; }

    if (check_s.Substring(0, 2).Equals("AA")) { code_DATA.set_Code_Aim("relay-host"); }
    else if(check_s.Substring(0, 2).Equals("0xAB")){ code_DATA.set_Code_Aim("relay-Slave"); }
    else if (check_s.Substring(0, 2).Equals("0xAB")) { code_DATA.set_Code_Aim("Slave-relay"); }
    else { code_DATA.set_Code_Aim("error"); }

    if (check_s.Substring(2, 2).Equals("01")) { code_DATA.set_Code_Name("temperature"); }
    else if (check_s.Substring(2, 2).Equals("02")) { code_DATA.set_Code_Name("humidity"); }
    else if (check_s.Substring(2, 2).Equals("03")) { code_DATA.set_Code_Name("Sensing human coordinates"); }
    else if (check_s.Substring(2, 2).Equals("04")) { code_DATA.set_Code_Name("Current person coordinates"); }
    else if (check_s.Substring(2, 2).Equals("05")) { code_DATA.set_Code_Name("suspend"); }
    else if (check_s.Substring(2, 2).Equals("10")) { code_DATA.set_Code_Name("Power on initialization completed"); }
    else if (check_s.Substring(2, 2).Equals("11")) { code_DATA.set_Code_Name("Test complete");}
    else if (check_s.Substring(2, 2).Equals("12")) { code_DATA.set_Code_Name("Reset complete");}
    else if (check_s.Substring(2, 2).Equals("13")) { code_DATA.set_Code_Name("Move complete");}

    else if (check_s.Substring(2, 2).Equals("F0")) { code_DATA.set_Code_Name("Host to slave data warning,Please re-establish the link");}
    else if (check_s.Substring(2, 2).Equals("F1")) { code_DATA.set_Code_Name("Slave to host data warning,Please re-establish the link");}
    else if (check_s.Substring(2, 2).Equals("F2")) { code_DATA.set_Code_Name("Host to PC Machine data warning,Please re-establish the link");}
    else { code_DATA.set_Code_Name("error"); }

    code_DATA.set_Code_Data1(Convert.ToInt32(check_s.Substring(4, 2), 16).ToString());
    code_DATA.set_Code_Data2(Convert.ToInt32(check_s.Substring(6, 2), 16).ToString());

    GC.Collect();
    GC.WaitForPendingFinalizers();
    return code_DATA;
}
Complete common interface function
public void Deal_The_Data(MainForm mainForm, Class_Code_DATA[] s_data, TextBox textBox_data, PictureBox pictureBox_state, RichTextBox command_richTextBox, 
            Label labelx, Label labely, ProgressBar command_progressBar1 , TextBox textBox401, TextBox textBox402, TextBox textBox403)
{
    mainForm.Invoke((EventHandler)(delegate
    {
        Show_data(s_data, textBox_data);
        foreach (Class_Code_DATA data in s_data)
        {
            if (data.get_Code_Name().Equals("Current person coordinates")) { Show_Point(data, labelx, labely , command_progressBar1); }
            else if (data.get_Code_Name().Equals("Sensing human coordinates")) { Paint_PIR(data , pictureBox_state);  }
            else if (data.get_Code_Name().Equals("Power on initialization completed")) { talk_String(command_richTextBox , "Power on initialization completed"); }
            else if (data.get_Code_Name().Equals("suspend")) { Command_progressBar_Stop(command_progressBar1); talk_String(command_richTextBox, "Pause completion"); Robot_state_set(2); }
            else if (data.get_Code_Name().Equals("Test complete")) { Save_ImageAuto(mainForm , command_richTextBox,textBox401, textBox402, textBox403); Command_progressBar_Stop(command_progressBar1); talk_String(command_richTextBox, "Test complete"); Robot_state_set(2); }
            else if (data.get_Code_Name().Equals("Reset complete")) {  Command_progressBar_Stop(command_progressBar1); talk_String(command_richTextBox, "Reset complete"); Robot_state_set(2); }
            else if (data.get_Code_Name().Equals("Move complete")) { Command_progressBar_Stop(command_progressBar1); talk_String(command_richTextBox, "Move complete"); Robot_state_set(2); }

            else if (data.get_Code_Name().Equals("Host to slave data warning")) { Command_progressBar_Stop(command_progressBar1); talk_String(command_richTextBox, "Host to slave data warning"); Robot_state_set(0); }
            else if (data.get_Code_Name().Equals("Slave to host data warning")) { Command_progressBar_Stop(command_progressBar1); talk_String(command_richTextBox, "Slave to host data warning"); Robot_state_set(0); }
            else if (data.get_Code_Name().Equals("Host to PC Machine data warning")) { Command_progressBar_Stop(command_progressBar1); talk_String(command_richTextBox, "Host to PC Machine data warning"); Robot_state_set(0); }
            else {
                if (data.get_Code_Name().Equals("temperature") || data.get_Code_Name().Equals("humidity")) { ; }
                else { talk_String(command_richTextBox, data.get_Code_Name() + " " + data.get_Code_Data1() + "" + data.get_Code_Data2()); }
            }
        }
        GC.Collect();
        GC.WaitForPendingFinalizers();
    }));
}

5-2 calling the main program control for the serial port data processing encapsulation function

Under the serial port control, select the first DATAreceive method in the attribute - method, and double-click to generate the default interface method:

How to use it:
Test data - code identification

 private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
    /*Serial port reception: register a Receive event for the serial port before using serial port reception,
       Equivalent to the serial port in the MCU receives the interrupt, and then reads the data in the buffer inside the interrupt*/
    String s_data = "";
    s_data = function_MainForm.Receive_data(this, serialPort1);
    Class_Code_DATA[] code_DATA = function_MainForm.Check_Data(this, s_data);
    function_MainForm.Deal_The_Data(this, code_DATA, textBox_data, Point_Box, command_richTextBox1, label6, label7, command_progressBar1, textBox401, textBox402, textBox403);

    GC.Collect(); //garbage collection
    GC.WaitForPendingFinalizers();
}

3, Complete code of serial port class

1. User defined class_ My_ Methods in the serialport class

using System;
using System.Collections.Generic;

using System.Linq;
using System.Text;
using System.Threading.Tasks;
// New reference
using System.Windows.Forms;
using System.IO.Ports;
using System.Text.RegularExpressions;

namespace Move_Robot
{
    class Class_My_SerialPort 
    { 
        public static string[] this_Serial_Name ;
        public static long send_code_count;
        public static long receive_code_count;

        //------------------------------------Data area--------------------------------------

        public long send_code_count_get() {
            return send_code_count;
        }
        public void send_code_count_set(long set_data){
            send_code_count = set_data;
        }
   
        public long receive_code_count_get(){
            return receive_code_count;
        }
        public void receive_code_count_set(long receive_data){
            receive_code_count = receive_data;
        }
     

        //--------------------------------------Serial port setting area-------------------------------------------

        private string[] USART_Search()//Return the found serial port name and add it to the combox of the serial port
        {
            string[] serial_Name= null;
            try{
                serial_Name = System.IO.Ports.SerialPort.GetPortNames();//Find serial port resources in the system
            }
            catch{
                System.Media.SystemSounds.Hand.Play();
                MessageBox.Show("Serial port search failed!", "System error");
                return serial_Name;
            }
            if (serial_Name == null) { return serial_Name; }
            else {
                Array.Sort(serial_Name);  //sort
                return serial_Name;
            }
        }

        private Boolean search_port_is_exist(string item, string[] port_list)
        {
            for (int i = 0; i < port_list.Length; i++){
                if (port_list[i].Equals(item)) { return true; }
            }
            return false;
        }

        public void update_Serial_List(ComboBox Port_comboBox)
        { 
            int count = Port_comboBox.Items.Count;
            this_Serial_Name = USART_Search();
            
            if (count == 0){
                if (this_Serial_Name.Length == 0){
                    Port_comboBox.Text = "";
                }
                else{ 
                    Port_comboBox.Items.AddRange(this_Serial_Name); //If not, increase it
                    Port_comboBox.Text = Port_comboBox.Items[0].ToString();
                }
            }
            else{//If there is a serial port, check whether the serial port has increased or decreased
                if (this_Serial_Name.Length == 0){
                    Port_comboBox.Items.Clear();
                    Port_comboBox.Text = "";
                }
                else {
                    foreach (String str in this_Serial_Name){
                        if (!Port_comboBox.Items.Contains(str)){ // If there is no current value in the serial port, a new serial port will be added
                            Port_comboBox.Items.Add(str);
                        }
                    }
                    for (int i = 0; i < count; i++){// If there is in the serial port, delete the original record and re-enter it
                        if (!search_port_is_exist(Port_comboBox.Items[i].ToString(), this_Serial_Name)){
                            Port_comboBox.Items.RemoveAt(i);
                            Port_comboBox.Text = Port_comboBox.Items[0].ToString();
                        }
                    }
                }
                
            }           
        }


        public void BaudRate_Init(ComboBox ParityRate_comboBox)
        {   //Baud rate loading
            for (int i = 0; i < 5; i++){
                ParityRate_comboBox.Items.Add((2400 * (Math.Pow(2, i))).ToString());
            }
            for (int i = 0; i < 2; i++){
                ParityRate_comboBox.Items.Add((57600 * (Math.Pow(2, i))).ToString());
            }
            ParityRate_comboBox.Items.Add((128000).ToString());
            ParityRate_comboBox.Items.Add((230400).ToString());
            ParityRate_comboBox.Items.Add((256000).ToString());
            ParityRate_comboBox.Text = "9600";
        }
        public void Parity_Init(ComboBox Parity_comboBox)
        {//Parity load settings
            Parity_comboBox.Items.Add("nothing");
            Parity_comboBox.Items.Add("odd");
            Parity_comboBox.Items.Add("even");
            Parity_comboBox.Text = "nothing";
        }
        public void Data_Init(ComboBox Data_comboBox)
        {//Parity load settings
            for (int i = 5; i <= 8; i++){
                Data_comboBox.Items.Add((i).ToString());
            }
            Data_comboBox.Text = "8";
        }
        public void Stop_Data_Init(ComboBox Stop_comboBox)
        {//Stop bit load setting            
            Stop_comboBox.Items.Add((1).ToString());
            Stop_comboBox.Items.Add((1.5).ToString());
            Stop_comboBox.Items.Add((2).ToString());
            Stop_comboBox.Text = "1";
        }

        public Boolean start_USART(SerialPort serialPort, String PortName , String BaudRate, String Parity, String DataBits, String StopBits, String code_UTFSet)
        {
            String this_PortName = PortName;
            String this_BaudRate = BaudRate;
            String this_Parity = Parity;
            String this_DataBits = DataBits;
            String this_StopBits = StopBits;
            String this_code_UTFSet = code_UTFSet;
            
            try
            {
                if (this_PortName == ""){
                    System.Media.SystemSounds.Hand.Play();
                    MessageBox.Show("No serial port available!", "error");
                    return false;
                }
                if(serialPort.IsOpen){
                    System.Media.SystemSounds.Hand.Play();
                    MessageBox.Show("The serial port has been opened!", "error");
                    return false;
                }
                //----------------------------Set the connection parameters of the serial port------------------------
                //Set serial port name
                serialPort.PortName = this_PortName;
                //set baud rate
                serialPort.BaudRate = Convert.ToInt32(this_BaudRate);
                //Set the check bit
                if (this_Parity.Equals("nothing")) { serialPort.Parity = System.IO.Ports.Parity.None; }
                else if (this_Parity.Equals("odd")) { serialPort.Parity = System.IO.Ports.Parity.Odd; }
                else { serialPort.Parity = System.IO.Ports.Parity.Even; }
                //set data bit
                serialPort.DataBits = Convert.ToInt32(this_DataBits);
                Set stop bit
                if (this_StopBits.Equals("1")) { serialPort.StopBits = System.IO.Ports.StopBits.One; }
                else if (this_StopBits.Equals("1.5")) { serialPort.StopBits = System.IO.Ports.StopBits.OnePointFive; }
                else { serialPort.StopBits = System.IO.Ports.StopBits.Two; }


                //-------------------------Here is the key -- Coding format setting---------------------
                serialPort.ReceivedBytesThreshold = 1; //An event is triggered when a character is received
                if (code_UTFSet.Equals("DEFAULT")) { serialPort.Encoding = Encoding.Default; }// Set encoding format
                else if (code_UTFSet.Equals("UTF-8")) { serialPort.Encoding = Encoding.UTF8; }// Set encoding format
                else if (code_UTFSet.Equals("GB232")) { serialPort.Encoding = Encoding.Default; }// Set encoding format
                else { serialPort.Encoding = Encoding.Default; }// Set encoding format

                //Officially open the serial port
                serialPort.Open();
            }
            catch
            {
                System.Media.SystemSounds.Hand.Play();
                MessageBox.Show("Failed to open serial port!", "error");
                return false;
            }  
            //System.Media.SystemSounds.Beep.Play();
            return true;
        }

        public Boolean stop_USART(SerialPort serialPort)
        {
            //If it is already closed
            try{              
                serialPort.Close();
                return true;
            }
            catch{
                System.Media.SystemSounds.Hand.Play();
                MessageBox.Show("Serial port shutdown failed!", "error");
                return false;
            }
            
        }

        //-----------------------------------Serial port action function------------------------------


        public String SEND_DATA(SerialPort serialPort ,String data_Style, Boolean B_data_Line, String send_text) //send data
        {
            long send_code_count = 0;
            byte[] Data = new byte[1];
            if (serialPort.IsOpen == false) {
                System.Media.SystemSounds.Hand.Play();
                MessageBox.Show("Serial port is not open", "error");
                return "";
            }
            if (send_text == "")
            {
                System.Media.SystemSounds.Hand.Play();
                MessageBox.Show("Send data cannot be empty", "error");
                return "";
            }
            if (data_Style.Equals("ASCLL")) // If the data sent is Classl data
            {    
                try
                {
                    string send_str = send_text;
                    if (B_data_Line == true) { send_str += "\r\n"; } // If the sending line is selected
                    byte[] TxdBuf = Encoding.Default.GetBytes(send_str);//After converting data to Byte data
                    //When the serial port is on, send the text in the sending area
                    serialPort.Write(TxdBuf, 0, TxdBuf.Length); // Write data to serial port data
                    send_code_count += TxdBuf.Length;  // Record the amount of data sent 
                    return send_str;
                }
                catch
                {
                    return "Send_error";  // Capture serial port sending exception
                }
                   
            }
            else if (data_Style.Equals("HEX")) // If the data sent is HEX data
            {
                string send_str = send_text.Trim();               
                send_str = Regex.Replace(send_str, @"[\u4e00 - \u9fa5]", ""); //Remove Chinese characters
                send_str = Regex.Replace(send_str, @"[f-z]", "");//Remove the outside of HEX
                send_str = Regex.Replace(send_str, @"[F-Z]", "");//Remove HEX
                send_str = Regex.Replace(send_str, @"[\r\n\s\W]", "");//Get rid of the mess
                send_code_count += ((send_str.Length - (send_str.Length % 2)) / 2);
                try
                {
                    for (int i = 0; i < ((send_str.Length - (send_str.Length % 2)) / 2); i++)
                    { //The sending before the end of the remaining odd number is completed
                        Data[0] = Convert.ToByte(send_str.Substring(i * 2, 2), 16);
                        serialPort.Write(Data, 0, 1);
                    }
                    if ((send_str.Length) % 2 != 0)//The end data sent separately is not 2-bit data
                    {
                        Data[0] = Convert.ToByte(send_str.Substring(send_str.Length - 1, 1), 16);
                        serialPort.Write(Data, 0, 1);
                        send_code_count += 1;
                    }
                    return send_str;
                }
                catch {
                    return "Send_error";
                }
                    
            }
            else {
                return "Send_set_error";
            }
           
        }

        
        public String RECEIVE_DATA(SerialPort serialPort, String data_Style, Boolean need_tab)
        {
            if (data_Style.Equals("ASCALL")){//If you are receiving Classl data
                try{
                    string get_str = "";
                    while (serialPort.BytesToRead > 0) // If the data is not empty, convert it
                    {
                        receive_code_count += serialPort.BytesToRead;
                        get_str += serialPort.ReadExisting(); // read in data
                    }
                    return get_str;
                }
                catch{
                    return "Receive_error";
                }
            }

            else if (data_Style.Equals("HEX")){
                try{
                    string get_str = "";
                    string receive_data = "";
                    receive_code_count += serialPort.BytesToRead;

                    byte[] data = new byte[serialPort.BytesToRead];
                    serialPort.Read(data, 0, data.Length);

                    foreach (byte get_data in data){
                        get_str = Convert.ToString(get_data, 16).ToUpper();//Converts each bit to a hexadecimal string
                        if (need_tab == true){//Does the read in data need space spacing
                            receive_data += ((get_str.Length == 1 ? "0" + get_str : get_str) + " "); // If it is 12a - > > 120a, automatically supplement 0
                        }
                        else{
                            receive_data += ((get_str.Length == 1 ? "0" + get_str : get_str));
                        }
                        if (get_str.Length == 1) { receive_code_count += 1; }//Automatic supplement
                    }
                    return receive_data;
                }
                catch{
                    return "Receive_error";
                }

            }
            else {
                return "Receive_set_error";
            }
        }

    }
}

2. Customize main program Function_MainForm interface method class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//New class
using System.Drawing;
using System.Windows.Forms;
using System.IO.Ports;

namespace Move_Robot
{
    class Function_MainForm
    {
        public static int Robot_State = -1;     // 0 fault 1 operation 2 pause 
        public static Boolean Robot_paint_receivecommand = true;
        private static bool state_show_tag = false;
        private static String File_name;

         
        // ---------------------------------Send various test instructions------------------------
        public String RESET_Command(MainForm mainForm, SerialPort serialPort)
        {
            String s_command = "";
            mainForm.Invoke((EventHandler)(delegate
            {
                s_command = Convert.ToString(new Class_My_SerialPort().SEND_DATA(serialPort, "HEX", false, "AA020000"));
                Robot_state_set(1);
            }));
            return s_command;
        }

        public String Stop_Command(MainForm mainForm, SerialPort serialPort)
        {
            String s_command = "";
            mainForm.Invoke((EventHandler)(delegate
            {
                s_command = Convert.ToString(new Class_My_SerialPort().SEND_DATA(serialPort, "HEX", false, "AA040000"));
                Robot_state_set(1);
            }));
            return s_command;
        }

        public String AUTO_Command(MainForm mainForm, SerialPort serialPort, String max_distance)
        {
            String s_command = "";
            String command = "AA0100";
            max_distance = Convert.ToString(Convert.ToInt32(max_distance), 16);
            if (max_distance.Length % 2 != 0) { command += "0"; }
            command += max_distance.ToUpper();
            mainForm.Invoke((EventHandler)(delegate
            {
                s_command = Convert.ToString(new Class_My_SerialPort().SEND_DATA(serialPort, "HEX", false, command));
                Robot_state_set(1);
            }));
            return s_command;
        }
        public String Line_Command(MainForm mainForm, SerialPort serialPort, String max_distance)
        {
            String s_command = "";
            String command = "AA0600";
            max_distance = Convert.ToString(Convert.ToInt32(max_distance), 16);
            if (max_distance.Length % 2 != 0) { command += "0"; }
            command += max_distance.ToUpper();
            mainForm.Invoke((EventHandler)(delegate
            {
                s_command = Convert.ToString(new Class_My_SerialPort().SEND_DATA(serialPort, "HEX", false, command));
                Robot_state_set(1);
            }));
            return s_command;
        }

        
        public String Point_Command(MainForm mainForm, SerialPort serialPort, String x_distance, String y_distance)
        {
            String s_command = "";
            String command = "AA03";
            x_distance = Convert.ToString(Convert.ToInt32(x_distance), 16);
            if (x_distance.Length % 2 != 0) { command += "0"; }
            command += x_distance.ToUpper();

            y_distance = Convert.ToString(Convert.ToInt32(y_distance), 16);
            if (x_distance.Length % 2 != 0) { command += "0"; }
            command += y_distance.ToUpper();

            mainForm.Invoke((EventHandler)(delegate
            {
                s_command = Convert.ToString(new Class_My_SerialPort().SEND_DATA(serialPort, "HEX", false, command));
                Robot_state_set(1);
            }));
            return s_command;
        }


        // ---------------------------------Receive data instruction------------------------
        public String Receive_data(MainForm mainForm, SerialPort serialPort)
        {
            String s_data = "";
            mainForm.Invoke((EventHandler)(delegate
            {
                s_data = new Class_My_SerialPort().RECEIVE_DATA(serialPort, "HEX", false);
            }));
            return s_data;
        }

        //------------------------------------Instruction data processing----------------------------

        private Class_Code_DATA Check_code(String check_s)
        {
            /*
                    {0xAA,0x01,X,X} //temperature
	                {0xAA,0x02,X,X} //humidity
	                {0xAA,0x03,X,X} //Sensing human coordinates							  
	                {0xAA,0x04,X,X} //Current person coordinates 
	                {0xAA,0x05,X,X} //Pause completion

	                {0xAA,0x010,X,X} //Power on initialization completed 
	                {0xAA,0x011,X,X} //Test complete
	                {0xAA,0x012,X,X} //Reset complete							  
	                {0xAA,0x013,X,X} //Move complete 
 
            Warning class:
	                {0xAB,0xF0,0xFF,0xFF} //Host to slave data warning 
	                {0xBA,0xF1,0xFF,0xFF} //Slave to host data warning
	                {0xAA,0xF2,0xFF,0xFF} //Host to PC data warning
            Tail data 00000D0A
         * 
         */

            Class_Code_DATA code_DATA = new Class_Code_DATA();
            if (check_s.Length != 8) { code_DATA.set_Code_Aim("relay-host"); code_DATA.set_Code_Name("Host to PC Machine data warning,Please re-establish the link");
                code_DATA.set_Code_Data1(""); code_DATA.set_Code_Data2("");
                GC.Collect();
                GC.WaitForPendingFinalizers(); 
                return code_DATA; }

            if (check_s.Substring(0, 2).Equals("AA")) { code_DATA.set_Code_Aim("relay-host"); }
            else if(check_s.Substring(0, 2).Equals("0xAB")){ code_DATA.set_Code_Aim("relay-Slave"); }
            else if (check_s.Substring(0, 2).Equals("0xAB")) { code_DATA.set_Code_Aim("Slave-relay"); }
            else { code_DATA.set_Code_Aim("error"); }

            if (check_s.Substring(2, 2).Equals("01")) { code_DATA.set_Code_Name("temperature"); }
            else if (check_s.Substring(2, 2).Equals("02")) { code_DATA.set_Code_Name("humidity"); }
            else if (check_s.Substring(2, 2).Equals("03")) { code_DATA.set_Code_Name("Sensing human coordinates"); }
            else if (check_s.Substring(2, 2).Equals("04")) { code_DATA.set_Code_Name("Current person coordinates"); }
            else if (check_s.Substring(2, 2).Equals("05")) { code_DATA.set_Code_Name("suspend"); }
            else if (check_s.Substring(2, 2).Equals("10")) { code_DATA.set_Code_Name("Power on initialization completed"); }
            else if (check_s.Substring(2, 2).Equals("11")) { code_DATA.set_Code_Name("Test complete");}
            else if (check_s.Substring(2, 2).Equals("12")) { code_DATA.set_Code_Name("Reset complete");}
            else if (check_s.Substring(2, 2).Equals("13")) { code_DATA.set_Code_Name("Move complete");}

            else if (check_s.Substring(2, 2).Equals("F0")) { code_DATA.set_Code_Name("Host to slave data warning,Please re-establish the link");}
            else if (check_s.Substring(2, 2).Equals("F1")) { code_DATA.set_Code_Name("Slave to host data warning,Please re-establish the link");}
            else if (check_s.Substring(2, 2).Equals("F2")) { code_DATA.set_Code_Name("Host to PC Machine data warning,Please re-establish the link");}
            else { code_DATA.set_Code_Name("error"); }

            code_DATA.set_Code_Data1(Convert.ToInt32(check_s.Substring(4, 2), 16).ToString());
            code_DATA.set_Code_Data2(Convert.ToInt32(check_s.Substring(6, 2), 16).ToString());

            GC.Collect();
            GC.WaitForPendingFinalizers();
            return code_DATA;
        }
        public Class_Code_DATA[] Check_Data(MainForm mainForm, String s_data)
        {
            int count_code = 0;
            Class_Code_DATA[] code_DATA = { };
            mainForm.Invoke((EventHandler)(delegate
            {
                String[] this_data = s_data.Split(new String[] { "00000D0A" }, StringSplitOptions.RemoveEmptyEntries);
                count_code = this_data.Count();
                code_DATA = new Class_Code_DATA[count_code];
                count_code = 0;
                foreach (String s in this_data)
                {
                    Class_Code_DATA check_code = Check_code(s);
                    code_DATA[count_code++] = check_code;
                }
                GC.Collect();
            }));
            return code_DATA;

        }


        public void Deal_The_Data(MainForm mainForm, Class_Code_DATA[] s_data, TextBox textBox_data, PictureBox pictureBox_state, RichTextBox command_richTextBox, 
            Label labelx, Label labely, ProgressBar command_progressBar1 , TextBox textBox401, TextBox textBox402, TextBox textBox403)
        {
            mainForm.Invoke((EventHandler)(delegate
            {
                Show_data(s_data, textBox_data);
                foreach (Class_Code_DATA data in s_data)
                {
                    if (data.get_Code_Name().Equals("Current person coordinates")) { Show_Point(data, labelx, labely , command_progressBar1); }
                    else if (data.get_Code_Name().Equals("Sensing human coordinates")) { Paint_PIR(data , pictureBox_state);  }
                    else if (data.get_Code_Name().Equals("Power on initialization completed")) { talk_String(command_richTextBox , "Power on initialization completed"); }
                    else if (data.get_Code_Name().Equals("suspend")) { Command_progressBar_Stop(command_progressBar1); talk_String(command_richTextBox, "Pause completion"); Robot_state_set(2); }
                    else if (data.get_Code_Name().Equals("Test complete")) { Save_ImageAuto(mainForm , command_richTextBox,textBox401, textBox402, textBox403); Command_progressBar_Stop(command_progressBar1); talk_String(command_richTextBox, "Test complete"); Robot_state_set(2); }
                    else if (data.get_Code_Name().Equals("Reset complete")) {  Command_progressBar_Stop(command_progressBar1); talk_String(command_richTextBox, "Reset complete"); Robot_state_set(2); }
                    else if (data.get_Code_Name().Equals("Move complete")) { Command_progressBar_Stop(command_progressBar1); talk_String(command_richTextBox, "Move complete"); Robot_state_set(2); }

                    else if (data.get_Code_Name().Equals("Host to slave data warning")) { Command_progressBar_Stop(command_progressBar1); talk_String(command_richTextBox, "Host to slave data warning"); Robot_state_set(0); }
                    else if (data.get_Code_Name().Equals("Slave to host data warning")) { Command_progressBar_Stop(command_progressBar1); talk_String(command_richTextBox, "Slave to host data warning"); Robot_state_set(0); }
                    else if (data.get_Code_Name().Equals("Host to PC Machine data warning")) { Command_progressBar_Stop(command_progressBar1); talk_String(command_richTextBox, "Host to PC Machine data warning"); Robot_state_set(0); }
                    else {
                        if (data.get_Code_Name().Equals("temperature") || data.get_Code_Name().Equals("humidity")) { ; }
                        else { talk_String(command_richTextBox, data.get_Code_Name() + " " + data.get_Code_Data1() + "" + data.get_Code_Data2()); }
                    }
                }
                GC.Collect();
                GC.WaitForPendingFinalizers();
            }));
        }

        //------------------------------------------------------------------Feedback action program start---------------------------
        private void talk_String(RichTextBox command_richTextBox, String Str)
        {
            command_richTextBox.AppendText("\r\n" + "[ process ]" + "->" + Str);
            command_richTextBox.ScrollToCaret();
        }      

        private void Show_data(Class_Code_DATA[] s_data, TextBox textBox_data)
        {
            textBox_data.AppendText("[ process ]" + "->");
            foreach (Class_Code_DATA data in s_data)
            {
                textBox_data.AppendText("\r\n"
                    + data.get_Code_Aim() + " "
                    + data.get_Code_Name() + " "
                    + data.get_Code_Data1() + " "
                    + data.get_Code_Data2() + " ");
            }
            textBox_data.AppendText("\r\n");
        }

        private void Show_Point(Class_Code_DATA data, Label labelx, Label labely,ProgressBar command_progressBar1)
        {
            if ((labelx.Text != data.get_Code_Data1()) || (labely.Text != data.get_Code_Data2()))
            {
                if(command_progressBar1.Value< command_progressBar1.Maximum)
                {
                    command_progressBar1.Value += 1;

                }
                
            }
            labelx.Text = data.get_Code_Data1();
            labely.Text = data.get_Code_Data2();
            
        }
        private void Paint_PIR(Class_Code_DATA data, PictureBox pictureBox_state)
        {
            if (Robot_paint_receivecommand == false) { return; }
            class_My_Paint.Point_set(data.get_Code_Data1(), data.get_Code_Data2(), "Draw") ;
            class_My_Paint.PointBox_Paint(pictureBox_state.CreateGraphics(), "draw_point");
        }

         
    }
}

3. Main program debugging:

private void button201_Click(object sender, EventArgs e)
{
    String s_command;

    textBox_data.Clear();
    s_command = function_MainForm.RESET_Command(this, serialPort1);

    talk_String("Start reset, please wait");//Is a window output
 
}

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) //Serial port added program
{
    /*Serial port reception: register a Receive event for the serial port before using serial port reception,
       Equivalent to the serial port in the MCU receives the interrupt, and then reads the data in the buffer inside the interrupt*/
    String s_data = "";
    s_data = function_MainForm.Receive_data(this, serialPort1);
    Class_Code_DATA[] code_DATA = function_MainForm.Check_Data(this, s_data);
    function_MainForm.Deal_The_Data(this, code_DATA, textBox_data, Point_Box, command_richTextBox1, label6, label7, command_progressBar1, textBox401, textBox402, textBox403);
    
    GC.Collect();  //garbage collection
    GC.WaitForPendingFinalizers(); 
}

Refer to the blogger's blog.
C# upper computer development (VI) -- function optimization of serial assistant (serial port automatic scanning function, receiving data saving function, loading and sending files, sending history record, opening browser function and regular sending function)

summary

Note that the serial port is a thread independent of the form, and the delegation must be used to update the status of the window under the serial port data:

mainForm.Invoke((EventHandler)(delegate{ }));

Keywords: C# Single-Chip Microcomputer stm32

Added by itworks on Tue, 18 Jan 2022 23:36:30 +0200