谁能帮我解释一下下面的程序,C++Builder的USB串口通讯问题 ( 积分: 200 )

  • 主题发起人 主题发起人 xgbing
  • 开始时间 开始时间
X

xgbing

Unregistered / Unconfirmed
GUEST, unregistred user!
struct IOREQ{
unsigned int wValue;
unsigned int wIndex;
};
struct SEND{
unsigned long FLAG;
........//SEND 数据格式
}
#ifndef __USBDRIVERioctl__h_
#define __USBDRIVERioctl__h_

#define IOCTL_READ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_WRITE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
#endif    // 1.上面这些是什么意思
..............

if(hPipe != NULL)      //hPipe为得到的USB串口的句柄
{
bool Result,Result1 ;
unsigned long nBytes=0;
int leftcount=148;       //leftcount是要发送数据的位数

unsigned long *P_Data=&SEND_DATA.FLAG; //SEND_DATA已设置好

OVERLAPPED ov;
IOREQ Ioctrl;    // 2.这干什么用的
memset(&ov,0,sizeof(OVERLAPPED));   
ov.hEvent=CreateEvent(NULL,true,false,NULL);

if(ov.hEvent==NULL) //能否解释下下面的if...else....干什么用的
{ShowMessage("Error");
return 0;
}
else
{
do{
if(leftcount>=64) //每次至多发送8个字节
{
Ioctrl.wValue=1;
Ioctrl.wIndex=64;
ResetEvent(ov.hEvent);

Result = DeviceIoControl(hPipe,IOCTL_WRITE,&Ioctrl,8,NULL,0,&nBytes,&ov);
}
else
{
Ioctrl.wValue=2;
Ioctrl.wIndex=leftcount;
ResetEvent(ov.hEvent);
Result = DeviceIoControl(hPipe,IOCTL_WRITE,&Ioctrl,8,NULL,0,&nBytes,&ov);
}


if (Result != true)
{
if(GetLastError()!=ERROR_IO_PENDING)
{
ShowMessage("数据发送失败, Error1");
return 0;
}
switch(::WaitForSingleObject(ov.hEvent,20))
{
case WAIT_OBJECT_0:
if(!::GetOverlappedResult(hPipe,&ov,&nBytes,true))
return 0;
break;
case WAIT_TIMEOUT:
::CancelIo(hPipe);
return 0;
default:
return 0;
}
}

if(leftcount>=64)
Result1 = WriteFile(hPipe,P_Data,64,&nBytes,&ov);
else
Result1 = WriteFile(hPipe,P_Data,leftcount,&nBytes,&ov);
if (Result1 != true)
{
if(GetLastError()!=ERROR_IO_PENDING)
{
ShowMessage("数据发送失败, Error2");
return 0;
}
while(::WaitForSingleObject(ov.hEvent,20)==WAIT_TIMEOUT)
{
::CancelIo(hPipe);
return 0;
}
if(!GetOverlappedResult(hPipe,&ov,&nBytes,false))
return 0;
}
P_Data += nBytes/4;
leftcount-=nBytes;

}while(leftcount!=0);
if(leftcount==0)
{
Ioctrl.wValue=0;
Ioctrl.wIndex=0;
ResetEvent(ov.hEvent);
Result=DeviceIoControl(hPipe,IOCTL_WRITE,&Ioctrl,8,NULL,0,&nBytes,&ov);
if(Result==true){ShowMessage("发送数据完毕!"); return 1;}
else return 0;
}
}
}

解释上面的三个问题就可以了
 
struct IOREQ{
unsigned int wValue;
unsigned int wIndex;
};
struct SEND{
unsigned long FLAG;
........//SEND 数据格式
}
#ifndef __USBDRIVERioctl__h_
#define __USBDRIVERioctl__h_

#define IOCTL_READ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_WRITE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
#endif    // 1.上面这些是什么意思
..............

if(hPipe != NULL)      //hPipe为得到的USB串口的句柄
{
bool Result,Result1 ;
unsigned long nBytes=0;
int leftcount=148;       //leftcount是要发送数据的位数

unsigned long *P_Data=&SEND_DATA.FLAG; //SEND_DATA已设置好

OVERLAPPED ov;
IOREQ Ioctrl;    // 2.这干什么用的
memset(&ov,0,sizeof(OVERLAPPED));   
ov.hEvent=CreateEvent(NULL,true,false,NULL);

if(ov.hEvent==NULL) //能否解释下下面的if...else....干什么用的
{ShowMessage("Error");
return 0;
}
else
{
do{
if(leftcount>=64) //每次至多发送8个字节
{
Ioctrl.wValue=1;
Ioctrl.wIndex=64;
ResetEvent(ov.hEvent);

Result = DeviceIoControl(hPipe,IOCTL_WRITE,&Ioctrl,8,NULL,0,&nBytes,&ov);
}
else
{
Ioctrl.wValue=2;
Ioctrl.wIndex=leftcount;
ResetEvent(ov.hEvent);
Result = DeviceIoControl(hPipe,IOCTL_WRITE,&Ioctrl,8,NULL,0,&nBytes,&ov);
}


if (Result != true)
{
if(GetLastError()!=ERROR_IO_PENDING)
{
ShowMessage("数据发送失败, Error1");
return 0;
}
switch(::WaitForSingleObject(ov.hEvent,20))
{
case WAIT_OBJECT_0:
if(!::GetOverlappedResult(hPipe,&ov,&nBytes,true))
return 0;
break;
case WAIT_TIMEOUT:
::CancelIo(hPipe);
return 0;
default:
return 0;
}
}

if(leftcount>=64)
Result1 = WriteFile(hPipe,P_Data,64,&nBytes,&ov);
else
Result1 = WriteFile(hPipe,P_Data,leftcount,&nBytes,&ov);
if (Result1 != true)
{
if(GetLastError()!=ERROR_IO_PENDING)
{
ShowMessage("数据发送失败, Error2");
return 0;
}
while(::WaitForSingleObject(ov.hEvent,20)==WAIT_TIMEOUT)
{
::CancelIo(hPipe);
return 0;
}
if(!GetOverlappedResult(hPipe,&ov,&nBytes,false))
return 0;
}
P_Data += nBytes/4;
leftcount-=nBytes;

}while(leftcount!=0);
if(leftcount==0)
{
Ioctrl.wValue=0;
Ioctrl.wIndex=0;
ResetEvent(ov.hEvent);
Result=DeviceIoControl(hPipe,IOCTL_WRITE,&Ioctrl,8,NULL,0,&nBytes,&ov);
if(Result==true){ShowMessage("发送数据完毕!"); return 1;}
else return 0;
}
}
}

解释上面的三个问题就可以了
 
大侠帮帮忙!!!
 
1.
#define IOCTL_READ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_WRITE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
这两个定义的东西你可以理解成就像SendMessage(hWnd, WM_XXX,...);中这个WM_XXX的东西,驱动程序用它来取区分你所调用的功能.而CTL_CODE是一个宏.基本上相当于
#define IOCTL_WRITE FILE_DEVICE_UNKNOWN shl 16 + METHOD_BUFFERED shl ? + FILE_ANY_ACCESS shl ?? + 0x801
前边的那些个BIT你是不能随便定义的,因为他们是标志位,只能选择已有的.比如FILE_ANY_ACCESS表示读写还是只读等.只有0x801这几位才是你能够定义的,并且自定义的一般都在0x800之上选择,避免和系统内部定义的冲突.

2.IOREQ Ioctrl;    // 2.这干什么用的
这个在上边已经说明了它就如同 DWORD msgId; SendMessage(hWnd, msgId, ...);类似,是一个功能标号.

3.
Result = DeviceIoControl(..); //DeviceIoControl如果返回BOOL表示调用是否成功
if (Result != true)
{ //调用失败
if(GetLastError()!=ERROR_IO_PENDING) //他使用的Overlapped操作,好像叫重叠IO.就是异步IO
{ //ERROR_IO_PENDING->重叠IO正在进行, !=自然就是不在进行,自然是错误
ShowMessage("数据发送失败, Error1"); //提示发送失败
return 0;
}
switch(::WaitForSingleObject(ov.hEvent,20)) //如上,重叠IO正在进行,等待重叠IO结束,最多20毫秒
{
case WAIT_OBJECT_0: //重叠IO正常完成
if(!::GetOverlappedResult(hPipe,&ov,&nBytes,true))
return 0;
break;
case WAIT_TIMEOUT: //等待20毫秒超时,取消IO操作
::CancelIo(hPipe);
return 0;
default:
return 0;
}
}
 
谢谢zjan521

关于第二个问题
还是有点不太明白
这里
Ioctrl.wValue=1;
Ioctrl.wIndex=64;
及后面的
  Ioctrl.wValue=2;
   Ioctrl.wIndex=leftcount;
给其它的值不可以吗?




关于第三个问题
我是想明白的是我注释部分的if...else....就是以下代码不太明白

if(leftcount>=64) //每次至多发送8个字节
{
Ioctrl.wValue=1;
Ioctrl.wIndex=64;
ResetEvent(ov.hEvent);

Result = DeviceIoControl(hPipe,IOCTL_WRITE,&Ioctrl,8,NULL,0,&nBytes,&ov);
}
else
{
Ioctrl.wValue=2;
Ioctrl.wIndex=leftcount;
ResetEvent(ov.hEvent);
Result = DeviceIoControl(hPipe,IOCTL_WRITE,&Ioctrl,8,NULL,0,&nBytes,&ov);
}


这些代码不太明白做了什么事,后面不是已经用writeFile发送了需要发送的数据吗?
SEND_Data是我想发送的数据,它为SEND结构类型
struct SEND{
unsigned long FLAG;
........//SEND 数据格式,下面的是我想发送的数据,就不写了
}

能否解释一下
 
第二个问题可能使我看错了,我仅仅看了变量名,没有注意到数据类型,因此解释上不是很贴切.
第三个问题,
Result = DeviceIoControl(hPipe,IOCTL_WRITE,&Ioctrl,8,NULL,0,&nBytes,&ov);
如同我前面所说,这个采用了重叠IO的操作,也就是异步I/O,DeviceIoControl其实是把这个请求放到了内部的队列,然后立即返回,可是这时候实际的IO操作还没有完成.这时候你可以继续作其他的事情,在IO真正完成的时候,系统会设置ov.hEvent,这样你可以在需要的时候通过WaitForSingleObject来得到此IO请求的状态,第二个参数是超时.如果Wait得到的结果是WAIT_OBJECT_0,这就说明ov.hEvent已经被设置,标志请求已经被完成.至于详细的重叠IO的资料,我想需要你去查看MSDN/书籍/网络,我只能说这么多了.
第二个问题:
Result = DeviceIoControl(hPipe,IOCTL_WRITE,&Ioctrl,8,NULL,0,&nBytes,&ov);
IOREQ Ioctrl;是在这里使用的,你可以查看MSDN关于DeviceIoControl的说明,这里实际上是一个输入缓冲区(输入是相对于驱动程序/设备,就是你向设备发送的数据),这个实际上可以使任何类型,既可以是一个RECORD,也可以是一段内存,只要你把指针传递进去即可.至于究竟IOREQ的每个字段代表了什么,这个是由驱动程序决定的,需要你去查开发文档的手册,或者你可以在程序中找到IOREQ(T/O请求)的声明,我想基本上也可以得到信息.这个我是没办法做的.
 
接受答案了.
 
后退
顶部