vc++无法实现串口通信的问题

miketry0313 2014-01-05 04:27:08
大家好,我正在用VC++写一个与机器人的串口通信程序, 通信使用的是XBee transmitter。现在的问题是,当我发送命令要求机器人返回信息以后,我收不到机器人发给我的任何信息。这个问题的一个难点就是,我事先不知道机器人会发送给我多大的数据,所以代码中buffer的size不知道有没有定义对。另外运行代码以后,error返回的结果一直是1. 同样的硬件,我用MATLAB程序能够实现串口通信,所以很大可能就是代码的问题。代码已附上,希望大家能帮助我。
#include "StdAfx.h"
#include <iostream>
#define WIN32_LEAN_AND_MEAN //for GetCommState command
#include "Windows.h"
#include <WinBase.h>

using namespace std;

int main(){

char init[]="";

HANDLE serialHandle;

// Open serial port
serialHandle = CreateFile("\\\\.\\COM8", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

// Do some basic settings
DCB serialParams;
DWORD read, written;
serialParams.DCBlength = sizeof(serialParams);

if((GetCommState(serialHandle, &serialParams)==0))
{
printf("Get configuration port has a problem.");
return FALSE;
}

GetCommState(serialHandle, &serialParams);
serialParams.BaudRate = CBR_57600;
serialParams.ByteSize = 8;
serialParams.StopBits = ONESTOPBIT;
serialParams.Parity = NOPARITY;

//set flow control="hardware"
serialParams.fOutX=false;
serialParams.fInX=false;
serialParams.fOutxCtsFlow=true;
serialParams.fOutxDsrFlow=true;
serialParams.fDsrSensitivity=true;
serialParams.fRtsControl=RTS_CONTROL_HANDSHAKE;
serialParams.fDtrControl=DTR_CONTROL_HANDSHAKE;

if (!SetCommState(serialHandle, &serialParams))
{
printf("Set configuration port has a problem.");
return FALSE;

}


GetCommState(serialHandle, &serialParams);

// Set timeouts
COMMTIMEOUTS timeout = { 0 };
timeout.ReadIntervalTimeout = 3;
timeout.ReadTotalTimeoutConstant = 3;
timeout.ReadTotalTimeoutMultiplier = 3;
timeout.WriteTotalTimeoutConstant = 3;
timeout.WriteTotalTimeoutMultiplier = 3;

SetCommTimeouts(serialHandle, &timeout);

if (!SetCommTimeouts(serialHandle, &timeout))
{
printf("Set configuration port has a problem.");
return FALSE;

}



//write packet to poll data from robot
WriteFile(serialHandle,">*>p4",sizeof(">*>p4"),&written,NULL);


//check whether the data can be received

char buffer[257];

if (!ReadFile(serialHandle,buffer,sizeof(buffer),&read,NULL))
{
printf("Reading data to port has a problem.");
return FALSE;
}
int t;
bool error;
DWORD numberOfBytesRead=0;
DWORD err = GetLastError();
for (int jj=0;jj<10;jj++)
{
error=ReadFile(serialHandle,LPVOID(buffer),255,&numberOfBytesRead,NULL);
buffer[numberOfBytesRead]=0;
cout<<buffer<<endl;
cout<<error;
}





CloseHandle(serialHandle);
return 0;
}
...全文
195 点赞 收藏 24
写回复
24 条回复
baichi4141 2014年01月10日
引用 19 楼 miketry0313 的回复:
还麻烦大神指点一下如何加边界检查,我刚才百度搜了一下,关于边界检查,啥都没搜到。 这个循环运行了挺久的,buffer只读到一个数据,因为read返回为0的原因,buffer的指针jj一直不变。但有点奇怪的是,每个循环buffer读的都是同一个数据。
jj++;
if(jj>=103)
break;
在你的代码里我没看见buffer被使用 你是怎么检查read都是0的?如果1000次里有999次都是0,你能看见剩下那个1不?
回复 点赞
miketry0313 2014年01月10日
引用 21 楼 French_fries 的回复:
你确定下面的设备用的是com8么?还有串口参数必须和下位机设备一致才行,否则通讯会有误的,可能会出现读不到数据的情况
引用 21 楼 French_fries 的回复:
你确定下面的设备用的是com8么?还有串口参数必须和下位机设备一致才行,否则通讯会有误的,可能会出现读不到数据的情况
谢谢你的回复,其他的我都挺确定的,就是把flow control设置成hardware那一块我不确定写没写对。现在我已经能收到数据了,但问题是ReadFile (serialHandle,&data[jj],1,&read, NULL);给我返回的read值一直都是0
回复 点赞
Burcy Wen 2014年01月10日
你确定下面的设备用的是com8么?还有串口参数必须和下位机设备一致才行,否则通讯会有误的,可能会出现读不到数据的情况
回复 点赞
Burcy Wen 2014年01月10日
运行这个代码,没发现问题,读写都正常,应该不是这段代码的问题吧。
回复 点赞
miketry0313 2014年01月10日
引用 18 楼 baichi4141 的回复:
[quote=引用 17 楼 miketry0313 的回复:] [quote=引用 16 楼 baichi4141 的回复:] [quote=引用 15 楼 miketry0313 的回复:] [quote=引用 3 楼 baichi4141 的回复:] 串口读数据每次只读一个字节,自己组合 二进制数据不该使用strlen
现在我用for循环可以读到一些数据了,但是还有一个问题。我用了ReadFile(serialHandle,LPVOID(buffer),1,&numberOfBytesRead,NULL); 以后,每个循环cout<<numberOfBytesRead的结果都是0. 所以这样的话,完全不能应用while循环,每次循环一次就跳出了。能不能麻烦你继续帮助我?[/quote] 串口每秒钟返回10个字节,你每秒钟读取1000次,你猜会有多少次读到0个字节? 完全不能应用while循环的原因在于你的逻辑不对,为啥要跳出?读到0个字节继续循环,读到1个字节就保存这1个字节后继续循环,就这么简单[/quote] 大神,我按照你的意思写了下,请问你觉得这样对么?
char buffer[1];
char data[103];
int t=0;
int jj=0;

do {
	
	ReadFile (serialHandle,&data[jj],1,&read, NULL);
	cout<<read;
	if (read!=0) 
	{
	  	jj++;
	    
	}
	t++;
 } while (t<10000); 
但是结果,我得到了一万个0. 我觉得奇怪的是,我实在串口能得到数据,为什么read返回的值总是0.能不能请你继续指点我?[/quote] 没加边界检查,data中只能存放103个数据,如果这段时间接收到了超过103个数据,那么就越界了 这个循环运行多长时间?这段时间内串口有没有收到数据?如果串口在这段循环运行的时间内压根没收到数据,你当然什么也读不出来[/quote] 还麻烦大神指点一下如何加边界检查,我刚才百度搜了一下,关于边界检查,啥都没搜到。 这个循环运行了挺久的,buffer只读到一个数据,因为read返回为0的原因,buffer的指针jj一直不变。但有点奇怪的是,每个循环buffer读的都是同一个数据。
回复 点赞
baichi4141 2014年01月10日
引用 17 楼 miketry0313 的回复:
[quote=引用 16 楼 baichi4141 的回复:] [quote=引用 15 楼 miketry0313 的回复:] [quote=引用 3 楼 baichi4141 的回复:] 串口读数据每次只读一个字节,自己组合 二进制数据不该使用strlen
现在我用for循环可以读到一些数据了,但是还有一个问题。我用了ReadFile(serialHandle,LPVOID(buffer),1,&numberOfBytesRead,NULL); 以后,每个循环cout<<numberOfBytesRead的结果都是0. 所以这样的话,完全不能应用while循环,每次循环一次就跳出了。能不能麻烦你继续帮助我?[/quote] 串口每秒钟返回10个字节,你每秒钟读取1000次,你猜会有多少次读到0个字节? 完全不能应用while循环的原因在于你的逻辑不对,为啥要跳出?读到0个字节继续循环,读到1个字节就保存这1个字节后继续循环,就这么简单[/quote] 大神,我按照你的意思写了下,请问你觉得这样对么?
char buffer[1];
char data[103];
int t=0;
int jj=0;

do {
	
	ReadFile (serialHandle,&data[jj],1,&read, NULL);
	cout<<read;
	if (read!=0) 
	{
	  	jj++;
	    
	}
	t++;
 } while (t<10000); 
但是结果,我得到了一万个0. 我觉得奇怪的是,我实在串口能得到数据,为什么read返回的值总是0.能不能请你继续指点我?[/quote] 没加边界检查,data中只能存放103个数据,如果这段时间接收到了超过103个数据,那么就越界了 这个循环运行多长时间?这段时间内串口有没有收到数据?如果串口在这段循环运行的时间内压根没收到数据,你当然什么也读不出来
回复 点赞
miketry0313 2014年01月10日
引用 16 楼 baichi4141 的回复:
[quote=引用 15 楼 miketry0313 的回复:] [quote=引用 3 楼 baichi4141 的回复:] 串口读数据每次只读一个字节,自己组合 二进制数据不该使用strlen
现在我用for循环可以读到一些数据了,但是还有一个问题。我用了ReadFile(serialHandle,LPVOID(buffer),1,&numberOfBytesRead,NULL); 以后,每个循环cout<<numberOfBytesRead的结果都是0. 所以这样的话,完全不能应用while循环,每次循环一次就跳出了。能不能麻烦你继续帮助我?[/quote] 串口每秒钟返回10个字节,你每秒钟读取1000次,你猜会有多少次读到0个字节? 完全不能应用while循环的原因在于你的逻辑不对,为啥要跳出?读到0个字节继续循环,读到1个字节就保存这1个字节后继续循环,就这么简单[/quote] 大神,我按照你的意思写了下,请问你觉得这样对么?
char buffer[1];
char data[103];
int t=0;
int jj=0;

do {
	
	ReadFile (serialHandle,&data[jj],1,&read, NULL);
	cout<<read;
	if (read!=0) 
	{
	  	jj++;
	    
	}
	t++;
 } while (t<10000); 
但是结果,我得到了一万个0. 我觉得奇怪的是,我实在串口能得到数据,为什么read返回的值总是0.能不能请你继续指点我?
回复 点赞
Burcy Wen 2014年01月10日
ReadFile() Return Value The ReadFile function returns when one of the following conditions occur: 1.A write operation completes on the write end of the pipe. 2.The number of bytes requested is read. 3.An error occurs. If the function succeeds, the return value is nonzero. If the function fails, the return value is zero (0). To get extended error information, call GetLastError. If the return value is nonzero and the number of bytes read is zero (0), the file pointer is beyond the current end of the file at the time of the read operation. However, if the file is opened with FILE_FLAG_OVERLAPPED and lpOverlapped is not NULL, the return value is zero (0) and GetLastError returns ERROR_HANDLE_EOF when the file pointer goes beyond the current end of file. 你看看是不是有不满足的导致返回error了
回复 点赞
baichi4141 2014年01月08日
引用 15 楼 miketry0313 的回复:
[quote=引用 3 楼 baichi4141 的回复:] 串口读数据每次只读一个字节,自己组合 二进制数据不该使用strlen
现在我用for循环可以读到一些数据了,但是还有一个问题。我用了ReadFile(serialHandle,LPVOID(buffer),1,&numberOfBytesRead,NULL); 以后,每个循环cout<<numberOfBytesRead的结果都是0. 所以这样的话,完全不能应用while循环,每次循环一次就跳出了。能不能麻烦你继续帮助我?[/quote] 串口每秒钟返回10个字节,你每秒钟读取1000次,你猜会有多少次读到0个字节? 完全不能应用while循环的原因在于你的逻辑不对,为啥要跳出?读到0个字节继续循环,读到1个字节就保存这1个字节后继续循环,就这么简单
回复 点赞
miketry0313 2014年01月08日
引用 3 楼 baichi4141 的回复:
串口读数据每次只读一个字节,自己组合 二进制数据不该使用strlen
现在我用for循环可以读到一些数据了,但是还有一个问题。我用了ReadFile(serialHandle,LPVOID(buffer),1,&numberOfBytesRead,NULL); 以后,每个循环cout<<numberOfBytesRead的结果都是0. 所以这样的话,完全不能应用while循环,每次循环一次就跳出了。能不能麻烦你继续帮助我?
回复 点赞
miketry0313 2014年01月08日
引用 10 楼 xiaohuh421 的回复:
[quote=引用 6 楼 miketry0313 的回复:] 你的意思是,ReadFile(serialHandle,LPVOID(buffer),255,&numberOfBytesRead,NULL);我这个语句是正确的,但是每次只会往buffer里面塞一个数据是么?
是每次只往buffer塞一个字节的数据 ReadFile(serialHandle,LPVOID(buffer),1,&numberOfBytesRead,NULL); //注意第二个参数. 这样每次读取后, 如果成功, 就只读取一个字符, 然后循环读取, 直到读取完成. 注意你的程序是WriteFile后马上去ReadFile, 你在确定对方能有这么快的返回速度吗? 你的timeout时间是不是太短了点. 串口设备是低速设备.[/quote] 现在我用for循环可以读到一些数据了,但是还有一个问题。我用了ReadFile(serialHandle,LPVOID(buffer),1,&numberOfBytesRead,NULL); 以后,每个循环cout<<numberOfBytesRead的结果都是0. 所以这样的话,完全不能应用while循环,每次循环一次就跳出了。能不能麻烦你继续帮助我?
回复 点赞
miketry0313 2014年01月08日
引用 12 楼 zhao4zhong1 的回复:
推荐使用portmon软件辅助调试串口通信程序。
谢谢你的回复,但portmon好像不能用于win7 64bit系统啊,我一connect local就出现error2
回复 点赞
赵4老师 2014年01月07日
推荐使用portmon软件辅助调试串口通信程序。
回复 点赞
xiaohuh421 2014年01月06日
要不纠结内存分配多少, 串口是字符设备, 你完全可以每次读取一个字符. 循环读取, 直到读取不到为止.
回复 点赞
hushoubo 2014年01月06日
定义一个大的缓冲去接收,PC端不要吝啬那么点儿内存
回复 点赞
baichi4141 2014年01月06日
串口读数据每次只读一个字节,自己组合 二进制数据不该使用strlen
回复 点赞
hushoubo 2014年01月06日
引用 9 楼 Binzo 的回复:
while(1){ //recieve the meaage; } 不然,程序都退出了,你到哪儿去接收消息。
正解,只要保证发出的指令正确,那就循环接收,不会收不到的
回复 点赞
xiaohuh421 2014年01月06日
引用 6 楼 miketry0313 的回复:
你的意思是,ReadFile(serialHandle,LPVOID(buffer),255,&numberOfBytesRead,NULL);我这个语句是正确的,但是每次只会往buffer里面塞一个数据是么?
是每次只往buffer塞一个字节的数据 ReadFile(serialHandle,LPVOID(buffer),1,&numberOfBytesRead,NULL); //注意第二个参数. 这样每次读取后, 如果成功, 就只读取一个字符, 然后循环读取, 直到读取完成. 注意你的程序是WriteFile后马上去ReadFile, 你在确定对方能有这么快的返回速度吗? 你的timeout时间是不是太短了点. 串口设备是低速设备.
回复 点赞
miketry0313 2014年01月06日
引用 1 楼 ALNG 的回复:
//write packet to poll data from robot WriteFile(serialHandle,">*>p4",sizeof(">*>p4"),&written,NULL); 这行是错的。sizeof是求一个类型的size, 如果你给的是一个char [], 比如稍后的ReadFile(serialHandle,buffer,sizeof(buffer),&read,NULL,sizeof就正确。这里你需要用是strlen //write packet to poll data from robot WriteFile(serialHandle,">*>p4",strlen(">*>p4"),&written,NULL); 如果你是在32的平台上,sizeof(const char *)为4,会少些一个4, 如果是在64为平台上sizeof(const char *)为8,后面会带上3个字节的垃圾。 这肯定是个问题,不过是不是唯一的问题我就不确定了。
谢谢你的回复,sizeof输出为6,strlen输出为5.但是我改成strlen以后,还是收不到任何数据。
回复 点赞
Binzo 2014年01月06日
while(1){ //recieve the meaage; } 不然,程序都退出了,你到哪儿去接收消息。
回复 点赞
发动态
发帖子
C++ 语言
创建于2007-09-28

3.1w+

社区成员

24.8w+

社区内容

C++ 语言相关问题讨论,技术干货分享
社区公告
暂无公告