怎样把vc6的MSComm控件接受的数据实时的显示在编辑框,并把数据实时存入txt文件中

wilia 2013-11-17 04:03:13
我在做一个基于VC6的MSComm控件的电机上位机控制,数据帧格式采用9600bps,8位数据位,奇校验,1位停止位,下位机每次发送16位数据,(16位是分两次发送吗??),高两位代表指令,后14位代表实际的数据,例如“00”代表的是发送的是转速数据,后14位才是转速的实际值。我现在要用vc++6.0的MSComm控件接受数据,把每次接受的数据要正确的显示在编辑框,并且要把每次的数据实时存入到不同的txt文件中。下面是我写的部分的代码,由于下位机还没有好。不知道写正确了没有,我是新手,望各位指导,共同学习。

CFile m_file(_T("data.txt"),CFile::modeCreate|CFile::modeWrite);//创建一个data.txt文件??
CFile m_file2(_T("data2.txt"),CFile::modeCreate|CFile::modeWrite);//创建一个data2.txt文件??
int savespeed,savecurrent;//savespeed是存入data.txt的全局变量,savecurrent是存入data2.txt的全局变量
//下面是MSComm控件的消息响应函数
void CreceiveDlg::OnOnCommMscomm()
{
VARIANT variant_in;
COleSafeArray safearray_in;
short m_data,m_flag;
long k,len,l_COM;
BYTE r_data[1024];//设置BYTE数组
CString temp, strtemp;
if(m_ctrlComm.GetCommEvent()==2)
{
variant_in=m_ctrlComm.GetInput();//读缓冲区数据,设置一个字符触发OnComm事件
safearray_in=variant_in;//类型转换
len=safearray_in.GetOneDimSize();//得到有效数据长度??
for(k=0;k<len;k++)
safearray_in.GetElement(&k,r_data+k);//转换成BYTE型数组,8-bit
l_COM=len;//一次从缓冲区接受的数据长度??
}
//下面是把16位数据整合为一个有效的数据,各位大神,帮看看,不知道对不对?
//下面这个if语句应该放在上面的if语句内部还是就是放在外部??也模糊
if(l_COM==2)
{
m_data=(r_data[0]<<8)+r_data[1];//把接受的原始16位赋给一个整数??
}
//下面得到高两位的控制指令
m_flag=(m_data&0xc000)>>14;//得到高两位指令,不知道对不对??
switch(m_flag)
{
case 0:
{
CString str_speed;
short speed;
speed=m_data<<2;
speed=m_data>>2;//右移两位,左移两位把高两位置“00”得到后14位
//下面把该次接受的实时数据存入data.txt文件,不知道对不对??
savespeed=speed;//把要存的值赋给全局变量savespeed,savespeed是要存入txt的变量
savespeed+=" ";//隔开两个位置
savespeed+="\r\n";//换行
m_file.Write(savespeed,savespeed.GetLength());//写到文件中
savespeed="";//清空,以便下次继续写入
//以下是把该次转速赋给编辑框关联的变量?
str_speed.Format("d%",speed);//把speed以字符形式给临时变量
m_speed=str_speed;//m_speed位编辑框关联的变量
break;
}
case 1:
{
CString str_current;
short current;
current=m_data<<2;
current=m_data>>2;//右移两位,左移两位把高两位置“00”
//下面把该次接受的实时数据存入data2.txt文件,不知道对不对??
savecurrent=current;//把要存的值赋给全局变量savecurrent,savecurrent是要存入txt的变量
savecurrent+=" ";//隔开两个位置
savecurrent+="\r\n";//换行
m_file2.Write(savecurrent,savecurrent.GetLength());//写到文件中
savecurrent="";//清空,以便下次继续写入
//以下是把该次电流赋给编辑框关联的变量?
str_curreent.Format("d%",current);//把current以字符形式给临时变量
m_current=str_current;//m_current位编辑框关联的变量
break;
}
case 2:
{
//待写
}
}
//更新编辑框
UpdataData(False);

}
...全文
264 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
xiaohuh421 2013-11-18
  • 打赏
  • 举报
回复
m_flag=(m_data&0xc000)>>14;//得到高两位指令,不知道对不对?? 这里最好是先位移, 再取位. m_flag=(m_data>>14)&0xC000; 避免符号位产生问题. 如果下位机程序没有写好, 可以使用回环的串口线来自己测试. 写一个模拟下位机的程序. 或者使用虚拟机模拟串口都可以.
schlafenhamster 2013-11-18
  • 打赏
  • 举报
回复
"由物理层去实现" 硬件只 对 一个 字节 进行 奇偶 校验。 软件是对 所有 字节 校验。 MODBUS 有2种 格式, ASCII 或 RTU。 RTU 占 字节 少, 但 发送 时 有 时间 限制,(2个 字节 间 ,间隔时间 《 3.5 T) 仔细看看 协议。
wilia 2013-11-18
  • 打赏
  • 举报
回复
引用 9 楼 shen_wei 的回复:
以十六进制发送。。。
那我从缓冲区接受的数据就是十六进制吗?那我向下位机发送数据可以直接写成如下的代码吗?? void CMctrDlg::Onfasong()//发送转速设定数据 { // TODO: Add your control notification handler code here short send_down,send_up,send_given; UpdataData(True);//默认的先发高位 send_down=m_down<<2;//把编辑框关联的变量m_down左移两位,再右移两位把高两位置“00” send_down=m_down>>2; send_down=send_down&0x3fff; m_ctrlComm.SetOutput(COleVariant(send_down)); //Sleep(100);//延时100ms send_up=m_up<<2;//看看反了没有!! send_up=m_up>>2; send_up=send_up|0x4000; m_ctrlComm.SetOutput(COleVariant(send_up)); //Sleep(100);//延时100ms send_given=m_given<<2; send_given=m_given>>2; send_given=send_given|0x4000; m_ctrlComm.SetOutput(COleVariant(send_given)); }
shen_wei 2013-11-18
  • 打赏
  • 举报
回复
以十六进制发送。。。
wilia 2013-11-18
  • 打赏
  • 举报
回复
引用 6 楼 shen_wei 的回复:
这个只管发送数据和接受数据就可以了! 发:0xFF,0xFF 接受:0xFF,0xFF
我看Modbus通讯协议它是以RTU码传送消息的,那我从缓冲区取得数据之后,若果想把它得到有效的十进制数据进行显示和保存,那是不是我还得把RTU码转换成十进制数或者二进制??
wilia 2013-11-18
  • 打赏
  • 举报
回复
引用 5 楼 hdg3707 的回复:
必须在程序里解析协议及校验,虽然串口的硬件有奇偶校验,但一般不用,都是自己加的校验。硬件不会知道你的协议是什么
我看Modbus通讯协议它是以RTU码传送消息的,那我再从缓冲区取得数据之后,若果想把它得到有效的十进制数据进行显示和保存,那是不是我还得把RTU码转换成十进制数或者二进制??
shen_wei 2013-11-18
  • 打赏
  • 举报
回复
这个只管发送数据和接受数据就可以了! 发:0xFF,0xFF 接受:0xFF,0xFF
hdg3707 2013-11-18
  • 打赏
  • 举报
回复
必须在程序里解析协议及校验,虽然串口的硬件有奇偶校验,但一般不用,都是自己加的校验。硬件不会知道你的协议是什么
schlafenhamster 2013-11-18
  • 打赏
  • 举报
回复
那个 T 表示 发送一个 字节的 时间, 与 波特率 有关。 按协议 不会 只有 2字节。 先要 读地址。。。。 http://bbs.csdn.net/topics/360101535 帖子里有 代码参考
wilia 2013-11-18
  • 打赏
  • 举报
回复
引用 11 楼 schlafenhamster 的回复:
"由物理层去实现"
硬件只 对 一个 字节 进行 奇偶 校验。
软件是对 所有 字节 校验。
MODBUS 有2种 格式, ASCII 或 RTU。
RTU 占 字节 少, 但 发送 时 有 时间 限制,(2个 字节 间 ,间隔时间 《 3.5 T)
仔细看看 协议。

上面的RTU模式,那下位机每次发送16位数据,16位能够一次发送过来吗,也就是当图片中的N=2表示一次发送了16位吗,那我读取缓冲区一次怎么知道就读取了16位,要是从缓冲区接受的数据大于16位,那不是接受不到正确的数据?
wilia 2013-11-18
  • 打赏
  • 举报
回复
引用 11 楼 schlafenhamster 的回复:
"由物理层去实现" 硬件只 对 一个 字节 进行 奇偶 校验。 软件是对 所有 字节 校验。 MODBUS 有2种 格式, ASCII 或 RTU。 RTU 占 字节 少, 但 发送 时 有 时间 限制,(2个 字节 间 ,间隔时间 《 3.5 T) 仔细看看 协议。
正在看Modbus协议,我想用RTU格式,那我在接受数据时,要对从缓冲区接受的数据进行解码吗,还是由下面自己解码?这个T是指什么,是指计算机时钟周期吗,我在MSComm控件通信里面也看见这个T?
wilia 2013-11-18
  • 打赏
  • 举报
回复
引用 12 楼 xiaohuh421 的回复:
m_flag=(m_data&0xc000)>>14;//得到高两位指令,不知道对不对?? 这里最好是先位移, 再取位. m_flag=(m_data>>14)&0xC000; 避免符号位产生问题. 如果下位机程序没有写好, 可以使用回环的串口线来自己测试. 写一个模拟下位机的程序. 或者使用虚拟机模拟串口都可以.
好了,又学了一招。
wilia 2013-11-17
  • 打赏
  • 举报
回复
引用 2 楼 hdg3707 的回复:
基本没问题,你程序里是按先发高位后发低位处理处理的。但这需要单片机发送不能太快,不然,你可能会收到超过2个字节以上的数据,如果超过两上2个字节,就需要两两判断(前提是接收到正确的数据)。最好定信协议,报文头+长度+命令号+数据+校验,这样就算收到多个报文也可以进行正确解析,否则就会解析错
那我在程序里面需要对通信协议的说明吗,比如,每次接受数据都要去查看报文头,进行奇偶校验吗;还是由物理层去实现?我的程序现在不好调试,因为下位机是别人在做,我得和他具体规定了才能进一步确定。其实,我一直被这个通信协议搞得头疼,要是我按“报文头+长度+命令号+数据+校验”这个协议,上面的程序得改动很大吗??
wilia 2013-11-17
  • 打赏
  • 举报
回复
引用 1 楼 schlafenhamster 的回复:
“每次发送16位数据” 是 2个 字节(16位)还是 16 字节? 如果是 2个字节,要分 高低 字节 的 顺序。 MSComm 要设置为 BINARY 模式。 你这个 协议,很难 找到消息的开始,通常协议是: 开始标记 如 (0x68 ’h‘); 长度,数据,检验和。 可以看看 MODBUS 协议
太谢谢了,给的题目说是每次发送16位(2个字节),我的MSComm初始化为二进制模式,初步给定也就是用Modbus协议,那要是用这个协议,我在程序里面要想接受到正确的数据还的要判断标记,进行奇偶校验吗?由于下位机是另一个同学在做,还的和他协调!!
hdg3707 2013-11-17
  • 打赏
  • 举报
回复
基本没问题,你程序里是按先发高位后发低位处理处理的。但这需要单片机发送不能太快,不然,你可能会收到超过2个字节以上的数据,如果超过两上2个字节,就需要两两判断(前提是接收到正确的数据)。最好定信协议,报文头+长度+命令号+数据+校验,这样就算收到多个报文也可以进行正确解析,否则就会解析错
schlafenhamster 2013-11-17
  • 打赏
  • 举报
回复
“每次发送16位数据” 是 2个 字节(16位)还是 16 字节? 如果是 2个字节,要分 高低 字节 的 顺序。 MSComm 要设置为 BINARY 模式。 你这个 协议,很难 找到消息的开始,通常协议是: 开始标记 如 (0x68 ’h‘); 长度,数据,检验和。 可以看看 MODBUS 协议

64,648

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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