/ Others / 47 views

[C#] Implementing PC-based software for microcontroller, example of serial communication

Before doing inverter projects, it is necessary to control the frequency and line voltage of the inverter through the host computer. With C#, you can quickly build a simple graphical interface, implement related functions quickly, and generate .exe files to run on Windows. Here, I will mainly share how to use serial communication. The complete project files are attached at the end.

The upper computer program in the plan should have the ability to search for serial ports, that is, communicate with the specified serial port. In addition, it should be able to display the current voltage and frequency, and set new voltage and frequency.

First, set up the interface framework. Here we only need one page, and there is no need for complex functions. Set up the interface as follows:

The button in the top left is responsible for the search serial port function. Bind an event to it:

this.ButtonSearchSP.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
this.ButtonSearchSP.Location = new System.Drawing.Point(41, 46);
this.ButtonSearchSP.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
this.ButtonSearchSP.Name = "ButtonSearchSP";
this.ButtonSearchSP.Size = new System.Drawing.Size(100, 29);
this.ButtonSearchSP.TabIndex = 0;
this.ButtonSearchSP.Text = "搜索串口";
this.ButtonSearchSP.UseVisualStyleBackColor = true;
this.ButtonSearchSP.Click += new System.EventHandler(this.ButtonSearchSP_Click);

The processing function for the click event is as follows:

private void ButtonSearchSP_Click(object sender, EventArgs e)
{
    LabelStatus.Text = "正在搜索。。。"; //点击后更改状态标签文字
    string[] serialNames = System.IO.Ports.SerialPort.GetPortNames();

    ProgressBar.Value = ProgressBar.Minimum ; 

    //对每个串口进行判断
    for (int i = 0; i < serialNames.Length; i++)
    {
        ProgressBar.Value += ProgressBar.Step;
        try
        {
            isMatched = false;
            // serialPort是用来主动通信的串口 
            // 声明为 private System.IO.Ports.SerialPort serialPort;
            if (serialPort.IsOpen){
                serialPort.Close();
            }

            serialPort.PortName = serialNames[i];
            serialPort.BaudRate = 115200; // 我设定波特率为115200
            serialPort.DataBits = 8;
            serialPort.Parity = System.IO.Ports.Parity.None;
            serialPort.StopBits = System.IO.Ports.StopBits.One;
            serialPort.Open();

            int t1 = 1000*DateTime.Now.Second+DateTime.Now.Millisecond;
            // 试着通信200ms
            while (1000 * DateTime.Now.Second + DateTime.Now.Millisecond - t1 < 200) ;

            // 读取数据
            int len = serialPort.BytesToRead;
            len = len > 100 ? 100 : len;
            Byte[] readBuffer = new Byte[len];
            serialPort.Read(readBuffer, 0, len);
            serialPort.DiscardInBuffer();  //清空接收缓冲区  

            for (int j = 0; j < len-1; j++)
            {
                // 寻找通信头,这里13 10是我设置的通信头,由单片机发出
                // 在识别到13 10后,确定是连接单片机的串口
                if (readBuffer[j] == 13 && readBuffer[j + 1] == 10) {
                    isMatched = true;
                break;
                }
            }
            if (isMatched)
            {
                LabelStatus.Text = "已找到"+ serialPort.PortName;
                ProgressBar.Value = ProgressBar.Maximum;
                groupBox1.Enabled = true;
                return;
            }
         }
         catch{
            continue;
         }
         if (serialPort.IsOpen)
         {
         serialPort.Close();
         }
    }
    LabelStatus.Text = "未找到串口";
    ProgressBar.Value = ProgressBar.Minimum;
}

Similarly, the “Confirm Settings” button also needs to be bound to a click event, responsible for notifying the microcontroller of the set voltage frequency.

private void button1_Click(object sender, EventArgs e)
{
    try
    {
        //将字符串转换成double类型
        double f = Convert.ToDouble(textBox1.Text);
        double v = Convert.ToDouble(textBox2.Text);
        // 预设的变化范围
        if ( f> 10 && f < 250)
        {
            Byte[] sendBuffer = new Byte[6];
            sendBuffer[0] = (Byte)v; sendBuffer[1] = (byte)((v - (double)sendBuffer[0]) * 100 + 0.5);
            sendBuffer[2] = (Byte)f; sendBuffer[3] = (byte)((f - (double)sendBuffer[2])*100+0.5);
            sendBuffer[4] = 13; sendBuffer[5] = 10;
            serialPort.Write(sendBuffer,0,6);
        }
    }
    catch {
        MessageBox.Show("频率范围 10~250 Hz");   
    }

}

Finally, add the program for real-time display of sensor data from the microcontroller. This processing function is also registered in the Designer file of the form.

this.serialPort.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(this.SerialDataRecveived);

private void SerialDataRecveived(Object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
    if (isMatched)
    {
        //接收数据事件处理
        try
        {
            //BytesToRead为要读入的字节长度
            int len = serialPort.BytesToRead;
            if (len > 5) {
                Byte [] readBuffer = new Byte[len];
                serialPort.Read(readBuffer, 0, len); //将数据读入缓存
                                                     //处理readBuffer中的数据
                serialPort.DiscardInBuffer();  //清空接收缓冲区  

                for (int j = 0; j < len - 1; j++)
                {
                    if (readBuffer[j] == 13 && readBuffer[j + 1] == 10)
                    {
                        if (j >= 4)
                        {
                            float v = readBuffer[j-4]+readBuffer[j-3]/100.0f;
                            float f = readBuffer[j - 2] + readBuffer[j - 1] / 100.0f;
                            this.Invoke(new EventHandler(delegate
                            {
                                label2.Text = v + " V";
                                label4.Text = f + " Hz";
                            }));

                        }
                        else { continue; }
                        break;
                    }
                }

            }
        }
        catch (Exception ex)
        {
            groupBox1.Enabled = false;
            LabelStatus.Text = "连接中断";
        }
    }
}

The main processing function flow is roughly as follows.

The reference address for the entire project file is as follows:

Link: https://pan.baidu.com/s/1MEPvyW25zRNk-lh-0qNk2Q?pwd=h9rf Access code: h9rf

Eysent
[Python] Backtracking recursive method solves Sudoku puzzles
[Python] Backtracking recursive method solves Sudoku puzzles

0

  1. This post has no comment yet

Leave a Reply

Your email address will not be published. Required fields are marked *