USB 端点n寄存器(USB_EPnR), n=[0..7],其结构如下图:
CTR_RX: 正确接收标志位,由硬件置位,只能写0。
DTOG_RX: 用于数据接收的数据翻转位,此位应用程序可读可写,但写0无效,写1可以翻转此位。
STAT_RX[1:0]:用于数据接收的状态位,此位用于指示端点当前的状态,这些位也是写0无效,写1翻转
SETUP:SETUP分组传输完成标志位,硬件置位并且只有控制端点才使用。此位应用程序只读。
EP_TPYE[1:0]:端点类型位
EP_KIND:端点特殊类型位
此位的需要和EP_TYPE位配合使用
CTR_TX:正确发送标志位,由硬件置位,只能写0。
DTOG_TX:发送数据翻转位,与DTOG_RX功能类似
STAT_TX[1:0]:用于发送数据的状态位,与STAT_RX功能类似
EA[3:0]:端点地址,应用程序必需设置此4位,在使能一个端点前为它定义一个地址。
初始化步骤
1. 设置端点类型
void SetEPType(uint8_t bEpNum, uint16_t wType)
STM32F103支持8个EP:
#define ENDP0 ((uint8_t)0)
#define ENDP1 ((uint8_t)1)
#define ENDP2 ((uint8_t)2)
#define ENDP3 ((uint8_t)3)
#define ENDP4 ((uint8_t)4)
#define ENDP5 ((uint8_t)5)
#define ENDP6 ((uint8_t)6)
#define ENDP7 ((uint8_t)7)
4种EP类型:
#define EP_BULK (0x0000) /* EndPoint BULK */
#define EP_CONTROL (0x0200) /* EndPoint CONTROL */
#define EP_ISOCHRONOUS (0x0400) /* EndPoint ISOCHRONOUS */
#define EP_INTERRUPT (0x0600) /* EndPoint INTERRUPT */
例如端点0都是EP_CONTROL:
SetEPType(ENDP0, EP_CONTROL);
2. 设置端点的状态,如果是单向,需要把不使用的方向设置为EP_RX_DIS或EP_TX_DIS
void SetEPTxStatus(uint8_t bEpNum, uint16_t wState),对应的宏定义:
#define _SetEPTxStatus(bEpNum,wState) {\
register uint16_t _wRegVal; \
_wRegVal = _GetENDPOINT(bEpNum) & EPTX_DTOGMASK;\
/* toggle first bit ? */ \
if((EPTX_DTOG1 & wState)!= 0) \
_wRegVal ^= EPTX_DTOG1; \
/* toggle second bit ? */ \
if((EPTX_DTOG2 & wState)!= 0) \
_wRegVal ^= EPTX_DTOG2; \
_SetENDPOINT(bEpNum, (_wRegVal | EP_CTR_RX|EP_CTR_TX)); \
} /* _SetEPTxStatus */
注意这些bits是写1翻转,所以写的有点复杂。
3. 设置端点的PMA地址
SetEPRxAddr(ENDP0, ENDP0_RXADDR);
SetEPTxAddr(ENDP0, ENDP0_TXADDR);
4. 设置EP_KIND
Clear_Status_Out(ENDP0); //清除Status Out状态,仅EP0
5. 设置Count值
根据端点的方向设置对应的Count值。
6. 如果是RX,使能端点RX有效
SetEPRxValid(ENDP0);
#define _SetEPRxStatus(bEpNum,wState) {\
register uint16_t _wRegVal; \
\
_wRegVal = _GetENDPOINT(bEpNum) & EPRX_DTOGMASK;\
/* toggle first bit ? */ \
if((EPRX_DTOG1 & wState)!= 0) \
_wRegVal ^= EPRX_DTOG1; \
/* toggle second bit ? */ \
if((EPRX_DTOG2 & wState)!= 0) \
_wRegVal ^= EPRX_DTOG2; \
_SetENDPOINT(bEpNum, (_wRegVal | EP_CTR_RX|EP_CTR_TX)); \
} /* _SetEPRxStatus */
7. 设置EP地址
/* set address in every used endpoint */
for (i = 0; i < nEP; i++)
{
_SetEPAddress((uint8_t)i, (uint8_t)i);
}