EC800M STM32F407 USB FS驱动调试

本文详细介绍了如何使用STM32的USBHost功能,配合Cubemx库驱动EC800M虚拟串口(CDC)进行AT通信,包括设置USB配置、修改源码、USB连接流程以及数据收发过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

注:本文档主要用于stm32做usb fs主机时,将EC800M虚拟串口(CDC)接入进行AT通信使用

参考文档:

使用stm32cubemx的usb-host-cdc库驱动EC20模块_stm32 ec20 usb-CSDN博客

使用stm32cubeide的usb-host-cdc库驱动EC20模块_ec20 stm32_郑州-刘明鑫的博客-CSDN博客

STM32 USB HOST CDC 驱动CH340串口_stm32 otg host com-CSDN博客

一、使用mx cube创建usb host工程

1、设置USB频率为48MHz

2、USB_OTG_FS, 选择 Host_Only,别的不用动

选择 Middleware 标签下的USB_HOST

Class For FS IP 选择图示选项 Communication Host Class (Virtual Port com)

USBH_MAX_NUM_ENP… 3

USBH_MAX_NUM_INTER… 5

USBH_MAX_NUM_SUPP… 1

USBH_MAX_NUM_CONF… 4

二、修改源码

说明:11、ST USB HOST概述_st freertos usb host驱动-CSDN博客

1、修改接口类型代码(CDC CLASS)

找到usbh_cdc.h,第53行,修改为0xFFU

2、修改CDC使用的interface和对应的endpoint

/*

* 注:

* cubemx生成的例程中,标准的CDC类设备,1个配置描述符中需要2接口

* 其中一个为Communication Interface Class, 该接口需要一个方向为in的Ep

* 另外一个为Data Interface Class, 该接口需要一个方向为in的Ep和一个方向为out的Ep

* 所以USBH_CDC_InterfaceInit函数,调用了两次USBH_FindInterface函数

* 查找两个匹配的Interface, 分别进行配置

*

* USB-TTL串口工具,debug状态下查询设备描述符结构体中,只有一个接口

* 但是该接口拥有3个Ep, 2个方向为in, 1个方向为out.

* 由此猜测,串口工具并没有将Interface分开

* 经测试, Communication Interface使用的Ep为2, Data Interface使用Ep0,1

*

* Ec20模块,可以读到5个Interface,但是只有Interface 1 2 3 有3个Ep,0 和 4 只有2个Ep

* 经测试,接口AT指令的串口Interface为 2.

* Interface 2中,Communication Interface使用的Ep为0

* Data Interface使用的Ep为1 和 2

*/

① 找到usbh_cdc.c,第158行修改部分如图所示

注:根据实际情况修改,当endpoint为3时为需要的点位

EC800M为最后一个点位。

② 还是 usbh_cdc.c,注释掉 interface = …这两行,然后将图中画红色框框部分的5个Ep_Desc[0]修改为 Ep_Desc[2]

注:EC800G的AT口只有2个endpoint,目前暂未找到如何配置的方法

③ 修改usbh_core.c中此处,修改为3个endpoint的点位位置

3、修改AT通信串口波特率

usbh_cdc.c,找到函数 USBH_CDC_ClassRequest,按如图所示修改。

4、修改USB CDC接收完成回调函数

usb_host.c,在 USER CODE BEGIN 0 部分添加如下代码

5、在MX_USB_HOST_Process函数中循环调用CDC receive函数进行数据接收

6、添加USB CDC发送数据

当设备连接成功并动作后,发送AT命令等待EC800G模块回复

三、USB连接流程

1、MX_USB_HOST_Init()

主要包括,初始化US_HOST状态机,注册用户回调函数 USBH_UserProcess();注册USBH_CDC_CLASS结构体,也是为了注册回调函数

2、MX_USB_HOST_Process()

usb host状态机切换

① HOST_IDLE状态

等待USB_DEVICE设备的插入,一旦设备插入,引起中断,中断函处理具体的中断信息

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; //进行入下一个状态 }

② HOST_WAIT_FOR_ATTACHMENT等待接入

中断处理 void USBH_LL_PortEnabled(USBH_HandleTypedef *phost) { phost->device.PortEnalbed = 1U; } 然后 phost->gState = HOST_DEV_ATTACHED; //进入下一个状态设备接入

③ HOST_DEV_ATTACHED

if(phost->pUser !=NULL) { phost->pUser(phost, HOST_USER_CONNECTED); //如果初始化注册用户函数,则调用用户处理 } 等待100ms的复位,主要是为了电路稳定。分配pip_out pip_in的端点,默认使用 USBH_EP_CONTROL 0

④ HOST_ENUMMERATION 进入设备枚举阶段

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

设备枚举阶段:

(1) ENUM_IDLE

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

然后调用 USBH_GetDescriptor() 函数,接着继续调用 USBH_CtlReq()函数

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:

到此,枚举结束。

⑤ HOST_SET_CONFIGURATION

⑥ HOST_SET_WAKUP_FEATURE

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

⑦ 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配置就设置完成。

⑧ HOST_CLASS_REQUEST

这里请求的时候失败,我觉得是发送具体信息的问题,由于具体发送什么我需要查资料,暂时不理会,直接 status = USBH_OK然后 phost->gState = HOST_CLASS跳转执行 默认是19200波特率

⑨ HOST_CLASS

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

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

3、数据收发

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

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

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

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值