最近在使用STM32的USB模塊開發個項目,還以為挺簡單,結果搞了快兩天才把USB的包緩沖區的訪問搞定,在此做個小總結吧。
STM32的USB模塊包緩沖區有512B,但是在STM32的參考手冊中的存儲器映像中卻表明0x40006000-0x400063ff,整整多了512B,怎么會這樣呢,同時在嘗試著編程時也遇到了一個問題:
在usb_core.c文件的Setup0_Process(void)這個函數中,有這么一段:
uint16_t offset = 1;
if (pInformation->ControlState != PAUSE)
{
pInformation->USBbmRequestType = *pBuf.b++; /* bmRequestType */
pInformation->USBbRequest = *pBuf.b++; /* bRequest */
pBuf.w += offset; /* word not accessed because of 32 bits addressing */
pInformation->USBwValue = ByteSwap(*pBuf.w++); /* wValue */
pBuf.w += offset; /* word not accessed because of 32 bits addressing */
pInformation->USBwIndex = ByteSwap(*pBuf.w++); /* wIndex */
pBuf.w += offset; /* word not accessed because of 32 bits addressing */
pInformation->USBwLength = *pBuf.w; /* wLength */
}
這其中又不太明白為什么需要pBuf.w += offset;而且后面的解釋也不太懂 /* word not accessed because of 32 bits addressing */
,我于是在這段之前加入調試以顯示收到什么數
#ifdef DEBUG
UARTSend_String("*** 端點0收到SETUP數據 ***rn");
for(offset=0;offset<16;offset++)
{
UARTSend_Hex(*pBuf.b++);
}
#endif
結果串口調試顯示如下:
*** USB總線復位 ***
*** USB總線CTR置位 ***
*** 進入端點0 ***
*** 端點0收到SETUP包 ***
*** 端點0收到SETUP數據 ***
0x80 0x06 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x40 0x00 0x00 0x00
本來應該顯示0x80 0x06 0x00 0x01 0x00 0x000x40 0x00才對,不太明白怎么0x80 0x06和0x00 0x01 后面多了兩個 0x00 ,難道USB模塊還會將收到的數據跳著放嗎?
后來反復看參考手冊,問了些人,才知道原來STM32的USB緩沖區是一個雙端口的RAM,CPU一端需要使用32位方式訪問,但USB模塊一端使用16位方式訪問。也就是說每個USB模塊中的地址*2才能對應到控制器中的實際地址,這樣每四個字節地址空間后兩個字節地址空間是空的。所以上面串口調試顯示的數據每正確兩個字節就會多出兩個字節的0x00。
這里也對STM32的USB庫函數中對緩沖區的操作函數做個說明:
在usb_men.c文件有這么一個函數
void PMAToUserBufferCopy(uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
uint32_t n = (wNBytes + 1) >> 1;/* /2*/
uint32_t i;
uint32_t *pdwVal;
pdwVal = (uint32_t *)(wPMABufAddr * 2 + PMAAddr);
for (i = n; i != 0; i--)
{
*(uint16_t*)pbUsrBuf++ = *pdwVal++;
pbUsrBuf++;
}
它的作用是將緩沖區中的數據拷貝到你所定義的uint8_t Receive_Buffer[];數組中。其它地方都好理解,這里說說
pdwVal = (uint32_t *)(wPMABufAddr * 2 + PMAAddr);
for (i = n; i != 0; i--)
{
*(uint16_t*)pbUsrBuf++ = *pdwVal++;
pbUsrBuf++;
}
首先是pdwVal = (uint32_t *)(wPMABufAddr * 2 + PMAAddr);這里wPMABufAddr * 2之所以要*2就是前面所述的USB模塊中的地址*2才能對應到控制器中的實際地址,在取得對應端點的緩沖區首地址后,將其(uint32_t*)強制指向uint32_t型,這樣每次*pdwVal++,pdwVal的地址都增加4個字節,并且每次都會有四個字節的數據讀出。
在for循環中,*(uint16_t*)pbUsrBuf++ = *pdwVal++;這句重點說說,++與指針*同優先級,結合順序為至右向左結合,因此相當于*((uint16_t*)pbUsrBuf++),先*(uint16_t*)pbUsrBuf賦值只取*pdwVal++的32位數據的前16位,然后再將pbUsrBuf加上1個字節。到這里,前面定義的uint8_tReceive_Buffer[];數組中就有兩個數組變量被賦值了,但這時地址還指增加一個字節,因此還需要pbUsrBuf++;讓其指向Receive_Buffer[];的下下個數組變量。一次循環,知道讀出所有數據。
上一篇:stm32 usb數據緩沖區疑問
下一篇:關于stm32的USB學習筆記之USB_HW.c
推薦閱讀
史海拾趣
隨著業務的不斷擴展,Belden公司于1910年搬遷至芝加哥更大的區域,并在產品線上增加了橡膠絕緣電線。這一舉措不僅擴大了公司的生產規模,也進一步豐富了產品種類,滿足了市場的多樣化需求。隨后,百通工程師于1927年發明的軟橡膠塞技術,進一步推動了公司的技術創新和業務拓展。
品質一直是EICHHOFF公司發展的核心競爭力。為了確保產品質量的穩定性和可靠性,公司建立了一套完善的質量管理體系,并持續進行改進和優化。從原材料采購到生產加工、從產品檢測到售后服務,每一個環節都嚴格按照質量管理體系的要求進行。
此外,EICHHOFF公司還積極引入國際先進的品質管理工具和方法,如六西格瑪、精益生產等,以進一步提高產品質量和生產效率。這些努力使得EICHHOFF的產品在行業中享有很高的聲譽和信譽。
DIOTECH公司成立于電子行業的黃金時期,憑借其創始人在半導體領域的深厚造詣,公司迅速在高性能處理器領域取得了技術突破。通過不斷優化產品設計和生產工藝,DIOTECH的產品在性能和穩定性上均達到了行業領先水平,逐漸贏得了市場的認可。隨著智能手機的普及,DIOTECH的高性能處理器成為了市場上的搶手貨,公司的營收和市場份額均實現了快速增長。
憑借優質的產品和服務,B&F Fastener Supply公司逐漸贏得了大型電子廠商的青睞。多家知名電子企業選擇與B&F建立長期合作關系,將其作為緊固件和電子元器件的主要供應商。這不僅為B&F帶來了穩定的訂單和收入來源,還進一步提升了公司在電子行業的地位和影響力。
在競爭激烈的電子行業中,APSA公司始終保持對技術的敏銳洞察和持續創新。公司不斷投入研發資金,引進先進的技術和設備,推動產品升級換代。通過不斷創新和技術升級,公司成功保持了市場領先地位。
近年來,電子行業正經歷著深刻的變革,傳統半導體市場逐漸飽和,新興領域如物聯網、人工智能等蓬勃發展。面對這一行業變革,AE&ST公司果斷進行轉型升級。公司調整戰略方向,加大在新興領域的研發投入,同時優化生產流程,降低成本。通過一系列的改革措施,AE&ST公司成功實現了從傳統半導體制造商向新興技術領域的轉型。
關鍵字:網絡攝像機 1.什么是網絡攝像機? 答:在裝有網絡攝像機的遠處通過因特網進行遠程監視的網絡統合管理、儲存影像。是將網絡服務器、控制軟件( TCP/UDP)和電子郵件等功能集于一體的網絡設備。 2.網絡攝像機與普通的可視 ...… 查看全部問答∨ |
本文轉自 越測越開心 的博客,其原文地址如下: http://forum.eet-cn.com/BLOG_ARTICLE_2670.HTM 本系列博文由我們的老用戶H3C北京公司常羽飛特別供稿 (2)讓我一眼看穿你的心肝脾肺腎你準備測一個信號,這個信號很重要,你想對它有個全面 ...… 查看全部問答∨ |
目前移植samba到mips中,現在用smbclient已經可以看到windows中的共享的目錄,但是用smbmount去將目錄掛在到系統中時,提示沒有目錄,具體信息如下: # smbclient -L //192.168.1.188 load_client_codepage: filename /usr/samba/lib/codepages/c ...… 查看全部問答∨ |
用pci插槽擴展出來的并口能否用于單片機試驗版的下載,如題! 買了一塊單片機試驗版,89s52,使用的是并口的下載線,可是主板上沒有并口,欲買一塊擴展卡,不知是否可行… 查看全部問答∨ |
我手里有個周立功2132的arm7板子,今天做GPIO輸出實驗-單路LCD控制,用的是LPC2000 Flash Utility2.2.1(philips),但是不能讀ID,請問是怎么回事?我是菜鳥,請大家告訴以下!!!!!!… 查看全部問答∨ |
有兩種控制LED亮度的方法.一種是改變流過LED的電流,一般LED管允許連續工作電流在20毫安左右,除了紅色LED有飽和現象外,其它LED亮度基本上與流過的電流成比例;另一種方法是利用人眼的視覺惰性,用脈寬調制方法來實現灰度控制,也就是周期性改變光脈沖寬 ...… 查看全部問答∨ |
2440的板,一般開機后顯示都很正常,但偶爾開機后,顯示會整體向上或向下偏移個20-50行左右.我們的產品要經過高溫老化,在50.c的爐里跑兩天,這個時候最容易發生這情況。 請問有遇到過同樣情況的兄弟嗎? 這個是因為我驅動參數設置的不好嗎?還是 ...… 查看全部問答∨ |
目前只完成了賦值語句以及遞增、遞減語句功能。 源程序1:#include <stm8s903k3.h> long *p; long *pp; foo() { char a = PA_DDR; int n; long m; a++; n += 0x100; m -= 0x001201; & ...… 查看全部問答∨ |
為什么在程序中加了math頭文件后,程序還是識別不了里面的庫函數,例如sinf。急急.... 本人是新手,接觸VxWorks時間不長。本人在Tornado的開發環境中編譯沒有任何問題。單下載到DSP上就報錯 說無法識別math里面的庫函數。程序中也加了頭文件,不知問題出在哪里,還請各位大神幫幫忙。很急很急。… 查看全部問答∨ |