STM32 USB HOST CDC 驱动CH340串口

本文主要讲述的是在STM32F407VE板子上通过STMCube生成的USB HOST CDC 程序驱动CH340进行数据传输。

创作背景:

        打算用RT1052开发一个项目,由于项目中用到的传感器比较多,像雷达,ublox等需要通过UART进行通讯,基本分配之后占用了8个串口。而RT1052只有8个串口,没有预留串口也没有调试串口,考虑到RT1052有两路USB-OTG而且内置高速PHY,打算一路用作USB-PC接口做U盘用,一路通过USB-HOST扩展接口,其中包括USB-UART,初步打算先挂载CH340进行通讯测试。

调试过程:

      想法确定之后打算先通过RT1052的管方开发板进行调试,发现不行,问题是“Device not support”,由于对于usb-host的机制不是特别熟悉,而且NXP的资料感觉不如ST多(其他方面不清楚单片机感觉ST资料比较丰富)。于是为了弄清楚问题出在哪里,打算用STM32F407的一个小开发板进行调试,搞清楚机制,看看问题到底出在哪里。

 ST32F407调试:

     步骤一: 通过STM32Cubemx生成一个工程不带操作系统(便于分析),只包括USART1,USBhost_CDC功能。USART1为了 调试打印信息。

     步骤二:通过USBlyzer抓取CH340串口的设备信息,进行对比,查找差异。

     步骤三:调试代码,进行信息对比。

代码分析:

      STM32Cubemx生成的代码主要如下:

       int main()

       {

            MX_USB_HOST_Init();

            while(1)

            {

                  MX_USB_HOST_Process();

            } 

       }

       MX_USB_HOST_Init();  主要包括,初始化US_HOST状态机,注册用户回调函数 USBH_UserProcess();

                                                                注册USBH_CDC_CLASS结构体,也是为了注册回调函数

       MX_USB_HOST_Process(); HOST状态机

      1.HOST_IDLE  状态,等待  USB_DEVICE设备的插入,一旦CH340设备插入,引起中断,中断函处理具体的中断信息

              USBH_StatusTypedef  USBH_LL_Connect(USBH_HandleTypedef* phost)

              {

                     phost->device.is_connected = 1U;

                     ....

              } 

              在USBH_Process()  状态机HOST_IDLE中检测到插入

              if( phost->device.is_connected) 

             {

                      phost->gState= HOST_DEV_WAIT_FOR_ATTACHMENT;  //进行入下一个状态

              }

     2. HOST_WAIT_FOR_ATTACHMENT等待接入

         中断处理  void USBH_LL_PortEnabled(USBH_HandleTypedef *phost)

                           {

                                   phost->device.PortEnalbed = 1U;

                           }

           然后 phost->gState = HOST_DEV_ATTACHED; //进入下一个状态设备接入

     3. HOST_DEV_ATTACHED

            if(phost->pUser !=NULL)

            {

                 phost->pUser(phost, HOST_USER_CONNECTED);  //如果初始化注册用户函数,则调用用户处理

             }

            等待100ms的复位,主要是为了电路稳定。分配pip_out pip_in的端点,默认使用 USBH_EP_CONTROL  0

    4. HOST_ENUMMERATION  进入设备枚举阶段

           status = USBH_HandleEnum(phost);  这个函数是枚举状态机,逐个分析。

             设备枚举阶段:

                         (1) ENUM_IDLE

                                       ReqStatus = USBH_Get_DevDesc(phost,8)默认采用8字节,获取设备描述符信息

                                        然后调用 USBH_GetDescriptor() 函数,这个函数继续调用 USBH_CtlReq()函数

                                        这个是控制请求函数,具体处理通过 USBH_HandleControl()是个状态机,这是具体数据的发送和接收                                          处理,具体不描述,可以理解为,数据请求发送了,然后等待数据接收即可。

                                      USBH_ParseDevDesc(); 发送完数据,收到数据进行解析,这里开始处理设备描述符

                                       由于第一次只接收到8个字节,解析后如下:

                                       

                         (2)ENUM_GET_FULL_DEV_DES

                                       这次获取全部信息

                                      

 

                                          下图是PC 通过USBlyzer获取的信息

                                                       

                            这个有个地方需要注意 就是  bDeviceClass  0xFF  Verdor-specfic 等会解释

                        (3)ENUM_SET_ADDR

                                   这里程序进行设置地址,我没有理会,默认ok

                                   根据实际size重新设定 端点信息。

                         (4) ENUM_GET_CFG_DESC  ,(5)ENUM_GET_FULL_CFG_GESC获取配置描述符

                                       USBH_Get_CfgDesc(phost, ...);   

                                          

                                   PC获取的配置信息

                                            

                          (6)ENUM_GET_MFC_STRING_DESC,ENUM_GET_PRODUCT_STRING_DESC,获取不到,不影响

                          (7)ENUM_GET_SERIALNUM_STRING_DESC:

                                   获取到USB-2.0Serial

                          (8)ENUM_GET_SERIALNUM_STRING_DESC:

                                     N/A

                            到此,枚举结束。

    5.进入HOST_SET_CONFIGURATION

    6.进入HOST_SET_WAKUP_FEATURE

            这里显示失败,但是我没有关注继续,HOST_CHECK_CLASS

    7. HOST_CHECK_CLASS

           这里是关键,一开始usbhost初始化的时候注册的是USBH_CDC_CLASS类,这个结构体中初始化的ClassCode是

          USB_CDC_CLASS这个数值等于2,但是刚才我获取的 bDeviceClass 是 0xFF,PC显示厂商自定义设备。

          所以在这里我增加一个宏定义USB_CDC_CLASS_CH340   0xFF,初始化,USBH_CDC_CLASS,

          这样 程序  phost-pActiveClass  = phost-pClass[idx]能够执行,能获指向USBH_CDC_CLASS这个注册类。

         接下来执行初始化,phost-pActiveClass->Init(pHost),  之后  phost->gState = HOST_CLASS_REQUEST;

          调用USBH_CDC_InterfaceInit( phost)  这里需要注意

        USBH_FindInterface,这个函数是根据第2,3,4个参数

          COMMUNICATION_INTERFACE_CLASS_CODE,   0X02

           ABSTRACT_CONTROL,     0X02

           COMMON_AT_COMMAND   0X01,

          进入程序发现  if( (pif->bInterfaceClass == class) || (Class == 0xFFU)) &&

                                     (pif->bInterfaceSubClass==SubClass)|| (SubClass == 0xFFU)) &&

                                     .......)

            这里3个参数都不匹配,因为程序是根据CDC进行查找的,而CH340的 class =  0xFF, SubClass = 0x01, Protocol = 0x02

          所以增加宏定义增加CH340对应的数值,之后pip配置就设置完成。

    8.HOST_CLASS_REQUEST

          这里请求的时候失败,我觉得是发送具体信息的问题,由于具体发送什么我需要查资料,暂时不理会,直接

           status = USBH_OK然后  phost->gState = HOST_CLASS跳转执行

          默认是19200波特率

    9. HOST_CLASS

           phost->pActiveClass->BgndProcess(phost);  调用USBH_CDC_CLASS的函数

         USBH_CDC_Process()这时一直处于IDLE状态,等待设定参数或者收发数据。

   10.数据收发

         在数函数中调用   USBH_CDC_Transmit(&hUsbHostFS,Sendbuf, 32);

         然后不断调用 USBH_CDC_Receive进行数据解析。实际验证可以收发。

         程序中主函数没有详细处理,直接自发自收的。

         

结论:

        第一次写文,不太会把文章格式排版的很好,希望理解,另外没有赋值粘贴,纯手打,难免有错误的地方,希望原谅。

       源码链接: https://download.csdn.net/download/k1542308627/12602318

       

          

          

     

                       

             

 

          

    

     

  • 8
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 23
    评论
对于使用STM32F103RCT6与CH340串口驱动的问题,你可以按照以下步骤进行操作: 1. 确保你已经安装了CH340串口驱动程序。你可以从CH340官方网站或者相关的硬件供应商网站上下载并安装驱动程序。 2. 在STM32F103RCT6上选择一个可用的串口,比如USART1或者USART2。根据你的需要选择合适的串口。 3. 配置串口的引脚。根据STM32F103RCT6的引脚映射表,将串口的引脚连接到相应的引脚上。比如,如果你选择了USART1,那么你需要将USART1的TX和RX引脚连接CH340的TX和RX引脚上。 4. 在STM32F103RCT6上配置串口的时钟。根据你选择的串口,配置相应的时钟使能位和时钟分频值。 5. 在STM32F103RCT6上配置串口的参数,比如波特率、数据位、停止位和校验位。根据你的需求,选择合适的参数进行配置。 6. 初始化串口,并开启相应的中断(如果需要)。在你的代码中,使用相应的函数来初始化串口,并开启接收和发送中断(如果需要)。 7. 编写接收和发送数据的代码。根据你的需求,使用相应的函数来接收和发送数据。 8. 编译、下载并运行你的代码。使用适当的编译工具将你的代码编译为可执行文件,然后下载到STM32F103RCT6上进行测试。 以上是一般的串口驱动步骤,你需要根据具体的需求和硬件连接进行相应的配置和编码。希望对你有所帮助!如果你还有其他问题,可以继续提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值