新聞中心

        EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 完成stm32 上HID的應(yīng)用

        完成stm32 上HID的應(yīng)用

        作者: 時(shí)間:2016-11-25 來(lái)源:網(wǎng)絡(luò) 收藏
        這個(gè)是公司的項(xiàng)目,以前基于usb的虛擬串口來(lái)做上下位機(jī)通信,由于usb平時(shí)也就刷參數(shù)和調(diào)試之用,也不很常用,外面反應(yīng)usb有時(shí)會(huì)連不上stm32控制器,心里一直認(rèn)為不是大問(wèn)題,后來(lái)反應(yīng)的多了,就重視這個(gè)事情了,雖然usb平時(shí)不用,但是用的時(shí)候只要出現(xiàn)異常掉線,就再也連不上去了,特別影響用戶對(duì)我們產(chǎn)品的信心。
        在網(wǎng)上找了很多資料,到現(xiàn)在也只能隱約確定是stm32官方的虛擬串口庫(kù)有問(wèn)題,我發(fā)現(xiàn)不同的電源板都會(huì)影響到usb虛擬串口的枚舉,于是下定決心使用其他方式來(lái)做上下位機(jī)的連接,排除了usb虛擬串口,眼前的選擇只有兩個(gè)
        1)usblib,這個(gè)是針對(duì)usb的上位機(jī)庫(kù),可以玩很多的花樣,但是需要開(kāi)發(fā)者稍稍熟悉usb協(xié)議,而且這個(gè)需要在上位機(jī)上安裝usb驅(qū)動(dòng)程序。
        2)hid設(shè)備,這個(gè)是windows自身支持的usb設(shè)備,只支持中斷傳輸,最大的速率也就64Kb/s,上位機(jī)采用windows api編程
        我估算了一下,hid方式滿足我的要求,而且是免驅(qū)動(dòng),又不用學(xué)習(xí)usblib,所以就使用hid方式實(shí)現(xiàn)了usb通信。
        hid幾個(gè)注意事項(xiàng):
        1)對(duì)于windows API來(lái)說(shuō),讀和寫(xiě)hid設(shè)備的數(shù)據(jù)包都是大小確定了,也就是說(shuō)如果stm32 端口設(shè)備的hid屬性是64的話,那么讀寫(xiě)都是64字節(jié)的。讀寫(xiě)的最大幀是64字節(jié),我在代碼中是基于64字節(jié)做應(yīng)用層協(xié)議的。
        2)hid寫(xiě)速度不能太快,所以我一般在寫(xiě)前會(huì)等待2ms左右,確保不會(huì)寫(xiě)出錯(cuò)。
        確認(rèn)是是HIDAPI的代碼問(wèn)題,我對(duì)寫(xiě)函數(shù)修改如下,結(jié)果就好了,可以一直寫(xiě)無(wú)需等待
        int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length)
        {
        DWORD bytes_written;
        BOOL res;
        BOOL bResult;
        OVERLAPPED ol;
        HANDLE ReportEvent;
        ReportEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
        ResetEvent(ReportEvent);
        memset(&ol, 0, sizeof(ol));
        ol.hEvent = ReportEvent;
        //res = WriteFile(dev->device_handle, data, 23, NULL, &ol);
        res = WriteFile(dev->device_handle, data, length, NULL, &ol);
        if (!res) {
        int errcode = GetLastError();
        if (errcode != ERROR_IO_PENDING) {
        // WriteFile() failed. Return error.
        register_error(dev, "WriteFile");
        return -1;
        }
        }
        bResult = WaitForSingleObject(ReportEvent, 50);
        if(bResult == WAIT_TIMEOUT || bResult == WAIT_ABANDONED)
        {
        register_error(dev, "WriteFile");
        CancelIo(&(dev->device_handle));
        return -1;
        }
        // Wait here until the write is done. This makes
        // hid_write() synchronous.
        res = GetOverlappedResult(dev->device_handle, &ol, &bytes_written, TRUE);
        if (!res) {
        // The Write operation failed.
        register_error(dev, "WriteFile");
        return -1;
        }
        return bytes_written;
        }
        3)上位機(jī)上的讀寫(xiě)之間不能釋放hid的句柄,這個(gè)我參考百合的hid教材的時(shí)候,吃了不少苦頭。
        4)我使用了HIDAPI這個(gè)庫(kù)來(lái)操作hid設(shè)備。
        具體細(xì)節(jié)的東西大家可以看看網(wǎng)上找到的hid教程,我的代碼和可執(zhí)行代碼下載鏈接如下
        http://pan.baidu.com/s/1qzTJw
        注意:上面鏈接中的寫(xiě)函數(shù)我沒(méi)有修正,請(qǐng)讀者自己修改


        關(guān)鍵詞: stm32HI

        評(píng)論


        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 微博| 谢通门县| 绥中县| 肃北| 车致| 稻城县| 城市| 蒙城县| 黄梅县| 宁蒗| 克什克腾旗| 庆安县| 侯马市| 东乌珠穆沁旗| 梅州市| 平度市| 军事| 长治市| 临夏市| 霸州市| 灵武市| 共和县| 洪湖市| 正镶白旗| 洛宁县| 河津市| 昭平县| 和顺县| 万盛区| 汪清县| 墨脱县| 睢宁县| 南漳县| 南投市| 襄城县| 桂阳县| 湘阴县| 富民县| 清镇市| 宜章县| 宝丰县|