以下是網(wǎng)友提出的問(wèn)題和我對這個(gè)問(wèn)題的說(shuō)明。 SMT32F103,根據例程Custom_HID修改,利用EP1 以EP_INTERRUPT 的方式發(fā)送包,原來(lái)的例程每次發(fā)送2個(gè)字節,現在修改后包的長(cháng)度不超過(guò)64字節時(shí)發(fā)送是正常的,但當一個(gè)包長(cháng)超過(guò)64字節時(shí)就發(fā)送失敗,沒(méi)有數據出來(lái)(程序沒(méi)有死機),該改的地方都已經(jīng)修改了,不知道哪個(gè)地方還沒(méi)有改到位,謝謝! 現象就是 超過(guò)63字節的包死活也發(fā)不出去,而且發(fā)送包的大小 還與 CustomHID_ConfigDescriptor里面的 EP1 IN endpoint 描述里包大小有關(guān) ,沒(méi)道理啊,其他的MCU 這地方設置為8 照樣發(fā)送256B 以上的包。 在Custom_HID例程上修改了如下代碼: 1.usb_proc.c 的CustomHID_Reset()里 SetEPTxCount(ENDP1, 64); 2.關(guān)閉 DMA中斷,不讓ADC采樣后發(fā)送EP1包 3.在main.c里 重復發(fā)送一個(gè)128B的包, while(1){ for(i=0;i<2;i++) { SetEPTxAddr(ENDP1, ENDP1_TXADDR+i*64); SetEPTxValid(ENDP1); Delay(10000); } } 4. 由于一個(gè)包是128B,最大包長(cháng)是64B,所以分兩次發(fā)送出來(lái),奇怪的是所有例程發(fā)送包時(shí)都沒(méi)有查發(fā)送狀態(tài)的處理,也沒(méi)有找到相應的狀態(tài)等待函數,這樣的話(huà),是不是出現第一個(gè)包還沒(méi)有發(fā)送完,第二個(gè)包就沖掉了第一個(gè)包的數據? 5. 所以問(wèn)題很簡(jiǎn)單,就是如何發(fā)送一個(gè)多數據包,發(fā)送函數要如何寫(xiě)? 以下是關(guān)于這個(gè)問(wèn)題的解答: 分兩次發(fā)送是對的,但關(guān)鍵是每次發(fā)送前需要檢查上次發(fā)送是否完成。 檢查一個(gè)端點(diǎn)的發(fā)送是否結束有2種方法,第一種方法是當發(fā)送結束(設備收到ACK)時(shí),有一個(gè)發(fā)送結束中斷,這個(gè)中斷由USB庫處理,并通過(guò)EP1_IN_Callback這個(gè)回調函數交由用戶(hù)程序確認,你可以搜索一下,例子中把EP1_IN_Callback定義為NOP_Process,沒(méi)有處理這個(gè)回調事件。如果要用這種方法檢測端點(diǎn)發(fā)送結束,你需要自己定義回調函數并做相應處理。 檢測端點(diǎn)發(fā)送結束的另一個(gè)方法是查詢(xún)這個(gè)端點(diǎn)的狀態(tài),如果端點(diǎn)狀態(tài)處于EP_TX_VALID,說(shuō)明發(fā)送未結束,如果端點(diǎn)狀態(tài)處于EP_TX_NAK,說(shuō)明發(fā)送結束。使用下述調用可以得到端點(diǎn)1的發(fā)送狀態(tài): GetEPTxStatus(ENDP1) 按照你的思路,可以使用第二種方法實(shí)現發(fā)送多個(gè)數據包的功能。 假定要發(fā)送150個(gè)字節的MyBuffer,EP1的最大包長(cháng)設為64字節。 u8 MyBuffer[150]; int packetN; packetN = 3; while (1) { if (packetN < 3) { // 有數據需要發(fā)送時(shí)置packetN為'0' if (GetEPTxStatus(ENDP1) == EP_TX_NAK) { if (packetN == 0) { // 拷貝頭64字節到發(fā)送緩沖區 UserToPMABufferCopy(MyBuffer, ENDP1_TXADDR, 64); SetEPTxCount(ENDP1, 64); } else if (packetN == 1) { // 拷貝第2個(gè)64字節到發(fā)送緩沖區 UserToPMABufferCopy(MyBuffer+64, ENDP1_TXADDR, 64); SetEPTxCount(ENDP1, 64); } else if (packetN == 2) { // 拷貝最后22字節到發(fā)送緩沖區 UserToPMABufferCopy(MyBuffer+128, ENDP1_TXADDR, 22); SetEPTxCount(ENDP1, 22); } packetN++; SetEPTxStatus(ENDP1, EP_TX_VALID); } } ...... // 其它操作 } 這里使用了一個(gè)變量記錄應該發(fā)送第幾個(gè)數據包,當程序的其它部分準備好數據后只要設置這個(gè)變量packetN=0,上述發(fā)送操作就會(huì )啟動(dòng),程序的其它部分只需檢測packetN==3即可知道MyBuffer是否已經(jīng)騰空,程序的其它部分可以使用MyBuffer繼續其它操作,注意這時(shí)數據不一定已經(jīng)全部發(fā)送完畢。 你的另一個(gè)問(wèn)題在于這一行:SetEPTxAddr(ENDP1, ENDP1_TXADDR+i*64); ENDP1_TXADDR是專(zhuān)門(mén)的發(fā)送緩沖區,它的長(cháng)度是有限的,而且是每32位編址中只有低16位有效;所以需要使用函數UserToPMABufferCopy()操作這個(gè)發(fā)送緩沖區,這個(gè)函數已經(jīng)在USB庫的手冊中說(shuō)明。 最后一個(gè)問(wèn)題是:如果你的程序中使用了ENDP1_RXADDR,因為你改變了ENDP1包的長(cháng)度,即改變了發(fā)送緩沖區的長(cháng)度,需要在usb_conf.h中重新定義以下ENDP1_RXADDR的地址。 最初發(fā)表日期:2008-8-29 |