日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

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

1 前言

本文將基于STM32F4DISCOVERY板,介紹如何使用USB的CDC類進(jìn)行開(kāi)發(fā),以及在開(kāi)發(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工程

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


圖3 pinout


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


圖4 時(shí)鐘樹(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)開(kāi)發(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è)置的波特率完全沒(méi)有關(guān)系,用戶不要被名字所迷惑,雖然使用起來(lái)跟串口沒(méi)有區(qū)別,但其本質(zhì)還是USB,在初始化設(shè)置波特率不會(huì)對(duì)USB的通訊速率產(chǎn)生任何影響,本文檔所描述的是全速USB,因此,其最大速率就固定為12M/S,這個(gè)是由全速USB外設(shè)標(biāo)準(zhǔn)48M輸入時(shí)鐘所決定的)

此時(shí)是沒(méi)有任何具體功能的,為了更好的看到通訊的數(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ù),,這里代碼基本完全沒(méi)有變化,只是發(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,這也就是為什么串口沒(méi)有接收到數(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)沒(mé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> 填寫(xiě)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ā)送代碼中,并沒(méi)有限定傳輸數(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)系本站刪除( 郵箱:macysun@21ic.com )。
換一批
延伸閱讀

九款全新型號(hào)最高支持 7 A 保持電流與 72 V 額定電壓,部分型號(hào)采用 SMD 封裝,大幅提升設(shè)計(jì)彈性與應(yīng)用選擇性

關(guān)鍵字: 保險(xiǎn)絲 控制系統(tǒng) USB

在現(xiàn)代應(yīng)用架構(gòu)中,數(shù)據(jù)庫(kù)連接池是提升系統(tǒng)性能、優(yōu)化資源利用的關(guān)鍵組件。它通過(guò)復(fù)用數(shù)據(jù)庫(kù)連接,避免了頻繁創(chuàng)建和銷毀連接帶來(lái)的性能開(kāi)銷,同時(shí)能有效控制并發(fā)連接數(shù),防止數(shù)據(jù)庫(kù)因過(guò)載而崩潰。然而,連接池大小的設(shè)置是一項(xiàng)極具挑戰(zhàn)性...

關(guān)鍵字: 數(shù)據(jù)庫(kù) 數(shù)據(jù)

【2026年3月18日, 德國(guó)慕尼黑訊】全球功率系統(tǒng)和物聯(lián)網(wǎng)領(lǐng)域的半導(dǎo)體領(lǐng)導(dǎo)者英飛凌科技股份公司(FSE代碼:IFX / OTCQX代碼:IFNNY)推出EZ-PD? PMG1-B2,這是業(yè)內(nèi)首款高度集成的單端口USB...

關(guān)鍵字: 控制器 USB 鋰離子電池

新一代架構(gòu)實(shí)現(xiàn)更快速分析、更清晰洞察與緊湊設(shè)計(jì),將數(shù)日的數(shù)字驗(yàn)證縮短至數(shù)小時(shí)

關(guān)鍵字: 示波器 DDR5 USB

STM32系列微控制器因其高性能和豐富的外設(shè)接口被廣泛應(yīng)用于各類場(chǎng)景。當(dāng)涉及USB高速(HS)與全速(FS)接口設(shè)計(jì)時(shí),開(kāi)發(fā)者常因?qū)π盘?hào)完整性、ESD防護(hù)及電源管理的理解不足而陷入調(diào)試?yán)Ь场1疚膶脑沓霭l(fā),結(jié)合實(shí)際案例...

關(guān)鍵字: STM32 USB

STM32的USB高速(HS)接口因其480Mbps的傳輸速率,廣泛應(yīng)用于數(shù)據(jù)采集、視頻傳輸?shù)葓?chǎng)景。然而,高頻信號(hào)與電源噪聲的耦合常導(dǎo)致EMC(電磁兼容性)問(wèn)題,表現(xiàn)為輻射超標(biāo)、通信中斷或設(shè)備誤觸發(fā)。本文以實(shí)際項(xiàng)目為背景...

關(guān)鍵字: STM32 USB EMC

嵌入式系統(tǒng)設(shè)計(jì),同時(shí)集成SRAM、SD卡和USB接口已成為高性能數(shù)據(jù)采集與存儲(chǔ)設(shè)備的常見(jiàn)需求。然而,這三個(gè)高速接口的共存對(duì)PCB設(shè)計(jì)提出了嚴(yán)苛挑戰(zhàn)——信號(hào)完整性、電源噪聲抑制和電磁兼容性(EMC)問(wèn)題相互交織,稍有不慎便...

關(guān)鍵字: SRAM SD卡 USB

2026 年 2 月 2 日,中國(guó)——意法半導(dǎo)體STUSB4531 USB輸電(PD)受電(sink)控制器引入一種新的混合模式,這項(xiàng)專利技術(shù)可簡(jiǎn)化USB PD 選配功能的設(shè)計(jì)開(kāi)發(fā),提升USB供電設(shè)備和USB充電設(shè)備的附...

關(guān)鍵字: 控制器 USB 無(wú)人機(jī)

加拿大魁北克市 — 2026 年 1 月 28日— Robotiq 今日正式發(fā)布 TSF-85 觸覺(jué)傳感指尖,這是專為旗下最受歡迎型號(hào) 2F-85 自適應(yīng)夾爪打造的全新觸覺(jué)傳感解決方案,為具身智能 (Physical A...

關(guān)鍵字: AI 機(jī)器人 USB

【2026年1月27日, 德國(guó)慕尼黑訊】全球功率系統(tǒng)和物聯(lián)網(wǎng)領(lǐng)域的半導(dǎo)體領(lǐng)導(dǎo)者英飛凌科技股份公司(FSE代碼:IFX / OTCQX代碼:IFNNY)近日推出新一代USB 2.0外設(shè)控制器EZ-USB? FX2G3,該產(chǎn)...

關(guān)鍵字: USB 控制器 SCB
關(guān)閉