MFC USB HID
MFC做USB HID上位机程序,背景不表,直接开始。
建立个Project;
执行Visual C++ Project|Settings,打开Link选项卡,在Category中选择Input,在Object/library modules中输入hid.lib setupapi.lib;
在应用程序一个文档内引用头文件,如:
extern "C" { // Declare the C libraries used #include "hidsdi.h" // Must link in hid.lib #include <setupapi.h> // Must link in setupapi.lib } 为方便起见,a_nothing直接拷贝hidpi.h, hidsdi.h, hidusagee.h, hidsdi.lib, setupapi.lib进工程文件夹。
接下来调用API函数,完成需求。
说几个遇到的问题:
应用程序调用ReadFile()函数时,缓冲区是空的,应用程序的执行进程会停止。直到有报表,或Ctrl+Alt+Del关闭应用程序,或是从总线上移除设备。
有仨方法解决:
1. 设备继续发数据;
2. 使用重叠(overlapped)选项ReadFile读取;
3. 使用多线程执行ReadFile读取。
在此采用创建个线程读取。引出的问题是不能UpdateData(), 在界面显示信息等不给力。
说俩方法:
1. 不用UpdateData();
例如,添加个CListBox m_ctrlList;
然后m_ctrlList.AddString(str); m_ctrlList.SetCurSel(m_ctrlList.GetCount()-1);等等。
不太给力。
2. 定义个用户消息。
多说下创建线程和消息:
HANDLE ThreadHandle; DWORD ThreadID; ThreadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&StaticIO_Thread, this, 0, &ThreadID);
CxxxDlg *godKnowsPt; DWORD CxxxDlg::StaticIO_Thread(LPVOID Param) { if(Param != NULL) { godKnowsPt = (CxxxDlg*)CWnd::FromHandle(((CxxxDlg*)Param)->m_hWnd); // UpdateData()用 return ((CxxxDlg*)Param)->ReadReport(); } else return -1; }
// CxxxDlg.cpp中加入: #define WM_GODKNOWS_MESSAGE WM_USER+47
BEGIN_MESSAGE_MAP(CxxxDlg, CDialog) //{{AFX_MSG_MAP(CSCOM6816Dlg) ... ON_MESSAGE(WM_GODKNOWS_MESSAGE, OnUpdateMessage) // insert in ... //}}AFX_MSG_MAP END_MESSAGE_MAP()
// CxxxDlg.h中加入: // Generated message map functions //{{AFX_MSG(CSCOM6816Dlg) ... afx_msg LRESULT OnUpdateMessage(WPARAM wParam, LPARAM lParam); // added here ... DECLARE_EVENTSINK_MAP() //}}AFX_MSG
// 程序中调用 godKnowsPt->PostMessage(WM_GODKNOWS_MESSAGE,0,0);
// UpdateData() LRESULT CxxxDlg::OnUpdateMessage(WPARAM wParam, LPARAM lParam) { UpdateData(FALSE); return 0; }
再说下重叠ReadFile读取,放这里:
// 声明一个重叠结构 OVERLAPPED HIDOverlapped; // 建立一个事件对象,来指示ReadFile的完成 hEventObject = CreateEvent(NULL, TRUE, TRUE, ""); // 指定重叠结构的成员 HIDOverlapped.hEvent = hEventObject; HIDOverlapped.Offset = 0; HIDOverlapped.Offset = 0; // 取得一个代号 ReadHandle = CreateFile( detaileData->DevicePath, GENERIC_READ|FILE_SHARE_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); // 读取一个报表,传递一个指针给重叠结构 Result = ReadFile( ReadHandle, InputReport, Capabilities.InputRepoortByteLength, &BytesRead, (LPOVERLAPPED)&HIDOverlapped); // 等待ReadFile完成或是时间到期 Result = WaitForSingleObject(hEventObject, 5000);
参考书籍:USB2.0硬件设计(第2版) 萧世文 宋延清 编著