MFC串口通讯问题

志雄阿三 2014-12-05 05:02:31
各位大神好!我的主界面上有一个Mscomm串口控件,要用这个控件获取发来的数据。我发给接收方的是指令,我发一条,对方接收一条,返回数据后,我才能再发第二条。这些指令要不断的发,以获取接收方实时信息。(自己发自己接来测试功能)
我的方法是,设置一个定时器,希望在定时器中发送指令。但是由于必须接收到反馈信息之后我才能发送第二条指令,经过测试,我依次发送4条指令,每条指令间Sleep(250),串口接收数据时依然一次性接收到我发的4条指令,而不是一条一条接收。我对串口的消息响应机制还不是特别了解,请大神们帮帮忙!谢谢~

// 这里是串口响应函数,串口接收到消息后会调用它
void CRobotControlDlg::OnCommMscomm()
{
// TODO: 在此添加命令处理程序代码

VARIANT variant_inp;
COleSafeArray safearray_inp;
long len,k;
unsigned int data[2048]={0};
byte rxdata[2048]={0}; // 设置BYTE 数组
CString strtemp=NULL;
CString strReceive=NULL; // 该变量保存串口接收到的数据

if( m_MSComm.get_CommEvent()==2 ) // 值为2 表示接收缓冲区内有字符
{
variant_inp = m_MSComm.get_Input(); // 读缓冲区消息
safearray_inp = variant_inp; // 变量转换
len = safearray_inp.GetOneDimSize(); // 得到有效的数据长度

for(k=0;k<len;k++)
{
safearray_inp.GetElement(&k,rxdata+k);
}
for(k=0;k<len;k++) // 将数组转换为CString 型变量
{
strtemp.Format(_T("%c"),*(rxdata+k)); // “%c”将数据从unsigned char转成string;“%x”将数据转成16进制
strReceive += strtemp;
}
CString temp=_T("\r\n"); // 换行
strReceive += temp;

DataHandler(strReceive); // 抛给数据处理函数

}
}

// 以下是定时器函数中,向对方发送指令的部分
// 使用串口功能

CString strSend1,strSend2; // 指令1和指令2,对方接收到指令后会回复响应的内容。
strSend1 = "123456789<counts>";
strSend2 = "PFB";
if (m_MSComm.get_PortOpen())
{
m_MSComm.put_Output(COleVariant(strSend1)); //发送数据
Sleep(50);
}
if (m_MSComm.get_PortOpen())
{
m_MSComm.put_Output(COleVariant(strSend2)); //发送数据
Sleep(50);
}

...全文
308 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
志雄阿三 2014-12-11
  • 打赏
  • 举报
回复
结贴了,谢谢大家啦!
志雄阿三 2014-12-11
  • 打赏
  • 举报
回复
引用 7 楼 wxhxj0268 的回复:
事件与定时需要联合使用的,当执行完发送指令,立即打开应答定时器(时间你自己定),在定时范围内收到读事件,关闭定时器后直接读取数据进行处理。超过定时时间未收到数据,可能因为通信断开或客户机未收到指令,可重发指令或做相应处理。这是一个闭环的控制系统。
嗯,这个方法不错,定时器随用随开,也不会很占用资源。谢谢!
笨笨仔 2014-12-08
  • 打赏
  • 举报
回复
事件与定时需要联合使用的,当执行完发送指令,立即打开应答定时器(时间你自己定),在定时范围内收到读事件,关闭定时器后直接读取数据进行处理。超过定时时间未收到数据,可能因为通信断开或客户机未收到指令,可重发指令或做相应处理。这是一个闭环的控制系统。
worldy 2014-12-08
  • 打赏
  • 举报
回复
引用 5 楼 y330197352 的回复:
[quote=引用 2 楼 worldy 的回复:] 有几种方法 1.上位机发送完数据后,加入sleep(若干毫秒),然后读取下位机发回数据,然后返回;适合于下位机延时不长,数据交换长度不多的场合(工业控制大多是这样的类型),这种模式最好创建一个发送线程; 2.上位机发送数据后,使用OnCommMscomm事件中,接收,这种方法有个麻烦,必须有结束标志或者返回的数据长度确定,否则无法判断一个接收结束 3,使用定时器,可以使用一个数组保存发送数据,每次发送标记一个发送,发送后,如果接收数据完毕,则取消发送标记。定时器每次进入,检查是否有发送标记,如果有,则转入读数据状态,否则,发送数组中下一条数据,这种方法比较有效率,但逻辑有点麻烦
我试了一下您提出的方法3,已经通过定时器实现了。但是定时器会不会比较占资源呢?而且它精度不高。我想是不是可以把定时器开在线程里面?您有什么好方法吗?我用串口主要是读取电机当前脉冲数的,所以对他的实时性要求比较高,效率也希望能更高一些。[/quote] 定时精度不高,并不关键,主要是使用定时器实现串口收发驱动 一般上位机读取数据都会存在延时,很难读到真正的“当前”数据,但基本上能反应运行情况
志雄阿三 2014-12-08
  • 打赏
  • 举报
回复
引用 1 楼 allenemo 的回复:
建议你使用CxSerial http://www.cnblogs.com/EdmundDwyane/p/3174308.html
这个可以尝试一下,我还是新手,对串口还不是很了解,我先把MSCOMM搞懂再尝试下您的方法吧。
志雄阿三 2014-12-08
  • 打赏
  • 举报
回复
引用 2 楼 worldy 的回复:
有几种方法 1.上位机发送完数据后,加入sleep(若干毫秒),然后读取下位机发回数据,然后返回;适合于下位机延时不长,数据交换长度不多的场合(工业控制大多是这样的类型),这种模式最好创建一个发送线程; 2.上位机发送数据后,使用OnCommMscomm事件中,接收,这种方法有个麻烦,必须有结束标志或者返回的数据长度确定,否则无法判断一个接收结束 3,使用定时器,可以使用一个数组保存发送数据,每次发送标记一个发送,发送后,如果接收数据完毕,则取消发送标记。定时器每次进入,检查是否有发送标记,如果有,则转入读数据状态,否则,发送数组中下一条数据,这种方法比较有效率,但逻辑有点麻烦
我试了一下您提出的方法3,已经通过定时器实现了。但是定时器会不会比较占资源呢?而且它精度不高。我想是不是可以把定时器开在线程里面?您有什么好方法吗?我用串口主要是读取电机当前脉冲数的,所以对他的实时性要求比较高,效率也希望能更高一些。
志雄阿三 2014-12-08
  • 打赏
  • 举报
回复
引用 3 楼 wjm1990 的回复:
每次接收数据引发一次ONCOMM事件,你这样就一直卡在发送上,发送完才进行接收,你可以弄一个全局变量k,,将发送写到if( m_MSComm.get_CommEvent()==2 ) 里面 ,k++ 每个K发送一条
这样会不会太占资源了?万一串口出现什么问题一直都接收不到,那我什么都做不了了。我觉得可以试一下worldy的方法3
wjm1990 2014-12-06
  • 打赏
  • 举报
回复
每次接收数据引发一次ONCOMM事件,你这样就一直卡在发送上,发送完才进行接收,你可以弄一个全局变量k,,将发送写到if( m_MSComm.get_CommEvent()==2 ) 里面 ,k++ 每个K发送一条
worldy 2014-12-05
  • 打赏
  • 举报
回复
有几种方法 1.上位机发送完数据后,加入sleep(若干毫秒),然后读取下位机发回数据,然后返回;适合于下位机延时不长,数据交换长度不多的场合(工业控制大多是这样的类型),这种模式最好创建一个发送线程; 2.上位机发送数据后,使用OnCommMscomm事件中,接收,这种方法有个麻烦,必须有结束标志或者返回的数据长度确定,否则无法判断一个接收结束 3,使用定时器,可以使用一个数组保存发送数据,每次发送标记一个发送,发送后,如果接收数据完毕,则取消发送标记。定时器每次进入,检查是否有发送标记,如果有,则转入读数据状态,否则,发送数组中下一条数据,这种方法比较有效率,但逻辑有点麻烦
阿先森 2014-12-05
  • 打赏
  • 举报
回复

2,640

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 硬件/系统
社区管理员
  • 硬件/系统社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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