當(dāng)前位置:首頁(yè) > 單片機(jī) > 單片機(jī)
[導(dǎo)讀]1 前言本文將基于STM32F4DISCOVERY板,介紹如何使用USB的CDC類進(jìn)行開發(fā),以及在開發(fā)過(guò)程中碰到發(fā)送64整數(shù)倍數(shù)據(jù)時(shí)會(huì)失敗的問(wèn)題分析及解決方案。2 硬件介紹在創(chuàng)建工程之前,我們首先即將使用的硬件進(jìn)行必要的介紹。圖

1 前言

本文將基于STM32F4DISCOVERY板,介紹如何使用USB的CDC類進(jìn)行開發(fā),以及在開發(fā)過(guò)程中碰到發(fā)送64整數(shù)倍數(shù)據(jù)時(shí)會(huì)失敗的問(wèn)題分析及解決方案。

2 硬件介紹

在創(chuàng)建工程之前,我們首先即將使用的硬件進(jìn)行必要的介紹。


圖1 USB電路


如上圖所示,USB電路使用PA11,PA12,全速USB OTG,當(dāng)然,這里只做device,英雌只需要看上圖的下面部分。


圖2 按鍵電路


如上圖,本例中將使用到1個(gè)用戶按鍵,PA0,按下時(shí)為1電平。
另外,晶振使用的是外部HSE 8M晶振。


3 創(chuàng)建CubeMx工程

打開CubeMX(V4.17.0),創(chuàng)建一個(gè)以STM32F407VGTx的工程,使用FS-USB,并使用PA0外部輸入EXIT,如下圖所示:


圖3 pinout


使能外部HSE,使用外部8M HSE,其時(shí)鐘樹如下設(shè)置:


圖4 時(shí)鐘樹


接下來(lái)是配置參數(shù),這里只修改USB中斷優(yōu)先級(jí)為1,而PA0的外部中斷優(yōu)先級(jí)設(shè)置為4,如下:


圖5 中斷優(yōu)先級(jí)設(shè)置


然后再中間件將USB class設(shè)置為Communicaiton Device Class,如下:


圖6 USB Class設(shè)置


最后將工程的堆設(shè)為0.5K,棧設(shè)為1.5K :


圖7 堆棧設(shè)置


最后生成一個(gè) F407_CDC_Test的工程。


4 修改工程代碼

我們對(duì)生成的工程不做任何修改,直接編譯后燒進(jìn)開發(fā)板后是可以被PC識(shí)別為虛擬串口的,如下圖所示:


圖8 PC識(shí)別為虛擬串口


當(dāng)然,這里的前提是必須在PC機(jī)上安裝了ST發(fā)布的虛擬串口驅(qū)動(dòng)(STSW-STM32102下載地址 :http://www.st.com/content/st_com/en/products/development-tools/software-development-tools/stm32-software-development-tools/stm32-utilities/stsw-stm32102.html)。


(注意:這里所說(shuō)的虛擬串口主要是指其可以被當(dāng)做串口來(lái)用,但其速度跟串口所設(shè)置的波特率完全沒有關(guān)系,用戶不要被名字所迷惑,雖然使用起來(lái)跟串口沒有區(qū)別,但其本質(zhì)還是USB,在初始化設(shè)置波特率不會(huì)對(duì)USB的通訊速率產(chǎn)生任何影響,本文檔所描述的是全速USB,因此,其最大速率就固定為12M/S,這個(gè)是由全速USB外設(shè)標(biāo)準(zhǔn)48M輸入時(shí)鐘所決定的)

此時(shí)是沒有任何具體功能的,為了更好的看到通訊的數(shù)據(jù),我們將使用串口通訊工具來(lái)進(jìn)行測(cè)試,這里我們使用的串口工具是: sscom32.

4.1 驗(yàn)證接收功能

我們將使用PC串口工具SSCOM32通過(guò)USB向MCU發(fā)送數(shù)據(jù),為了能在PC端能看到MCU是否能接收到數(shù)據(jù),我們?cè)贛CU端修改代碼,讓MCU一旦接收到來(lái)自PC端的數(shù)據(jù)后,立馬返回一模一樣的數(shù)據(jù),因此需要在生成的源碼文件usbd_cdc_if.c文件中找到到函數(shù):CDC_Receive_FS(),添加處理函數(shù),如下:

staticint8_tCDC_Receive_FS(uint8_t*Buf,uint32_t*Len){/*USERCODEBEGIN6*/HanldeReceiveData(Buf,*Len);USBD_CDC_SetRxBuffer(&hUsbDeviceFS,&Buf[0]);USBD_CDC_ReceivePacket(&hUsbDeviceFS);return(USBD_OK);/*USERCODEEND6*/}/*USERCODEBEGINPRIVATE_FUNCTIONS_IMPLEMENTATION*/staticvoidHanldeReceiveData(uint8_t*Buf,uint32_tLen){CDC_Transmit_FS(Buf,Len);}/*USERCODEENDPRIVATE_FUNCTIONS_IMPLEMENTATION*/12345678910111213141516171234567891011121314151617

編譯后燒進(jìn)板子進(jìn)行驗(yàn)證:


圖9%20MCU接收返回相同數(shù)據(jù)


如上如所示,串口工具能夠收到來(lái)自MCU的返回?cái)?shù)據(jù),與發(fā)送數(shù)據(jù)完全一樣,這說(shuō)明,MCU已經(jīng)接收到了PC端發(fā)送的數(shù)據(jù),另外,PC端也能接收到MCU端發(fā)送的數(shù)據(jù)。


4.2%20驗(yàn)證發(fā)送功能

接下來(lái)我們來(lái)通過(guò)按鍵響應(yīng)來(lái)主動(dòng)向PC端發(fā)送數(shù)據(jù),我們?cè)诎存I回調(diào)函數(shù)內(nèi)添加代碼如下:

/*USERCODEBEGIN0*/staticuint8_tSendData[256]={0};voidHAL_GPIO_EXTI_Callback(uint16_tGPIO_Pin){uint16_ti;for(i=0;i

即用戶按下按鍵,MCU則向PC端發(fā)送一次數(shù)據(jù),這里發(fā)送的是63個(gè)字節(jié),內(nèi)容為0~62,測(cè)試后PC端的串口工具完全能收到MCU端發(fā)送的63個(gè)字節(jié),如下圖所示:


圖10 PC端收到63個(gè)字節(jié)


但是當(dāng)我們將代碼修改為發(fā)送64個(gè)字節(jié)后 :


/*USERCODEBEGIN0*/staticuint8_tSendData[256]={0};voidHAL_GPIO_EXTI_Callback(uint16_tGPIO_Pin){uint16_ti;for(i=0;i

修改后進(jìn)行驗(yàn)證,發(fā)現(xiàn)PC端串口工具不能接收到數(shù)據(jù),,這里代碼基本完全沒有變化,只是發(fā)送長(zhǎng)度之前為63,這里為64,結(jié)果卻不相同,很明顯,USB CDC協(xié)議棧哪里出了問(wèn)題。

我們先使用USB分析儀對(duì)發(fā)送64個(gè)字節(jié)時(shí)進(jìn)行USB總線監(jiān)控:


圖11 USB數(shù)據(jù)監(jiān)控


如上圖,我們發(fā)現(xiàn),當(dāng)發(fā)送64個(gè)字節(jié)時(shí),由于正好是最大包長(zhǎng)(64),按USB標(biāo)準(zhǔn)來(lái)看,應(yīng)該多發(fā)一次空的transaction,但是這里,僅僅只發(fā)了一次transaction,這也就是為什么串口沒有接收到數(shù)據(jù)的原因(MCU端的USB實(shí)際上是已經(jīng)發(fā)送了64個(gè)字節(jié),但由于缺少一個(gè)transaction,因此PC端的驅(qū)動(dòng)會(huì)認(rèn)為數(shù)據(jù)格式不完整,而放棄所有已經(jīng)接收到的數(shù)據(jù),從而使上層看起來(lái)沒有接收到任何內(nèi)容)。


圖12 USB2.0標(biāo)準(zhǔn)對(duì)于最大包長(zhǎng)整數(shù)倍的要求


因此,接下來(lái)的工作就是找到USB協(xié)議棧中的相應(yīng)處理環(huán)節(jié),然后將缺少的那個(gè)空的transaction補(bǔ)上即可。


4.3 USB CDC協(xié)議棧修改4.3.1 USB數(shù)據(jù)發(fā)送流程分析

在對(duì)USB CDC協(xié)議棧進(jìn)行修改之前,我們先來(lái)梳理下USB發(fā)送的流程。
發(fā)送USB數(shù)據(jù)大概過(guò)程如下:
1> 填寫DIEPTSIZ寄存器的發(fā)送包數(shù)(pakage count)和傳輸大小(transfer size)。
2> 使能發(fā)送斷點(diǎn)的發(fā)送空中斷(DIEPEMPMSK,利用發(fā)送空中斷TXFE來(lái)將發(fā)送數(shù)據(jù)填充到DFIFO)。
3> 使能中斷。
4> 后續(xù)就是中斷的事了。
后續(xù)將會(huì)有3次中斷:
1> USB_OTG_DIEPINT_TXFE中斷:在此中斷處理中,程序?qū)l(fā)送緩沖的數(shù)據(jù)分包填充到DFIFO(不能超過(guò)最大包長(zhǎng),只有最后一包數(shù)據(jù)才有可能小于最大包長(zhǎng))。
2> USB_OTG_DIEPINT_TXFE中斷: 還是TXFE中斷,上次TXFE填充的發(fā)送數(shù)據(jù)全部發(fā)送完了后,最終還是會(huì)繼續(xù)觸發(fā)TXFE中斷,也就是這次中斷,在這次FXFE中斷中禁止FXFE。也就是說(shuō),后續(xù)不會(huì)再有TXFE中斷,除非再次使能。
3> USB_OTG_DIEPINT_XFRC中斷:傳輸完成中斷,表示到這次中斷為止,傳輸完成。在這個(gè)中斷中將回調(diào)HAL_PCD_DataInStageCallback()函數(shù),就相當(dāng)于發(fā)送中斷一樣。
這就是USB數(shù)據(jù)發(fā)送的流程,這里需要注意地是,對(duì)于端點(diǎn)0和非端點(diǎn)0來(lái)說(shuō),在具體流程實(shí)現(xiàn)上還是稍微有所差異的。究其原因,主要是端點(diǎn)0和非端點(diǎn)0的DIEPTSIZ寄存器的包大小和傳輸大小位寬是不一樣的。如下圖:


圖13 端點(diǎn)0的DIEPTSIZ寄存器



圖14 端點(diǎn)1~3的DIEPTSIZ寄存器


對(duì)比上圖,端點(diǎn)0的DIEPTSIZ寄存器的XFRSIZ位寬為7,最大值為127,也就是說(shuō)最多一次只能傳輸127個(gè)字節(jié),按最大包長(zhǎng)64字節(jié)來(lái)算,就是是最多兩包數(shù)據(jù)。如果需要發(fā)送超過(guò)127個(gè)字節(jié)時(shí),又該如何做呢?查看USB協(xié)議棧內(nèi)核代碼,發(fā)現(xiàn)每次端點(diǎn)0發(fā)送數(shù)據(jù)時(shí),在發(fā)送代碼中固定每次最多可以傳輸64字節(jié),然后在傳輸完成中斷處理時(shí),再將剩下的數(shù)據(jù)接著傳輸(usb core),當(dāng)然,每次傳輸最多也是64個(gè)字節(jié),就這樣,直到發(fā)送完所有數(shù)據(jù)為止。為什么每次傳輸最大設(shè)置為64?不是XFRSIZ位寬為7,理論上可以為127嗎?我的理解是,這樣也是可以的,只要包長(zhǎng)控制在64個(gè)字節(jié)內(nèi)就可以了,至于每次傳輸多少字節(jié),只要XFRSIZ位寬夠用,你可以設(shè)置127個(gè)字節(jié)范圍內(nèi)任何數(shù)據(jù)均可。代碼中設(shè)置為64,主要為了圖方便。


但是,對(duì)于非端點(diǎn)0,XFRSIZ位寬為19位,524288個(gè)字節(jié),足夠傳輸所有實(shí)際數(shù)據(jù)了,因此,在發(fā)送代碼中,并沒有限定傳輸數(shù)據(jù)的長(zhǎng)度,在TXFE中斷中也能將所有待發(fā)送的字節(jié)填入DFIFO。但是,當(dāng)發(fā)送的數(shù)據(jù)剛好是64的整數(shù)倍時(shí),按USB標(biāo)準(zhǔn),應(yīng)該繼續(xù)發(fā)送一次空字節(jié),以表示數(shù)據(jù)全部發(fā)送完畢。

4.3.2 代碼修改

對(duì)比端點(diǎn)0的處理,發(fā)現(xiàn)端點(diǎn)0在傳輸完成中斷(XFRC)中,有對(duì)這種情況的判斷,一旦檢測(cè)到這種情況,則會(huì)發(fā)送一次空傳輸。如下:
usb_core.c文件中的USBD_LL_DataInStage()函數(shù) :

USBD_StatusTypeDefUSBD_LL_DataInStage(USBD_HandleTypeDef*pdev,uint8_tepnum,uint8_t*pdata){USBD_EndpointTypeDef*pep;if(epnum==0){pep=&pdev->ep_in[0];if(pdev->ep0_state==USBD_EP0_DATA_IN){if(pep->rem_length>pep->maxpacket){pep->rem_length-=pep->maxpacket;//繼續(xù)發(fā)送剩余數(shù)據(jù)USBD_CtlContinueSendData(pdev,pdata,pep->rem_length);/*Prepareendpointforprematureendoftransfer*/USBD_LL_PrepareReceive(pdev,0,NULL,0);}else{/*lastpacketisMPSmultiple,sosendZLPpacket*/if((pep->total_length%pep->maxpacket==0)&&(pep->total_length>=pep->maxpacket)&&(pep->total_lengthep0_data_len)){//再多發(fā)送一次空數(shù)據(jù)USBD_CtlContinueSendData(pdev,NULL,0);pdev->ep0_data_len=0;/*Prepareendpointforprematureendoftransfer*/USBD_LL_PrepareReceive(pdev,0,NULL,0);}else{if((pdev->pClass->EP0_TxSent!=NULL)&&(pdev->dev_state==USBD_STATE_CONFIGURED)){pdev->pClass->EP0_TxSent(pdev);}USBD_CtlReceiveStatus(pdev);}}}if(pdev->dev_test_mode==1){USBD_RunTestMode(pdev);pdev->dev_test_mode=0;}}elseif((pdev->pClass->DataIn!=NULL)&&(pdev->dev_state==USBD_STATE_CONFIGURED)){pdev->pClass->DataIn(pdev,epnum);//非0端點(diǎn)回調(diào)CDC類的DataIn()函數(shù)處理}returnUSBD_OK;}12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364651234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來(lái)越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來(lái)越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開幕式在貴陽(yáng)舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語(yǔ)權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉