STM32F407端点
2026-08-17
本文链接为:http://www.usbzh.com/article/detail-1793.html ,欢迎转载,转载请附上本文链接。
端点的初始化
端点的初始化使用DCD_EP_Open函数实现。USB_OTG_EPActivate函数根据对应的配置写寄存器,并使能该端点的中断。
uint32_t DCD_EP_Open(USB_OTG_CORE_HANDLE *pdev , uint8_t ep_addr, uint16_t ep_mps,uint8_t ep_type)
{
USB_OTG_EP *ep;
if ((ep_addr & 0x80) == 0x80)
{
ep = &pdev->dev.in_ep[ep_addr & 0x7F];
}
else
{
ep = &pdev->dev.out_ep[ep_addr & 0x7F];
}
ep->num = ep_addr & 0x7F;
ep->is_in = (0x80 & ep_addr) != 0;
ep->maxpacket = ep_mps;
ep->type = ep_type;
if (ep->is_in)
{
/* Assign a Tx FIFO */
ep->tx_fifo_num = ep->num;
}
/* Set initial data PID. */
if (ep_type == USB_OTG_EP_BULK )
{
ep->data_pid_start = 0;
}
USB_OTG_EPActivate(pdev , ep );
return 0;
}
端点关闭
uint32_t DCD_EP_Close(USB_OTG_CORE_HANDLE *pdev , uint8_t ep_addr)
{
USB_OTG_EP *ep;
if ((ep_addr&0x80) == 0x80)
{
ep = &pdev->dev.in_ep[ep_addr & 0x7F];
}
else
{
ep = &pdev->dev.out_ep[ep_addr & 0x7F];
}
ep->num = ep_addr & 0x7F;
ep->is_in = (0x80 & ep_addr) != 0;
USB_OTG_EPDeactivate(pdev , ep );
return 0;
}
准备接收数据-OUT端点
uint32_t DCD_EP_PrepareRx( USB_OTG_CORE_HANDLE *pdev,
uint8_t ep_addr,
uint8_t *pbuf,
uint16_t buf_len)
{
USB_OTG_EP *ep;
ep = &pdev->dev.out_ep[ep_addr & 0x7F];
/*setup and start the Xfer */
ep->xfer_buff = pbuf;
ep->xfer_len = buf_len;
ep->xfer_count = 0;
ep->is_in = 0;
ep->num = ep_addr & 0x7F;
if (pdev->cfg.dma_enable == 1)
{
ep->dma_addr = (uint32_t)pbuf;
}
if ( ep->num == 0 )
{
USB_OTG_EP0StartXfer(pdev , ep);
}
else
{
USB_OTG_EPStartXfer(pdev, ep );
}
return 0;
}
OUT端点有独立的FIFO,当每个端点有独立的用户缓冲区。
另外端点0和其它端点使用不同的函数,其主要区别在于端点大小不同。
数据发送-IN端点
uint32_t DCD_EP_Tx ( USB_OTG_CORE_HANDLE *pdev,
uint8_t ep_addr,
uint8_t *pbuf,
uint32_t buf_len)
{
USB_OTG_EP *ep;
ep = &pdev->dev.in_ep[ep_addr & 0x7F];
/* Setup and start the Transfer */
ep->is_in = 1;
ep->num = ep_addr & 0x7F;
ep->xfer_buff = pbuf;
ep->dma_addr = (uint32_t)pbuf;
ep->xfer_count = 0;
ep->xfer_len = buf_len;
if ( ep->num == 0 )
{
USB_OTG_EP0StartXfer(pdev , ep);
}
else
{
USB_OTG_EPStartXfer(pdev, ep );
}
return 0;
}
- 对于USB_OTG_EP0StartXfer
| 方向 | xfer_len == 0 |
0 < xfer_len <= maxpacket |
xfer_len > maxpacket |
|---|---|---|---|
| IN(发送) | 发 ZLP(0 长度) | 按实际长度发 | 截断到 maxpacket |
| OUT(接收) | 准备收一包(maxpacket) |
强制 = maxpacket | 强制 = maxpacket |
- USB_OTG_EPStartXfer,都会向上取整数倍包,并不会截断数据包
| xfer_len | maxpacket | IN 公式 | OUT 公式 | 结果 |
|---|---|---|---|---|
| 64 | 64 | 127/64=1 | 127/64=1 | 1 包 |
| 65 | 64 | 128/64=2 | 128/64=2 | 2 包 |
| 100 | 64 | 163/64=2 | 163/64=2 | 2 包 |
端点的STALL和CLEAR STALL
uint32_t DCD_EP_Stall (USB_OTG_CORE_HANDLE *pdev, uint8_t epnum)
{
USB_OTG_EP *ep;
if ((0x80 & epnum) == 0x80)
{
ep = &pdev->dev.in_ep[epnum & 0x7F];
}
else
{
ep = &pdev->dev.out_ep[epnum];
}
ep->is_stall = 1;
ep->num = epnum & 0x7F;
ep->is_in = ((epnum & 0x80) == 0x80);
USB_OTG_EPSetStall(pdev , ep);
return (0);
}
uint32_t DCD_EP_ClrStall (USB_OTG_CORE_HANDLE *pdev, uint8_t epnum)
{
USB_OTG_EP *ep;
if ((0x80 & epnum) == 0x80)
{
ep = &pdev->dev.in_ep[epnum & 0x7F];
}
else
{
ep = &pdev->dev.out_ep[epnum];
}
ep->is_stall = 0;
ep->num = epnum & 0x7F;
ep->is_in = ((epnum & 0x80) == 0x80);
USB_OTG_EPClearStall(pdev , ep);
return (0);
}
本文链接为:http://www.usbzh.com/article/detail-1793.html ,欢迎转载,转载请附上本文链接。
HID人机交互QQ群:564808376
UAC音频QQ群:218581009
UVC相机QQ群:331552032
BOT&UASP大容量存储QQ群:258159197
STC-USB单片机QQ群:315457461
USB技术交流QQ群2:580684376
USB技术交流QQ群:952873936 USB技术交流3:1031974172
STM32-USB





