C#连续读串口,然后进行数据处理,前面20几分钟都正常,30分钟左右以后开始出错

yilaozhuang 2016-08-07 09:44:27
各位大神,给帮忙看看我这个是为什么:
我用C#去读串口,每秒钟读一次,速率9600,每次读88个字节。
程序开始的20几分钟一切正常,30分钟以后开始各种出问题,比如丢字节啥的,每次的88个总凑不够数。
不明白这是为什么?开始的20几分钟能正常运行,说明程序的基本逻辑和语句都是对的吧,后面怎么出错了呢?
====================
百度了一下,有人说是不能在读串口的线程里对读到的数据处理,我读到串口数据以后,下面的数据处理语句还挺多的,估计有几百行,不知道是否跟这个有关?

...全文
464 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
yilaozhuang 2016-08-08
  • 打赏
  • 举报
回复

while (com.IsOpen == true)
            {
                try
                {
                    int status_limit1 = 0;
              。。。。。。
                    int status_limit10 = 0;

                    Byte[] Data = new byte[Num_data2read];
                    Byte[] Num_battery = new Byte[10];

                    int num_combuffer = com.BytesToRead;
                    //System.Threading.Thread.Sleep(100);                                       

                //这个是读取串口的条件,现在秒钟读88个字节,Num_data2read就是88。每次读串口的条件是:缓冲区字节数为88,并且等待50ms,字节没有增加,认为数据正确,读取串口缓冲区
//////////////////////////////////大神们给看看,这个判断条件没问题吧??
                    if (num_combuffer == Num_data2read)
                    {
                        System.Threading.Thread.Sleep(50);
                        int num_combuffer1 = com.BytesToRead;                        
                        if (num_combuffer1 == num_combuffer)
                        {
//初始化一下,10组数据,每组数据有7个数
                            T11 = 0;
                            T12 = 0;
                            T13 = 0;
                            T14 = 0;
                            T15 = 0;
                            P11 = 0;
                            F11 = 0;
                          。。。。。
                            TA1 = 0;
                            TA2 = 0;
                            TA3 = 0;
                            TA4 = 0;
                            TA5 = 0;
                            PA1 = 0;
                            FA1 = 0;

                            //读串口1                            
                            com.Read(Data, 0, num_combuffer);

                            //错误测试代码,最后删除&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
                            string str_receive = "";
                            for (int i = 0; i < 44 * Num_terminal1 + 44; i = i + 22)
                            {
                                str_receive = str_receive + Data[i].ToString("x2") + Data[i + 1].ToString("x2)。。。。。。。tring("x2") + Data[i + 20].ToString("x2") + Data[i + 21].ToString("x2") + "\r\n";
                            }

                            FileStream fs_data = new FileStream(Name_data, FileMode.Append);
                            StreamWriter sw_data = new StreamWriter(fs_data);
                            //开始写入
                            sw_data.Write(DateTime.Now.ToLongTimeString() + "\r\n" + str_receive + "\r\n");
                            //清空缓冲区
                            sw_data.Flush();
                            //关闭流
                            sw_data.Close();
                            fs_data.Close();
                            //错误测试代码,最后删除&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
////////由于10组数据来的先后顺序不同,需要根据地址进行排序,sort_num_battery是对数据组进行排序
                            Num_battery = Sort_num_battery(Data);
/////下面是对拍好顺序的数据进行计算真实值,然后对界面上的对应位置进行更新显示
                            //解析第一个电池数据
                            Byte[] temp_battery_org1 = new Byte[16];
                            double[] temp_battery_res1 = new double[7];
                            int Num_1 = Num_battery[0];
                            if (Num_1 > 0)
                            {
                                temp_battery_org1[0] = Data[Num_1 + 2];
                               .....
                                temp_battery_org1[15] = Data[Num_1 + 17];
                                temp_battery_res1 = Jiexi_onebattery(temp_battery_org1);

                                T11 = cal_zero[0, 0] * temp_battery_res1[0] + cal_zero[0, 1];
                              .....
                                F11 = cal_zero[6, 0] * temp_battery_res1[6] + cal_zero[6, 1];

                                status_limit1 = 0;
                                if (T11 > Convert.ToDouble(textBox_TMX11.Text))
                                {
                                    status_limit1 = status_limit1 + 128;
                                }
                                ......
                                if (F11 > Convert.ToDouble(textBox_FMX11.Text))
                                {
                                    status_limit1 = status_limit1 + 2;
                                }

                                SetTextBox_T11(T11);
                                ....
                                SetTextBox_F11(F11);
                                ChangeImagePic_TMX11(T11);
                                ....
                                ChangeImagePic_FMX11(F11);
                            }
                            else
                            {
                                SetTextBox_T11(T11);
                                SetTextBox_T12(T12);
                                SetTextBox_T13(T13);
                                SetTextBox_T14(T14);
                                SetTextBox_T15(T15);
                                SetTextBox_P11(P11);
                                SetTextBox_F11(F11);
                                ChangeImagePic_TMX11(T11);
                                ChangeImagePic_TMX12(T12);
                                ChangeImagePic_TMX13(T13);
                                ChangeImagePic_TMX14(T14);
                                ChangeImagePic_TMX15(T15);
                                ChangeImagePic_PMX11(P11);
                                ChangeImagePic_FMX11(F11);
                            }

//。。。。。。。。。。。。剩下的9组数据和界面控件操作,跟第一个完全一样
                           
//把计算好的前面1组数据,写入到excel表

                            DateTime T0 = DateTime.Now;
                            //写入电池1数据
                            //获得需要写入行的编号
                            int rowCount1 = worksheet1.LastRowNum + 1;
                            //创建行
                            IRow row_i = worksheet1.CreateRow(rowCount1);
                            //写新行的每个列
                            ICell cell10 = row_i.CreateCell(0);
                            cell10.SetCellValue(rowCount1);

                            ICell cell11 = row_i.CreateCell(1);
                            cell11.SetCellValue(T0);

                            ICell cell12 = row_i.CreateCell(2);
                            cell12.SetCellValue(T11);

                            ICell cell13 = row_i.CreateCell(3);
                            cell13.SetCellValue(T12);

                            ICell cell14 = row_i.CreateCell(4);
                            cell14.SetCellValue(T13);

                            ICell cell15 = row_i.CreateCell(5);
                            cell15.SetCellValue(T14);

                            ICell cell16 = row_i.CreateCell(6);
                            cell16.SetCellValue(T15);

                            ICell cell17 = row_i.CreateCell(7);
                            cell17.SetCellValue(P11);

                            ICell cell18 = row_i.CreateCell(8);
                            cell18.SetCellValue(P12);

                            ICell cell19 = row_i.CreateCell(9);
                            cell19.SetCellValue(F11);

                            ICell cell1a = row_i.CreateCell(10);
                            cell1a.SetCellValue(status_limit1);

                       。。。。。   //写入2-10组数据的excel表操作,与第一组完全相同
                            using (FileStream fs = File.Open(strSaveFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                            {
                                wk1.Write(fs);
                                fs.Close();
                            }

                            //实时更新曲线
//把数据加入到显示曲线的数组里
                            //电池1
                            Data_T11.Add(rowCount1, T11);
                            Data_T12.Add(rowCount1, T12);
                            Data_T13.Add(rowCount1, T13);
                            Data_T14.Add(rowCount1, T14);
                            Data_T15.Add(rowCount1, T15);
                            Data_P11.Add(rowCount1, P11);
                            Data_F11.Add(rowCount1, F11);
                            //电池2
                           。。。。。。把数据加入到显示曲线的数组里,2-10个,与第一个完全相同

                            string Battery_num = listBox_BatteryNum.SelectedItem.ToString();
//界面显示数据组的一些简单操作
                            if (Battery_num == "电池1")
                            {
                                if (radioButton_T1.Checked)
                                {
                                    T_F_P = "T1";
                                    Data_temp = Data_T11;
                                }
                                。。。。。。。。
                            //线程等待更新
                            RealTime_Update_Curve(Battery_num, T_F_P, Data_temp);
                            System.Windows.Forms.Application.DoEvents();
                            System.Threading.Thread.Sleep(50);
                        }                          
                            
                        else if ((num_combuffer1 > 44) & (num_combuffer1 < Num_data2read))
                        {
                            com.ReadExisting();
                            //Num_error = DateTime.Now.ToString();
                             FileStream fs_error = new FileStream(Name_error, FileMode.Append);
                            StreamWriter sw_error = new StreamWriter(fs_error);
                            //开始写入
                            sw_error.Write(DateTime.Now.ToString() +"字节少"+ "\r\n");
                            //清空缓冲区
                            sw_error.Flush();
                            //关闭流
                            sw_error.Close();
                            fs_error.Close();                                
                        }                             
                    }  
                }

yilaozhuang 2016-08-08
  • 打赏
  • 举报
回复
引用 5 楼 just59277 的回复:
读取数据和处理数据分开来弄吧,感觉可能是你处理数据里面用来保存数据的数组或者集合越来越大的缘故。 另外你没贴代码,总不能靠猜测去推断问题吧。
由于串口不断读数据,后面处理的数据,需要用曲线显示,这样保存数据的数组确实是不断增大,并且又20个相同的通道。这样存储数据的数组越来越大。我一会把代码贴上来,大神再给分析一下,谢谢先
a199101sdo 2016-08-08
  • 打赏
  • 举报
回复
酱油 串口 没概念
  • 打赏
  • 举报
回复
no code no truth
我叫小菜菜 2016-08-08
  • 打赏
  • 举报
回复
在读串口和其他关键地方,写上日志。然后跑30分钟尝试重现问题。
charmign1 2016-08-08
  • 打赏
  • 举报
回复
估计是读得太慢,串口接收缓存满了
小程序员 2016-08-08
  • 打赏
  • 举报
回复
每次读完后清空下接收缓冲区试试
just59277 2016-08-08
  • 打赏
  • 举报
回复
读取数据和处理数据分开来弄吧,感觉可能是你处理数据里面用来保存数据的数组或者集合越来越大的缘故。 另外你没贴代码,总不能靠猜测去推断问题吧。
mjp1234airen4385 2016-08-08
  • 打赏
  • 举报
回复
如果处理数据的代码比较复杂,建议另开线程处理,这样就不会影响到串口的线程了
拜一刀 2016-08-08
  • 打赏
  • 举报
回复
记录下读取的数据吧,还有每次操作花费时间啦内存的占用情况之类的 还有,包头包尾校验、丢弃错误数据之类的处理有做好吗?
redshiliu 2016-08-08
  • 打赏
  • 举报
回复
无论你定时轮询还是通过串口组件的事件来接受数据,较安全的方法是将每次读取的数据放入一个缓冲区,然后另外开一个线程去处理该缓冲区中的数据(注意同步),因为系统并不保证每次有数据到达时串口接受缓冲区内是包含了整个包的数据,可能是分两次或三次才接受完毕。如果你的通讯协议每个包都是88字节可以通过设置ReceivedBytesThreshold = 88来实现。
Poopaye 2016-08-07
  • 打赏
  • 举报
回复
我猜是电脑过热了,然后就罢工了

110,535

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧