USB学习笔记三《读写USB设备+示例代码》

通过前两节,可以正确识别自己的USB-HID设备了,剩下最重要的就是通信了,总结如下;

读取USB-HID设备上传的数据:

由于我们并不知道下位机何时上传数据,因此,我们创建一个辅助线程,来监听USB设备,一旦由数据到来,取走数据,并告诉主程序;

一、首先定义读取异步读USB状态变量

//异步操作
OVERLAPPED m_osRead,m_osWrite;

//初始化

memset(&m_osRead,0,sizeof(OVERLAPPED)); //异步读

memset(&m_osWrite,0,sizeof(OVERLAPPED)); //异步写

二、建立辅助线程

//线程函数
UINT USBReadThreadFunction(LPVOID pParam);


//创建线程
if(usbread_pThread == NULL)
usbread_pThread = AfxBeginThread(USBReadThreadFunction,this,THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED,NULL);
if(usbread_pThread == NULL)
{
CloseHandle(hidHandle);
hidHandle = INVALID_HANDLE_VALUE;
RichEditShow(_T("线程创建失败"));
m_ConnectionFlag=false;
return false;
}
else
{
usbread_pThread->ResumeThread();
}


/*******************************************************************

读报告的线程。由于使用的是异步调用,因而在调用ReadFile
函数时提供一个Overlapped的结构,该结构中含有一个事件的
句柄。平时该事件是处于无信号状态的,因而等待事件的函数
就会被挂起,从而该线程被阻塞。当数据正确返回后,事件被
触发,线程恢复运行。并检查返回的数据量以及报告ID是否正
确,从而设置界面上各开关的状态。由于该函数并不是
CUnidirectionaltesttoolingDlg类(就是该工程中主窗口类)中的成员函数,
所以无法直接调用CUnidirectionaltesttoolingDlg类中的成员函数。
在创建该线程时,通过pParam参数传递了一个this指针,将参数pParam
强制转化为CUnidirectionaltesttoolingDlg类的指针即可
访问CUnidirectionaltesttoolingDlg类中的成员函数。

*********************************************************************/


//创建工作者线程入口函数
UINT USBReadThreadFunction(LPVOID pParam)
{
CUnidirectionaltesttoolingDlg *pDlg = (CUnidirectionaltesttoolingDlg *)pParam;

while(1)
{
if(pDlg->EventObject!=NULL)
{
pDlg->USBReadProcessing(0);
}
else
{
WaitForSingleObject(m_osRead.hEvent,INFINITE);
}
}
return 0;
}


bool CUnidirectionaltesttoolingDlg::USBReadProcessing(int usb)
{
if(hidHandle==INVALID_HANDLE_VALUE)
{
return false;
}
unsigned int read_count=0;
read_count=USBRead();
if(read_count==0)
{
return false;
}


if(usb_judge_time1==1)//PC请求建立连接
{
KillTimer(WM_TIMER1);
usb_judge_time1=0;
usb_judge_write=0;
usb_councet   =0;
if((usb_inBuffer[1]==0x98) && (usb_inBuffer[2]==0xAC))
{
RichEditShow(_T("PC建立连接成功"));
usb_judge_write=5;
}
return true;
}


。。。。。。

。。。。。。


unsigned int CUnidirectionaltesttoolingDlg::USBRead()
{
if(hidHandle ==INVALID_HANDLE_VALUE)
{
return 0;
}
ResetEvent(m_osRead.hEvent);
unsigned long BytesRead;
m_osRead.Offset = 0;
SetLastError(NO_ERROR);
ReadFile(  hidHandle, 
 (LPVOID)usb_inBuffer,
//  inCapabilities.InputReportByteLength,
 65,
 &BytesRead, 
 (LPOVERLAPPED)&m_osRead);
DWORD bResult = WaitForSingleObject(m_osRead.hEvent,INFINITE);//0:立即反悔;n:到时间返回;INFINITE:一直等待,知道对象处于通知状态


if(hidHandle ==INVALID_HANDLE_VALUE)//防止期间拔出USB设备
{
return 0;
}


if(bResult == WAIT_TIMEOUT || bResult == WAIT_ABANDONED)
{
CancelIo(&hidHandle);//取消由本线程处理的所有等待的输入输出(I/O)操作。函数不能取消由其他线程处理的I/O操作。
//如果要取消其他线程处理的I/O操作,可以使用CancelIoEx函数。
memset(usb_inBuffer,0,65);
BytesRead = 0;
}
if(bResult == WAIT_OBJECT_0)
{
//如果重叠操作未完成,等待直到操作完成
if(GetLastError() == ERROR_IO_PENDING)
{
BytesRead=GetLastError();
GetOverlappedResult(hidHandle,&m_osRead,&BytesRead,TRUE);
m_osRead.Offset = 0;
}
else
{
memset(usb_inBuffer,0,65);
BytesRead = 0;
}
}
ResetEvent(m_osRead.hEvent);
return (unsigned int)BytesRead;
}注意:在找到USB设备时候,要手动触发下

//手动触发事件,让读报告线程恢复运行。因为在这之前并没有调用
//读数据的函数,也就不会引起事件的产生,所以需要先手动触发一
//次事件,让读报告线程恢复运行。
SetEvent(m_osRead.hEvent);


写USB函数

1、创建辅助函数

UINT USBWriteThreadFunction(LPVOID pParam);


if(usbwrite_pThread == NULL)
usbwrite_pThread = AfxBeginThread(USBWriteThreadFunction,this,THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED,NULL);
if(usbwrite_pThread == NULL)
{
CloseHandle(hidHandle);
hidHandle = INVALID_HANDLE_VALUE;
RichEditShow(_T("线程创建失败"));
m_ConnectionFlag=false;
return false;
}
else
{
usbwrite_pThread->ResumeThread();
}



UINT USBWriteThreadFunction(LPVOID pParam)
{
CUnidirectionaltesttoolingDlg *pDlg = (CUnidirectionaltesttoolingDlg *)pParam;


while(1)
{
if(pDlg->EventObject!=NULL)
{
pDlg->USBWriteProcessing(0);
}
}
return 0;

}


bool CUnidirectionaltesttoolingDlg::USBWriteProcessing(int usb)
{
if(hidHandle==INVALID_HANDLE_VALUE)
{
return false;
}
if(usb_judge_write==1)//PC机建立连接请求
{
usb_judge_write =0;
usb_judge_time1 =1;
usb_outBuffer[1]=0x91;
usb_outBuffer[2]=0xAC;
USBWrite();
SetTimer(WM_TIMER1,Time1,0);
return true;
}

。。。。。。

。。。。。。

unsigned int CUnidirectionaltesttoolingDlg::USBWrite()
{
if(hidHandle ==INVALID_HANDLE_VALUE)
{
return 0;
}
ResetEvent(m_osWrite.hEvent);
unsigned long BytesWritten;
usb_outBuffer[0]=0;
m_osWrite.Offset = 0;
SetLastError(NO_ERROR);
WriteFile(    hidHandle,
(LPVOID)usb_outBuffer, 
// outCapabilities.OutputReportByteLength, 
65,
&BytesWritten,
(LPOVERLAPPED)&m_osWrite);
DWORD bResult=WaitForSingleObject(m_osWrite.hEvent,INFINITE);//0:立即反悔;n:到时间返回;INFINITE:一直等待,知道对象处于通知状态


//防止拔出
if(hidHandle ==INVALID_HANDLE_VALUE)
{
return 0;
}


if(bResult == WAIT_TIMEOUT || bResult == WAIT_ABANDONED)
{
CancelIo(&hidHandle);//取消本调线程处理的所有等待的输入输出(I/O)操作。函数不能取消由其他线程处理的I/O操作。
//如果要取消其他线程处理的I/O操作,可以使用CancelIoEx函数。
BytesWritten = 0;
}
if(bResult == WAIT_OBJECT_0)
{
if(GetLastError() == ERROR_IO_PENDING)
{
// BytesWritten=GetLastError();
GetOverlappedResult(hidHandle,&m_osWrite,&BytesWritten,TRUE);
m_osWrite.Offset = 0;
}
else
BytesWritten = 0;
}
ResetEvent(m_osWrite.hEvent);
return (unsigned int)BytesWritten;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值