zoukankan      html  css  js  c++  java
  • 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("
    16进制:" + byteToHexStr(recvBytes) + "
    "); //显示在文本框里面
                    })));
    
                    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

  • 相关阅读:
    数论笔记
    哈哈哈
    闭关修炼屯题中,期末考完A
    acm几何
    POJ
    Educational Codeforces Round 42 (Rated for Div. 2) D.Merge Equals (优先队列)
    Educational Codeforces Round 42 (Rated for Div. 2) C. Make a Square (dfs)
    牛客网 VVQ 与线段 (优先队列或线段树或RMQ)
    Educational Codeforces Round 41 (Rated for Div. 2) C.Chessboard (DP)
    Educational Codeforces Round 41 (Rated for Div. 2)D. Pair Of Lines
  • 原文地址:https://www.cnblogs.com/yangfengwu/p/11087618.html
Copyright © 2011-2022 走看看