您看一下我原来发的老帖子,也都是关于同一个问题,数据丢失的问题。
今天来此,还是这个,真的很苦恼。
我的流程如下:
串口控件设置如下:
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) |