Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2349615
  • 博文数量: 816
  • 博客积分: 10000
  • 博客等级: 上将
  • 技术积分: 5010
  • 用 户 组: 普通用户
  • 注册时间: 2008-12-17 17:57
文章分类

全部博文(816)

文章存档

2011年(1)

2008年(815)

分类:

2008-12-17 18:08:03

您看一下我原来发的老帖子,也都是关于同一个问题,数据丢失的问题。

今天来此,还是这个,真的很苦恼。

我的流程如下:

串口控件设置如下:
    YbCommDevice1->PackageInterval = 50;
    YbCommDevice1->PackageSize = 1024;
    YbCommDevice1->PackageType = cptFrameTimeout;
    YbCommDevice1->UsePackage = true;

发送一条命令以后,就开始进行采集,开始返回数据。数据的返回规则具体如下:

每隔125毫秒发送回一个2字节的数据,我的测试程序里除了将每次返回的数据保存到一个整型数组里,什么都不进行动作。但是在采集的同时,我打开一些杀毒软件、系统的磁盘整理程序运行、动作,则数据就会丢失,我用来进行计数的计数器也会变化的一会慢一会快,最终检查一下数据还是丢了。

我用的是新的1.3.3.5版本的,OnPackage事件里部分代码如下:

    if(NotifyType & EV_RXCHAR) //如果 NotifyType 的 RXCHAR 位为 1
    {
        unsigned char Buf[1024]; //收到的字节数不会超过串口缓存的容量, 所以分配一个缓存容量相同的Buf
        int n = YbCommDevice1->ReadPackage(Buf, 1024); //收到 n 个字节
        if(n == 0) return;

        AnsiString s;
        static int dataCount1 = 0;

        for(int i=0; i
        switch(commStatus)
        {
            case 1:    // 谱图采集状态
            {
                if(n != 2)
                {
                    if(s==("5555550001FC"))
                    {
                        Edit1->Text = "已经停止数据采集!";

                        TStringList *MyList = new TStringList;

                        for(int i=0; i                        {
                            MyList->Add(IntToStr(data[i])) ;
                        }

                        MyList->SaveToFile(sSampleFile);
                        Label1->Caption = "0";                        

                        delete MyList;
                       
                        Button4->Enabled = true;
                        Button5->Enabled = false;
                        dataCount1 = 0;
//                        fclose(datafile);
                        commStatus = 0;
                        return;
                    }
                }
                else
                {
                    int tmpY;
                    double X,Y;
                    data[dataCount1] = Buf[0]*256 + Buf[1];
//                    fprintf(datafile, "%d\n",tmpY);
//                    X = RoundTo(0.125*dataCount1, -3);
//                    Y = RoundTo(2500.0*tmpY/65535.0, -2);
//                    SampleSeries->AddXY(dataCount1, tmpY);

                    dataCount1++;
                    Label1->Caption = dataCount1;
                   ……………………


这个问题一直没解决,对我们试验结果很影响,Victor站长,您有什么好的办法没有来解决这个问题,您能帮帮我吗?真的很着急……非常感谢!!期待您的回复。

--------------------next---------------------
由于 Windows 的多任务处理,对数据接收影响很大,通过修改进程和线程的优先级,效果能好很多,但是还不理想

发送的数据在接收端,由于接收数据的延误,数据包内的两个字节之间可能会时间拉长,有的甚至会超过100ms
这样就会缩短这个数据包和下一个数据包之间的间隔,会把两个数据包之间的间隔缩短到 20ms

如果没有很大的数据包,都在 8 个字节以内,可以把 PackageInterval 设小一点,在 15 左右,几乎没有错误
如果有很大的数据包,可能会在数据包中间断开


为了提高你的 .exe 文件的进程的优先级,在程序最开始执行

SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS); //当前进程设为最高优先级, 好像作用不明显



为了提高控件线程的优先级,在串口控件里面,修改了下面两处,有一定的效果:

// TComm32.cpp 的函数 void __fastcall TComm32::Open(void) 里面,修改这句:

if(!ecErrCode)
 {
   SetThreadPriority((HANDLE)_ReadThreadId,THREAD_PRIORITY_TIME_CRITICAL); //原来是 THREAD_PRIORITY_HIGHEST
   //SetThreadPriority((HANDLE)_WriteThreadId,THREAD_PRIORITY_HIGHEST);

   ……

//TCommPkg.cpp 的函数 __fastcall TCommPackage::TCommPackage(TComm32 *lpComm)

  ……

  _hTimerEvent = CreateEvent(NULL, false, false, NULL); //Create Auto-Reset Event
  _hTimerThreadId = _beginthread(_fnTimerThread, 4096, this);
  SetThreadPriority((HANDLE)_hTimerThreadId,THREAD_PRIORITY_HIGHEST); //新增这句提高线程优先级

  ……



--------------------next---------------------
Victor站长,十分感激您的回复和帮助,我最近在重新调整我的程序。

有几个问题想请教您:

1) 您说的更改TComm32.cpp和TCommPkg.cpp,来提高控件线程的优先级,这些修改完毕后,是不是得重新编译生成bpl文件,来更换原来安装的bpl包,您能否稍微再详细点,见笑了……

2) 由于普通命令都是十几个字节长,我在命令状态都采用UsePackage=true;当开始采集时,我就采用UsePackage=false,在CommNotify里处理接收数据,这些数据之间间隔是125毫秒,长度为2个字节。不知道这个和您说的将PackageInterval设置为15ms相比,哪种更好呢?CommNotiy情况下默认的间隔是多少呢?

3) 还有个编程上的问题想请教您:
    我接收这些数据时,需要将其在Chart控件的曲线、Edit控件里显示出来,并追加到数据文件中去,这样我把这些动作都放到Comm控件的接收事件里去,对数据的接收会不会有影响?如果有影响的话,该如何处理呢?望站长指点,多谢!

4) 如果在CommNotify的事件里接受到了2个数据(两个数据发送的间隔是125ms,但是此时Windows系统非常繁忙),即4个字节的数据,这种情况会不会有呢?

谢谢,祝万事如意,身体健康!

--------------------next---------------------
在接收数据的过程中,如果要有显示之类比较耗费时间的工作,不要放在控件的OnPackage事件中,可以在其中发送消息到主线程中,所有的数据处理和显示都在主线程中进行,例如:
void __fastcall TForm1::YbCommDevice1Package(TObject *Sender,int NotifyType)
     if(NotifyType & EV_RXCHAR) //如果 NotifyType 的 RXCHAR 位为 1
     {
          PostMessage(Handle, WM_COMMPKG, 0, 0); //向窗口发消息
     }

重载主线程的WndProc:
void __fastcall TForm1::WndProc(Messages::TMessage &Message)
{
   ......
   ......
   if(Message.Msg == WM_COMMPKG)
   {
       //接收数据作相关的处理
       while((nBytes=YbCommDevice1->ReadPackage(Buffer,BufSize))>0)
       {
       ......
       ......
       ......
       }
       //其他处理
   }
  TForm::WndProc(Message); //这句不能写错, 否则程序无法运行
}

我的程序和您的有类似的地方,需要长时间的接收数据,并显示到TChart控件上,我就是采用这样的方法,使用起来比较稳定。不过这可能和我在运行程序时没有打开太多的应用程序有关。你可以试试。
PS:是不是有点班门弄斧的意思。因为从版主这里得到了很多帮助,刚好您的程序和我的有类似的地方,不要笑我哦。



--------------------next---------------------

阅读(1433) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~