闫刚 stm32的usb的hal软件架构原理讲解

资源

stm32_usb_cubemx.md
闫刚 stm32的usb的hal软件架构原理讲解

一. usb基础

stm32的usb也是很多公司都在使用的接口,usb全速可以达到12M/s, 作为虚拟串口接口,还是不错的.usb整个协议还是很复杂的,整理了下我这几年对usb的使用,讲解下usb软件架构,和一些重要的知识点

二. cubemx生成usb虚拟串口的demo工程

usb_vcp_demo仓库链接

下载仓库:

git clone https://github.com/yangang123/usb_vcp_demo.git

2.1 步骤:

  1. 选择板子是stm32f4 discovery
  2. 选择外部晶振
  3. 设置系统时钟是168MHz
  4. 设置USB是device
  5. 设置USB的从设备的类是vcp
  6. 设置堆栈是0x600[注意]
  7. 设置复位
  8. 查看端口
  9. 查看结果

1. 选择板子是stm32f4 discovery

2. 选择外部晶振

3. 设置系统时钟是168MHz

4. 设置USB是device

5. 设置USB的从设备的类是vcp

6. 设置堆栈是0x600

7. 设置复位

8. 查看端口

9. 查看结果

2.2 测试工作:

PC : WIN10
软件:友善之臂串口助手
Keil: MDK5
单板:stm32f4 discory

2.3 测试过程:

  1. KEIL中要设置下载完成后,自动复位
  2. 在电脑上查看COM口是哪个
  3. 程序中每秒发送1个字符’a’,
  4. 串口助手每秒发送1个字符’a’

整个工程保存已经提交到了github中

地址:

三. 如何处理发送和接收

接收和发送的接口都是usbd_cdc_if.c中

3.1 数据缓冲大小配置是下面

#define APP_RX_DATA_SIZE  4
#define APP_TX_DATA_SIZE  4

3.2 发送数据

发送数据用下面这个api接可以了
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
下面是1s周期发送"a"数据

HAL_Delay(1000);
char *string = "a";
CDC_Transmit_FS((uint8_t*)string, 1);

3.3 接收数据

接收缓冲区会用到 uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];
接收数据的长度 int recv_len = 0;
接收数据的接口是 static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len), 接收数据

static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{ 
  recv_len = *Len;
  USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
  USBD_CDC_ReceivePacket(&hUsbDeviceFS);
  return (USBD_OK);
}

四. 发送和接收原理

层次功能主要文件
APP应用层usbd_cdc_if.c
calss不同的设备不同的数据usb_cdc.c
coreUSB数据缓冲的处理usb_core.c
HAL硬件中断处理stm32f4_ll_usb.c

4.1 发送数据

USB_EPStartXfer: 启动一个端点传输
USBx_INEP: 使能EP
USB_WritePacket:数据写入fifo

CDC_Transmit_FS((uint8_t*)string, 15); 
    -> USBD_CDC_TransmitPacket(&hUsbDeviceFS);
        ->   USBD_LL_Transmit(pdev,  CDC_IN_EP, hcdc->TxBuffer,hcdc->TxLength);
            ->   hal_status = HAL_PCD_EP_Transmit(pdev->pData, ep_addr, pbuf, size);
                -> HAL_StatusTypeDef USB_EPStartXfer(USB_OTG_GlobalTypeDef *USBx , USB_OTG_EPTypeDef *ep, uint8_t dma)
                    ->USBx_INEP(ep->num)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
                    ->USB_WritePacket(USBx, ep->xfer_buff, ep->num, ep->xfer_len, dma);

4.2 接收数据

HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS);
    -> HAL_PCD_DataOutStageCallback(hpcd, epnum);
        -> USBD_LL_DataOutStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->OUT_ep[epnum].xfer_buff);
            -> pdev->pClass->DataOut(pdev, epnum); 
                ->  ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Receive(hcdc->RxBuffer, &hcdc->RxLength);

4.2.1 接口 DataOut

接口结构体

  typedef struct _Dev   ice_cb{
  uint8_t  (*DataOut)(struct _USBD_HandleTypeDef *pdev , uint8_t epnum); 

注册DataOut这个接口

USBD_ClassTypeDef  USBD_CDC = {
  USBD_CDC_DataOut,

4.2.2 接口 Receive

接口结构体

typedef struct _USBD_CDC_Itf
{
  int8_t (* Init)          (void);
  int8_t (* DeInit)        (void);
  int8_t (* Control)       (uint8_t, uint8_t * , uint16_t);   
  int8_t (* Receive)       (uint8_t *, uint32_t *);  
}USBD_CDC_ItfTypeDef;

注册(* Receive)这个接口函数

USBD_CDC_ItfTypeDef USBD_Interface_fops_FS = 
{
  CDC_Init_FS,
  CDC_DeInit_FS,
  CDC_Control_FS,  
  CDC_Receive_FS
};
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值