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版) 萧世文 宋延清 编著

posted @ 2011-01-19 17:31  yangzd  阅读(6122)  评论(2编辑  收藏  举报