有关MSComm控件,接收数据的问题?

bearRON 2010-07-26 09:27:43
目的:将接收到的数据保存在一个数组中,通过判断此数组的某个字节,选择相应的操作。
调试中用了下面这段经典的接收程序,在与下位机通信过程中,用串口助手发送接收没有问题,但用这段程序会出现个别字节接收错误的情况,不知道是为何?
void CSCommTestDlg::OnComm()
{
// TODO: Add your control notification handler code here
VARIANT variant_inp;
COleSafeArray safearray_inp;
LONG len,k;
BYTE rxdata[2048];
CString strtemp;
if(m_ctrlComm.GetCommEvent()==2) //事件值为2表示接收缓冲区内有字符
{
variant_inp=m_ctrlComm.GetInput(); //读缓冲区
safearray_inp=variant_inp; //VARIANT型变量转换为ColeSafeArray型变量
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); //16进制显示
m_strRXData+=strtemp;
}
}
UpdateData(FALSE);
}

随后将触发事件这段程序修改了后,接收数据没错。但在调试中会弹出“Access violation ”的对话框,不知道为何?

if(m_ctrlComm.GetCommEvent()==2) //事件值为2表示接收缓冲区内有字符
{
variant_inp=m_ctrlComm.GetInput(); //读缓冲区
safearray_inp=variant_inp; //VARIANT型变量转换为ColeSafeArray型变量
len=safearray_inp.GetOneDimSize(); //得到有效数据长度
for(k=0;k<len;k++) //将数组转换为Cstring型变量
{
safearray_inp.GetElement(&k,rxdata+k);//转换为BYTE型数组
receivebuf[i] = rxdata[k]; //将数据保存在receivebuf[]中
i++;
}
}

又修改了一下程序,用指针实现数据的保存,不会弹出“Access violation ”,但是接收到的数据receivebuf[i]会与rxdata[k]错位,又不知道是为何?所以在此请求帮助,望高人指点!在此谢过。

定义了一个unsigned char *preceive
初始化了preceive = receivebuf;
if(m_ctrlComm.GetCommEvent()==2) //事件值为2表示接收缓冲区内有字符
{
variant_inp=m_ctrlComm.GetInput(); //读缓冲区
safearray_inp=variant_inp; //VARIANT型变量转换为ColeSafeArray型变量
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);
*preceive = bt;
preceive++;
m_strRXData+=strtemp;
}
}

...全文
294 点赞 收藏 14
写回复
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
TBEA_gh 2010-08-25
m_ctrlComm.GetInput()每次只接受8个字符的数据
回复
bearRON 2010-08-02
[Quote=引用 8 楼 maojian2011 的回复:]
现在你的问题是什么?
使用MSComm控件时,要注意控件属性的设置,尤其是OnComm事件的响应,通过SetRThreshold设置触发OnComm事件的具体条件,当接收缓冲区中达到RThreshold属性设置的字符门限,就触发OnComm事件(这个触发过程是操作系统帮助我们完成的),同时CommEvent属性值变为2,此事件将一直阻塞,直到通过GetInput读取InputLen属性设置的字符……
[/Quote]
InputLen这个属性一般初始化为 :m_ctrlComm.SetInputLen(0); //设置当前接收区数据长度为0
m_ctrlComm.SetRThreshold(1); 若接受一个字符就发生一次OnComm事件,那它读取多少个字符呢?0个字符还是读取所有接受到的字符。

回复
bearRON 2010-08-02
[Quote=引用 11 楼 maojian2011 的回复:]
定义的缓冲区未初始化?是报错吗?
[/Quote]
用串口助手断点调试的时候,看到rxdata里面有121个烫!
回复
ning0025 2010-08-01
121个“烫”,说是定义的缓冲区未初始化? 如何初始化哦?/////////////////这个是显示的问题吧
回复
maojian2011 2010-08-01
现在你的问题是什么?
使用MSComm控件时,要注意控件属性的设置,尤其是OnComm事件的响应,通过SetRThreshold设置触发OnComm事件的具体条件,当接收缓冲区中达到RThreshold属性设置的字符门限,就触发OnComm事件(这个触发过程是操作系统帮助我们完成的),同时CommEvent属性值变为2,此事件将一直阻塞,直到通过GetInput读取InputLen属性设置的字符长度后,OnComm事件返回,若返回后缓冲区中的数据还满足条件,就会继续触发OnComm事件,直到条件不满足为止。这就是通信的机制。
你的问题可能主要是对交换数据的处理上。
MSComm控件使用GetInput和SetOutput这两个函数来实现接收和发送数据,并且GetInput的返回类型和SetOutput的参数都是VARIANT数据类型,所以需要对数据做一些变换。
回复
maojian2011 2010-08-01
定义的缓冲区未初始化?是报错吗?
回复
maojian2011 2010-08-01
你将接收的数据显示时,出现了121个“烫”?
回复
bearRON 2010-07-31
在做单步调试的时候,发现rxdata[2048]里有121个“烫”,说是定义的缓冲区未初始化? 如何初始化哦?
回复
bearRON 2010-07-31
[Quote=引用 5 楼 peterdan 的回复:]
最好还是设置下触发OnComm事件的缓冲区字节数SetRThreshold(xx)
[/Quote]
在串口初始化里,已经设置了 m_ctrlComm.SetRThreshold(1);
回复
peterdan 2010-07-30
最好还是设置下触发OnComm事件的缓冲区字节数SetRThreshold(xx)
回复
melody1304 2010-07-28
m_ctrlComm.GetInput(); 前加sleep(100)试下
回复
旋风 2010-07-26
好像可以设置等缓冲区字符大于40个字节再触发OnComm事件
回复
bearRON 2010-07-26
[Quote=引用 1 楼 m_tornado 的回复:]
你的len是怎么得到的?循环中的那个
觉得会不会是字符串访问达不到的数据才产生的Acess Violation~好比20个字符,你在程序中要获取第21个字符~
[/Quote]
len 是由 len=safearray_inp.GetOneDimSize(); 语句得到的。
你说的问题确实可能会发生。不过在调试的过程中,我又发现,本来固定好接受40个字节的数据,却接受到了41个,而且它接受的是分段接受,先接33个,后接7个。
回复
m_tornado 2010-07-26
你的len是怎么得到的?循环中的那个
觉得会不会是字符串访问达不到的数据才产生的Acess Violation~好比20个字符,你在程序中要获取第21个字符~
回复
发动态
发帖子
硬件/系统
创建于2007-09-28

2590

社区成员

VC/MFC 硬件/系统
申请成为版主
社区公告
暂无公告