9-ESP8266 SDK開發基礎入門篇--編寫串口上位機軟件


https://www.cnblogs.com/yangfengwu/p/11087613.html

 

頁面修改成這樣子

 

 

            

 

 

 

 

現在看串口發送數據 

點擊點亮 發送0xaa 0x55 0x01    

 我電腦上安裝了虛擬串口軟件,虛擬出來了COM1和COM2,然后COM1發送的數據會發給COM2  COM2發送的數據會發給COM1

大家如果有兩個串口模塊也可以

 

 

 

 

https://jingyan.baidu.com/article/e3c78d648965303c4c85f535.html

 

 

 

那個按鈕的程序這樣寫

 

 

 測試一下

 

 

 

現在看串口接收數據

 

 

 

 說一下哈,這個是上位機的串口中斷函數,就是只要接收到數據就會進入這個中斷

現在咱讀出來接收的數據,然后顯示在

 

 讀取數據給了好幾個方法

咱就說1個,哈哈哈,其實自己一選擇方法的時候就有中文注釋......

 

 

大家注沒注意

 

 

現在調用一個函數讀出來,然后顯示出來

 

 

ReadExisting()   這個方法就會返回緩沖區里面的所有字節,注意返回的是字符串形式的

調用這個方法就是  serialPort1.ReadExisting();       serialPort1就是咱的

 

因為咱就是要里面的數據所以  

string str = serialPort1.ReadExisting();//讀出來當前緩存里面的所有數據

 

 

 

Invoke((new Action(() =>
{
    這里面放要操作的主線程的控件的方法
})));

其實這個方法主要是方便解決一個問題,稍候再說,咱先測試一下哈

 

 

 

 說明可以了,現在呢,咱去掉

 

 

 

 

 

 大家可以點開那個  如何跨線程調用 Windows 窗體控件

大家可以看這個 https://www.cnblogs.com/yangfengwu/p/5761841.html   (最好別看,看了就會感覺麻煩)

4.0之后引進了這種方法

 

 對於初學者知道這個就可以了,像C#,C++,JAVA等等這種高級語言哈,因為可以做界面了,,高級語言規定,操作頁面不能在子線程中進行

哪些是子線程呢!..像上面那個串口中斷函數,還有自己創建的任務Thread,,,等等吧

好現在,咱接收16進制,

接收到

 

0xaa 0x55 0x01  

 

 

0xaa 0x55 0x00  

 

 

 好,上菜

 

        //串口接收到數據就會進入
        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            int len = serialPort1.BytesToRead;//獲取可以讀取的字節數
            if (len > 0)
            {
                byte[] recvBytes = new byte[len];//創建接收的數組
                serialPort1.Read(recvBytes, 0, len);//接收數據
                if (recvBytes[0] == 0xaa && recvBytes[1] == 0x55)//判斷數據
                {
                    if (recvBytes[2] == 0x01)//
                    {
                        Invoke((new Action(() =>
                        {
                            button3.Text = "熄滅";
                            label5.Text = "點亮";
                        })));
                    }
                    else if (recvBytes[2] == 0x00)
                    {
                        Invoke((new Action(() =>
                        {
                            button3.Text = "點亮";
                            label5.Text = "熄滅";
                        })));
                    }
                }
            }
            //string str = serialPort1.ReadExisting();//讀出來當前緩存里面的所有數據
            //Invoke((new Action(() =>
            //{
            //    //顯示在文本框里面
            //    textBox1.AppendText(str);
            //})));
        }

 

 

 

 

 

 

 

 

 測試

 

 

 

 

 

 雖然可以了,但是這樣寫不保險...

原因是那個中斷是不定長的數據就進去(受到電腦整體運行狀態的影響),所以呢咱優化下

 

 

        //串口接收到數據就會進入
        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            int len = serialPort1.BytesToRead;//獲取可以讀取的字節數
            if (len > 0)
            {
                byte[] recvBytes = new byte[len];//創建接收的數組
                serialPort1.Read(recvBytes, 0, len);//接收數據

                for (int i = 0; i < len; i++)//拷貝數據到UsartReadBuff
                {
                    UsartReadBuff[i+ UsartReadCnt] = recvBytes[i];//從上次的地方接着填入數據
                }
                UsartReadCnt = UsartReadCnt + len;//記錄上次的數據個數
                if (UsartReadCnt >= 3)//接收到可以處理的數據個數
                {
                    UsartReadCnt = 0;
                    if (UsartReadBuff[0] == 0xaa && UsartReadBuff[1] == 0x55)//判斷數據
                    {
                        if (UsartReadBuff[2] == 0x01)//
                        {
                            Invoke((new Action(() =>
                            {
                                button3.Text = "熄滅";
                                label5.Text = "點亮";
                            })));
                        }
                        else if (UsartReadBuff[2] == 0x00)
                        {
                            Invoke((new Action(() =>
                            {
                                button3.Text = "點亮";
                                label5.Text = "熄滅";
                            })));
                        }
                    }
                }
            }
            //string str = serialPort1.ReadExisting();//讀出來當前緩存里面的所有數據
            //Invoke((new Action(() =>
            //{
            //    //顯示在文本框里面
            //    textBox1.AppendText(str);
            //})));
        }

自己測試哈

現在說一下

 

 如果接收的是字符串,想顯示出來

 

 

 

 

 

 

如果發過來了16進制   注意哈,發過來的是16進制  假設 00  就是數字0   因為那個文本框顯示的時候是顯示的字符串

所以需要轉成  "00"    發過來0F   需要顯示字符串形式的  "0F"

 

給大家准備好了

        /// <字節數組轉16進制字符串>
        /// <param name="bytes"></param>
        /// <returns> String 16進制顯示形式</returns>
        public static string byteToHexStr(byte[] bytes)
        {
            string returnStr = "";
            try
            {
                if (bytes != null)
                {
                    for (int i = 0; i < bytes.Length; i++)
                    {
                        returnStr += bytes[i].ToString("X2");
                        returnStr += " ";//兩個16進制用空格隔開,方便看數據
                    }
                }
                return returnStr;
            }
            catch (Exception)
            {
                return returnStr;
            }
        }

 

        //串口接收到數據就會進入
        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            int len = serialPort1.BytesToRead;//獲取可以讀取的字節數
            if (len > 0)
            {
                byte[] recvBytes = new byte[len];//創建接收的數組
                serialPort1.Read(recvBytes, 0, len);//接收數據

                Invoke((new Action(() =>//顯示字符串
                {
                    textBox1.AppendText("字符串:"+Encoding.Default.GetString(recvBytes)); //顯示在文本框里面
                })));

                Invoke((new Action(() =>//顯示16進制
                {
                    textBox1.AppendText("\r\n16進制:" + byteToHexStr(recvBytes) + "\r\n"); //顯示在文本框里面
                })));

                for (int i = 0; i < len; i++)//拷貝數據到UsartReadBuff
                {
                    UsartReadBuff[i+ UsartReadCnt] = recvBytes[i];//從上次的地方接着填入數據
                }
                UsartReadCnt = UsartReadCnt + len;//記錄上次的數據個數
                if (UsartReadCnt >= 3)//接收到可以處理的數據個數
                {
                    UsartReadCnt = 0;
                    if (UsartReadBuff[0] == 0xaa && UsartReadBuff[1] == 0x55)//判斷數據
                    {
                        if (UsartReadBuff[2] == 0x01)//
                        {
                            Invoke((new Action(() =>
                            {
                                button3.Text = "熄滅";
                                label5.Text = "點亮";
                            })));
                        }
                        else if (UsartReadBuff[2] == 0x00)
                        {
                            Invoke((new Action(() =>
                            {
                                button3.Text = "點亮";
                                label5.Text = "熄滅";
                            })));
                        }
                    }
                }
            }
        }

 

 

 

 

 

 

 

 現在看發送

發送就只做字符串發送哈,,,16進制發送后期補上,,大家先吸收吸收現在的....

 

 

 

 

 

 執行文件

 

 

我把16進制發送用到的函數放在這里,后期再回來加上

        /// <字符串轉16進制格式,不夠自動前面補零>
        /// 
        /// </summary>
        /// <param name="hexString"></param>
        /// <returns></returns>
        private static byte[] strToToHexByte(String hexString)
        {
            int i;
            bool Flag = false;


            hexString = hexString.Replace(" ", "");//清除空格
            if ((hexString.Length % 2) != 0)
            {
                Flag = true;
            }
            if (Flag == true)
            {
                byte[] returnBytes = new byte[(hexString.Length + 1) / 2];

                try
                {
                    for (i = 0; i < (hexString.Length - 1) / 2; i++)
                    {
                        returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
                    }
                    returnBytes[returnBytes.Length - 1] = Convert.ToByte(hexString.Substring(hexString.Length - 1, 1).PadLeft(2, '0'), 16);

                }
                catch
                {
                    for (i = 0; i < returnBytes.Length; i++)
                    {
                        returnBytes[i] = 0;
                    }
                    MessageBox.Show("超過16進制范圍A-F,已初始化為0", "提示");
                }
                return returnBytes;
            }
            else
            {
                byte[] returnBytes = new byte[(hexString.Length) / 2];
                try
                {
                    for (i = 0; i < returnBytes.Length; i++)
                    {
                        returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
                    }
                }
                catch
                {
                    for (i = 0; i < returnBytes.Length; i++)
                    {
                        returnBytes[i] = 0;
                    }
                    MessageBox.Show("超過16進制范圍A-F,已初始化為0", "提示");
                }
                return returnBytes;
            }
        }

 

 

對了,其實上位機串口是有空閑時間中斷的(異常捕獲),只不過,我還沒細研究呢!!!

 

https://www.cnblogs.com/yangfengwu/p/11094009.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM