|
天有空,開貼講講,怎樣配合 ST提供的庫函數(shù)理解 STM32F102/103的USB模塊,以及怎么調(diào)用這些庫函數(shù)來實現(xiàn)基本的USB通信。
題目很大,先只講講最簡單的應(yīng)用。
1
關(guān)于512字節(jié)的Packet Buffer
在STM32F103的USB模塊中有一個RAM區(qū),稱為PacketBuffer,共有512字節(jié)。
SB模塊中有個BufferDescriptionTable,這個Table位于512字節(jié)的PacketBuffer中,可以在PacketBuffer的任意位置。
USB模塊提供一個寄存器USB_BTABLE來設(shè)置BufferDescriptionTable在Packet
uffer的偏移地址。
在庫函數(shù)中, Define了這個偏移地址:
usb_conf.h:
#defineBTABLE_ADDRESS (0x00)
這意味著 Buffer Description Table位于 Packet Buffer的首地址
Buffer DescriptionTable中的,是所用到的端點的緩存區(qū)地址寄存器和緩存區(qū)長度寄存器。所有用到的端點的這兩個寄存器都位于這個Table中。
如上所說, 由于這個 Table位于 Packet Buffer的首地址。 所以端點 0的發(fā)送緩沖區(qū)地址寄存器就位于 Packet Buffer的首地址, 緊接的是端點0發(fā)送緩沖區(qū)長度寄存器, 接著的是端點0接收緩存區(qū)的地址寄存器, 跟著是端點0的接收緩存區(qū)的長度寄存器, 等等等等, 一直到最后一個端點8的接收緩存區(qū)的長度寄存器。
每個端點的一個方向有 2個寄存器, 共8個端點 16個方向, 一共32個寄存器, 每個寄存器為4個字節(jié),所以這個 Table一共占有128字節(jié)
端點 0發(fā)送緩存區(qū)的地址寄存器中的值,是端點 0發(fā)送緩存區(qū)在 Packet Buffer中的偏移地址。而端點 0接收緩存區(qū)的地址寄存器中的值, 是端點 0接收緩存區(qū)在Packet Buffer中的偏移地址。
如前所說, Buffer Description Table從理論上占有 128個字節(jié)。但對于具體的應(yīng)用,不是每個應(yīng)用都會用到 8個端點的 16個方向的。所以,對于那些沒有用到的端點寄存器,我們可以不考慮為他們預(yù)留位置。
在ST提供的例程中,通常這么定義
define BTABLE_ADDRESS (0x00)
/* EP0 */
/* rx/tx buffer base address */
#define ENDP0_RXADDR (0x18)
#define ENDP0_TXADDR (0x58)
這 3句定義,意味著:
1, 端點 0的接收緩存區(qū)位于 Packet Buffer的 0x18地址。
2, 端點 0的發(fā)送緩存區(qū)位于 Packet Buffer的 0x58地址。
3, Buffer Description Table 位于 Packet Buffer的前 24字節(jié)。 24個字節(jié)意味著
應(yīng)用需要使用6個寄存器,即 3個端點。
4, 端點 0的接收緩存區(qū)長度為64字節(jié)
了,關(guān)于這個PacketBuffer講解完畢。
要做一個USB應(yīng)用,第一步就是要根據(jù)應(yīng)用合理的分配好這個PacketBuffer。
出個題目給大家做做
假設(shè), 需要使用端點0的IN,OUT傳輸, 端點長度為8字節(jié), 端點1的IN傳輸, 長度為16字節(jié)。端點2的OUT傳輸,長度為64字節(jié)。端點2的IN傳輸,長度為64字節(jié)。
該怎么分配這個PacketBuffer?
2 使用STM32F102/103USB函數(shù)庫 進行USB通信
第一步:
根據(jù)應(yīng)用的需求,定義使用到的端點數(shù)量
usb_conf.h
#define EP_NUM(3)
上意味著應(yīng)用需要使用到EP0, EP1和EP2
第二步:
初始化每個使用到的端點
usb_prop.c
SetEPType(ENDP2,EP_INTERRUPT);
定義端點2為中斷端點
SetEPTxAddr(ENDP2,ENDP2_TXADDR);
如果需要進行EP2IN通信,需要定義端點 2的發(fā)送緩存區(qū)的地址,也就是在PacketBuffer
中的偏移地址
SetEPRxAddr(ENDP2,ENDP2_RXADDR);
如果需要進行EP2OUT通信,需要定義端點2的接收緩存區(qū)在PacketBuffer中的偏移地址
SetEPRxStatus(ENDP2,EP_RX_NAK);
設(shè)置端點2的接收狀態(tài)為NAK,設(shè)備將以NAK來響應(yīng)主機發(fā)起的所有OUT通信。
SetEPTxStatus(ENDP2,EP_TX_NAK);
設(shè)置端點2的發(fā)送狀態(tài)為NAK,設(shè)備將以NAK來響應(yīng)主機發(fā)起的所有IN通信。
第三步:
使能端點的通信
對于IN端點的使能:
UserToPMABufferCopy(Send_Buffer,ENDP2_TXADDR,8);
拷貝用戶數(shù)據(jù)到端點2的發(fā)送緩存區(qū)
SetEPTxCount(ENDP2,8);
設(shè)置端點2發(fā)送數(shù)據(jù)長度
SetEPTxValid(ENDP2);
設(shè)置端點2的發(fā)送狀態(tài)為VALID
以上三句可以在應(yīng)用代碼的任意位置調(diào)用,一旦調(diào)用,即使能了一次USBIN通信。
USB設(shè)備將在收到主機的 INTOKEN后,自動發(fā)送緩存區(qū)中的數(shù)據(jù)到主機,并在發(fā)送完畢
后產(chǎn)生EP2_IN_Callback中斷,同時將端點2的發(fā)送狀態(tài)自動改為NAK。
如果需要再次進行數(shù)據(jù)傳送,需要再次調(diào)用以上的三句函數(shù)。
對于OUT端點的使能:
SetEPRxValid(ENDP2);
設(shè)置端點2的接收狀態(tài)為VALID。
以上的這句函數(shù)即使能了端點2的OUT通信,可以在任意位置調(diào)用。
一旦調(diào)用,即使能了一次OUT通信。 USB設(shè)備將以 ACK來響應(yīng)主機隨后的OUT通信,并
在接收數(shù)據(jù)完畢后, 產(chǎn)生EP2_OUT_Callback中斷, 同時自動將端點的接收狀態(tài)改為NAK。
在EP2_OUT_Callback中斷函數(shù)中調(diào)用
USB_SIL_Read(EP2_OUT,Receive_Buffer);
可以將端點2接收緩存區(qū)中收到的數(shù)據(jù)拷貝到用戶數(shù)據(jù)區(qū)
|
評分
-
查看全部評分
|