打印
[工具下载]

数据通过串口实时传到上位机中

[复制链接]
399|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
robincotton|  楼主 | 2023-8-27 16:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
作者:番茄炒鸡蛋
链接:https://www.zhihu.com/question/346164139/answer/2386256780
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

在原有上位机的基础上,简单做了一款显示转速波形和电压 电流的上位机。当然了其中还存在一些问题,不过用于显示和调试PID问题不大。
1.整体界面如下
  分为串口选择和设置区,数据显示区,监控信息区,数据缓存以及曲线显示。
2.上位机在获取多个数据时候,串口如何识别哪个是电流电压和转速呢?
   由于串口一次发送一个字节。对于超过255的数据 只能分开发。一次性发很多数据,上位机也不能把一组数据提取出来进行整合显示对应的物理量。基于以上问题,我就采用了以下的方法。单片机发送数据以一个包进行发送,包的开始以0xFF开始,结束以0x55结束(当然了也有局限性),程序如下:
         if(Transmit_Time>=800) //5ms
         {
                                 Transmit_Time=0;
                                 Main_Num++;
                                 if( Main_Num==1)
                                 {
                                   USART_SendData(USART1,0xFF);  //字节0
                                 }
                                 if( Main_Num==2) //实时性高的发送优先级高--转速 显示曲线
                                 {                          
                                      USART_SendData(USART1,Motor.ActualSpeed/255); //字节1
                                       USART_SendData(USART1,Motor.ActualSpeed%255); //字节2
                                 }
                                 if( Main_Num==3) //优先级次之---电流
                                 {
                                    USART_SendData(USART1,((uint16_t)(Motor.Current))/255);//字节3
                                    USART_SendData(USART1,((uint16_t)(Motor.Current))%255);//字节4                                        
                                 }
                           if(Main_Num==4) //电压
                           {
                              USART_SendData(USART1,ADCSampPare.BUS_Voltage);  //字节5
                           }
                           if(Main_Num==5) //PCB温度
                           {
                                    USART_SendData(USART1,ADCSampPare.PCB_Temp);//字节 6
                            }
                         if( Main_Num==3)
                         {
                                 Main_Num=0;
                                 USART_SendData(USART1,0xFF);  //字节7
                           }
     }
上位机接受数据程序:
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            try
            {
                int n = serialPort1.BytesToRead;
                byte[] Receive = new byte[n];
serialPort1.Read(Receive, 0, Receive.Length);
                bool DataCatched = false;//数据可以分析的标志
                //缓存数据
                ReceBuffer.AddRange(Receive);     
                //完整性判断
                 while (ReceBuffer.Count >= 8)
                {
                    //这里可以写成对数据的校验如CRC
                    if (ReceBuffer[0] == 0xff && ReceBuffer[7] == 0xff)
                    {
                        ReceBuffer.CopyTo(0, DataTemp, 0, 8);
                        DataBuf.AddRange(DataTemp);
                        DataCatched = true;

                        ReceBuffer.RemoveRange(0, 8);//获得一条正确的数据,删除缓存
                    }
                    else
                    {
                        ReceBuffer.RemoveAt(0);//不是数据头,删除数据
                    }
                }
                //分析数据
                if (DataCatched == true)
                {
                    while (DataBuf.Count > 0)
                    {
                        DataBuf.CopyTo(0, DataTemp2, 0, 8);
                        //数据分析
                        Test.Speed_Buffer[0] = DataTemp2[1] * 255 + DataTemp2[2];//转速
                       Test.Speed_Buffer[2] = DataTemp2[3] * 255 + DataTemp2[4];//电流
                        if (Test.Speed_Buffer[0] > 0)
                        {
                             Flag_Data_Save = true;
                        }
                       string str = Convert.ToString((DataTemp2[1] * 255 + DataTemp2[2]), 10).ToUpper(); //转速
                       string str1 = Convert.ToString(DataTemp2[3] * 255 + DataTemp2[4], 10).ToUpper();  //电流
                        string str2 = Convert.ToString(DataTemp2[5], 10).ToUpper();  //电压
                        string str3 = Convert.ToString(DataTemp2[6], 10).ToUpper();  //温度

                        if ((Test.Speed_Buffer[0] - Test.Speed_Buffer[1]) > 50 || ((Test.Speed_Buffer[1] - Test.Speed_Buffer[0]) > 50))
                        {
                            textBox3.Text = str + "r/min";
                        }
                       if ((Test.Speed_Buffer[2] - Test.Speed_Buffer[3]) > 50 || ((Test.Speed_Buffer[3] - Test.Speed_Buffer[2]) > 50))
                        {
                            textBox2.Text = str1 + "mA";
                        }

                        textBox1.Text = str2 + "V";
                        textBox4.Text = str3 + "℃";
                        Speed_Temp = str;
                        if ((Test.Speed_Buffer[1] - Test.Speed_Buffer[0]>200)&&(Test.Speed_Buffer[0]>1000) ) //当前转速低于上一个太多
                        {
                            textBox5.AppendText("转速异常\r\n");

                        }
                        Test.Speed_Buffer[1] = Test.Speed_Buffer[0];
                        Test.Speed_Buffer[3] = Test.Speed_Buffer[2];
textBox1.AppendText((str.Length == 1 ? "0" + str : str) + " ");//速度
                        progressBar1.Value = DataTemp2[5];  //电压
                        progressBar2.Value = DataTemp2[3] * 255 + DataTemp2[4];  //电流
                        progressBar3.Value = DataTemp2[6];  //PCB温度
                        progressBar4.Value = DataTemp2[1] * 255 + DataTemp2[2];//转速

                        if(progressBar2.Value>=19000)
                        {
                            textBox5.AppendText("电流过大\r\n");

                        }
                       Delay(1000);//不延时的话不显示
Thread.Sleep(10);
                        DataBuf.RemoveRange(0, 4);
                    }
                }
            }
            catch { }
        }
数据能够正常接收和显示,但这只是基础版本的,还有很多细节没有处理,后面会不管完善!以下是我电机转速调节转速曲线图:



使用特权

评论回复
沙发
minzisc| | 2023-9-7 10:02 | 只看该作者
使用 上位机程序从串口读取数据。这通常涉及使用读取函数(如Serial.read())或轮询串口缓冲区。

使用特权

评论回复
板凳
51xlf| | 2023-9-7 10:39 | 只看该作者
可以使用相应的传感器模块来采集数据。采集到的数据可以通过串口写入缓冲区,然后通过串口发送出去。

使用特权

评论回复
地板
10299823| | 2023-9-7 10:44 | 只看该作者
在单片机中设置串口的波特率、数据位、停止位等参数

使用特权

评论回复
5
jtracy3| | 2023-9-7 12:11 | 只看该作者
需要调用相关的API函数来配置串口。在大多数编程语言和操作系统下,都提供了相应的序列通信库或模块

使用特权

评论回复
6
updownq| | 2023-9-7 12:49 | 只看该作者
可以使用相应的API函数从串口读取数据。在成功读取数据后,您需要对数据进行解析和处理,以便将其转换为可视化或者计算机可读的格式。

使用特权

评论回复
7
loutin| | 2023-9-7 13:43 | 只看该作者
在开始传输数据之前,您需要确定串口的通信协议和参数,包括波特率、数据位、停止位和校验位等。这些参数应该与上位机端设置一致,以确保数据传输的正确性。

使用特权

评论回复
8
mollylawrence| | 2023-9-7 13:57 | 只看该作者
数据通过串口实时传到上位机中需要考虑数据的正确性和可靠性,以及数据的传输速率和延迟等因素

使用特权

评论回复
9
i1mcu| | 2023-9-7 14:29 | 只看该作者
在上位机中编写串口通信程序,包括接收数据、处理数据、显示数据等功能。

使用特权

评论回复
10
updownq| | 2023-9-7 14:36 | 只看该作者
在单片机中编写串口通信程序,包括发送数据、接收数据、处理数据等功能。

使用特权

评论回复
11
sdCAD| | 2023-9-7 14:57 | 只看该作者
在单片机和上位机上分别运行串口通信程序,以实现数据的实时传输。

使用特权

评论回复
12
tpgf| | 2023-9-11 12:16 | 只看该作者
上位机的软件可以编写为自适应的吗

使用特权

评论回复
13
heimaojingzhang| | 2023-9-11 13:08 | 只看该作者
tpgf 发表于 2023-9-11 12:16
上位机的软件可以编写为自适应的吗

我觉得是可以额 但是得保证通讯的稳定

使用特权

评论回复
14
keaibukelian| | 2023-9-11 19:00 | 只看该作者
数据通讯的具体内容是自己定义的吗

使用特权

评论回复
15
zhuotuzi| | 2023-9-26 20:21 | 只看该作者
数据通信。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

12

主题

1140

帖子

0

粉丝