串口实时采集的问题,急急急!

qzf368 2009-01-06 06:25:15
导师让做一个串口实时采集的程序,用来验证FPGA中输出数据的正确性。FPGA发送数据的格式是每个数据包用十六进制的EB和AD作为同步头,后面再加上3个十六进制的数据,进行编码后,加上起始位、校验位、停止位一共55位;发送周期为10毫秒,用19200的波特率,我算了一下,不到3毫秒就发完了。
我一开始用CSerialPort类和MSCOMM控件的OnComm函数,每当检测到有连续的EB和AD时,我就记录下当前的时间,并记下后面3个字符然后进行处理,可是发现经常有漏采的情况,表现为前3个数据包之间都差10毫秒,而第四个就差了20毫秒,甚至于后面有的还差了30、40、60的,不知道这是什么原因?
后来我用再网上看到说事件驱动的发放容易漏数,查询的方法对实时采集更有效,我就用MSCOMM控件写了一个ReadComm函数,并用多媒体定时器定时周期1毫秒去运行ReadComm,只要有数据马上读进来进行处理,但是在WIN2K里进行实际数据采集时发现检测周期经常会变大到2、3、6毫秒,最大的一次甚至是隔了两百多毫秒才去读串口,结果一下读进很多数据,极度影响了数据采集的实时性;而且只要我一运行我的程序,WIN2K的CPU占用率就一直是100%,电脑也比较烂,最后我只能从任务管理器才能将程序关闭。因为本来数据是每10ms发过来一次的,我中间收到的数据的周期也应该是10ms。所以这样让我无法判断正确性。
请问这到底是什么问题呢?我应该怎么做才行呢?不胜感激啊!
...全文
128 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
ka_ng 2009-01-08
  • 打赏
  • 举报
回复
Windows下CPU调用进程每次执行时间是大概是50毫秒(当然,如果这个进程只需运行0.01毫秒,0.01毫秒后就会调用下一等待进程啦),你的定时器间隔太少了,系统无法达到那么高的精度(据说只有精度在秒以上定时器才准确)。
要想做那么精确,可以放弃大的操作系统,将程序做到单片机芯片里吧。
qzf368 2009-01-06
  • 打赏
  • 举报
回复
这用的是MSCOMM控件,参考的龚建伟的方法
qzf368 2009-01-06
  • 打赏
  • 举报
回复
void OnComm()
{
// TODO: Add your control notification handler code here
//VARIANT variant_inp;
COleVariant myVar;
COleSafeArray safearray_inp;
LONG len,k;
int n;
BYTE rxdata[2048]; //设置BYTE数组 An 8-bit integer that is not signed.
CString strtemp;
if(m_ctrlComm.GetCommEvent()==2) //事件值为2表示接收缓冲区内有字符
{ ////////以下你可以根据自己的通信协议加入处理代码
n=m_ctrlComm.GetInBufferCount();
if(n>0)
{
/*variant_inp=m_ctrlComm.GetInput(); //读缓冲区
safearray_inp=variant_inp; //VARIANT型变量转换为ColeSafeArray型变量*/
myVar.Attach(m_ctrlComm.GetInput());
safearray_inp=myVar; //解决WIN2K中内存增大的问题
len=safearray_inp.GetOneDimSize(); //得到有效数据长度
for(k=0;k<len;k++)
safearray_inp.GetElement(&k,rxdata+k);//转换为BYTE型数组
for(k=0;k<len;k++) //将数组转换为Cstring型变量
{
BYTE bt=*(char*)(rxdata+k); //字符型
strtemp.Format("%02X",bt); //将字符以十六进制的形式送入临时变量strtemp存放
m_strRXData+=strtemp; //加入接收编辑框对应字符串
m_cc[0]=m_cc[1];
m_cc[1]=m_cc[2];
m_cc[2]=m_cc[3];
m_cc[3]=m_cc[4];
m_cc[4]=(int)bt;
if((m_cc[0]==235)&&(m_cc[1]==173)) //可以保存完整的数(EBAD加三个字符),方便处理
OnDealAngle();//这个函数对m_cc数组进行处理,完了然后对m_cc全赋0
}
}
}
}
qzf368 2009-01-06
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 Mackz 的回复:]
不对啊,你这个是接收数据的吗?
[/Quote]
是啊,用的CSerialPort类,ch就是每次串口给的字符
菜牛 2009-01-06
  • 打赏
  • 举报
回复
不对啊,你这个是接收数据的吗?
菜牛 2009-01-06
  • 打赏
  • 举报
回复
你这个是消息方式,不是事件方式吧。
qzf368 2009-01-06
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 Mackz 的回复:]
等待事件的方式一般是不会丢数据的,可能还是你的代码有问题;所谓查询要(接近)实时,最好开个线程循环读取串口,中间也不要等多少时间了。
[/Quote]
这是我的OnComm函数
LONG CSCOMMDlg::OnCommunication(WPARAM ch, LPARAM port)
{
if (port <= 0 || port > 8)
return -1;
rxdatacount++; //接收的字节计数
CString strTemp;
//对每个数据都加上时间
//以下是对项目要求的操作
if(m_ctrlProject.GetCheck())
{
m_cc[0]=m_cc[1];
m_cc[1]=m_cc[2];
m_cc[2]=m_cc[3];
m_cc[3]=m_cc[4];
m_cc[4]=(int)ch;
if((m_cc[0]==235)&&(m_cc[1]==173)) //可以保存完整的数(EBAD加三个字符),方便处理
{
QueryPerformanceCounter(&litmp);
QPart2 = litmp.QuadPart;//获得中止值
dfMinus = (double)(QPart2-QPart1);
dfTim = dfMinus*1000 / dfFreq;// 获得对应的时间值,单位为毫秒
int t;
t=(int)dfTim;
QPart1 = QPart2;
CString strt;
strt.Format("%02d毫秒 ",t);
OnDealAngle();
}
}
}
菜牛 2009-01-06
  • 打赏
  • 举报
回复
等待事件的方式一般是不会丢数据的,可能还是你的代码有问题;所谓查询要(接近)实时,最好开个线程循环读取串口,中间也不要等多少时间了。
keven1868 2009-01-06
  • 打赏
  • 举报
回复
你的数据读取和处理大致需要多长时间?
你的数据发送端是每隔10ms一发,即使是查询式的数据接收也没必要非得1ms就去查询接收一次

lz可以这样试一下:
如果数据接收处理可以很快处理完,即可以忽略,那么,可以创建一个自动重置事件,通过多媒体时钟设置TIME_CALLBACK_EVENT_SET来得到事件通知,工作线程里等待此事件的信号状态,得到信号后即开始接收和处理操作,然后继续等待这个事件的信号状态
qzf368 2009-01-06
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 keven1868 的回复:]
多媒体时钟也不是那么准,可以专门开一个线程来做读取和处理操作,在线程中控制每隔多久做一次读取操作
[/Quote]
那要用什么定时器来做啊,多媒体定时器说是可以精确到1毫秒的,我想应该够用
qzf368 2009-01-06
  • 打赏
  • 举报
回复
在线等啊!急!!!
keven1868 2009-01-06
  • 打赏
  • 举报
回复
多媒体时钟也不是那么准,可以专门开一个线程来做读取和处理操作,在线程中控制每隔多久做一次读取操作
qzf368 2009-01-06
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 oyljerry 的回复:]
开一个线程,在里面用多媒体定时器来读...这样不会cpu太高
[/Quote]
然后呢?检测到数据然后用消息通知主线程读数据并处理?这样实时性可以保证吗?能说的具体些吗?
oyljerry 2009-01-06
  • 打赏
  • 举报
回复
开一个线程,在里面用多媒体定时器来读...这样不会cpu太高

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

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