1、客户需求
客户使用 STM32H563 开发产品,需要 USB CDC ACM 虚拟串口的工程,并且要求不使用 PD 功能,而我们 STM32CubeH5 代码库中是包含 PD 功能的工程。于是协助客户解决这个问题,提供给客户不带 PD 功能的虚拟串口工程。
在 STM32CubeMX 软件中,选择 ThreadX USBX 模块完成 USB CDC ACM 虚拟串口的工程,并且不使能 PD 功能。
2、基本硬件和 STM32CubeMX 的配置
硬件方面使用客户开发板和 NUCLEO_H563ZI 同时来进行软件开发。
由于不使用 PD 功能,需要对 NUCLEO_H563ZI 的电路进行改动,在开发板上PA11,PA12 连接到了使用 PD 功能的 Type-C 接口,因此需要做如下的硬件修改:需要把 SB27、 SB28 上的两个小电阻换移到 SB22、SB21 的位置,这样做是把PA11、PA12 连接到开发板的 CN12 上,然后就可以接 USB 线了。
USB 连接线需要接 GND、D+、D-;在对 NUCLEO_H563ZI 开发板的调试中,VBUS没有连接起来,但客户开发板的设计中是需要连接的。以此来告诉 USB Device 端(STM32H563ZI)的软件工程,USB 线连接到 PC 上了。
3、对工程进行完善和修改
由于 CubeMX 的生成的代码有限,生成软件工程后需要对工程进行完善,具体改动如下:
代码开发的第一步是将 ST HAL USB 驱动程序与 USBX 固件连接起来,然后初始化 USB 外设。还需要添加一下必要的代码,下面蓝色部分为需要添加的,绿色部分是生成的代码,你可以搜索绿色部分快捷收到需要添加的位置,第一步: 在“app_usbx_device.h”添加必须包含的头文件和需要用到的函数声明。
第二步: 在“app_usbx_device.c”添加需要用到的变量和函数声明。
第三步:在 app_ux_device_thread_entry 函数中,添加链接驱动程序和初始化 USB 外设的代码。
先调用 MX_USB_PCD_Init()来初始化 USB 外设; 然后使用 HAL_PCDEx_PMAConfig(…)进行配置, 该函数为 STM32H563 配置专用 USB RAM 内存中的 PMA(packet memory area), 在本例中,端点为 0 IN/OUT ( USB 标准控制端点)、端点 3 OUT (CDC 数据输出点)、端点 1 IN (CDC 数据输入端点)和控制端点 2 IN ( CDC 命令端点)。PCD_SNG_BUF 参数意味着我们为端点使用单个缓冲区,这是必要的,因为我们在双向模式下使用端点。最后,该函数的最后一个参数是 PMA 地址,缓冲区大小为 64Bytes。
使用内存的第一个地址来存储 BTABLE,它是端点缓冲区的地址列表。BTABLE 为每个端点存储8 个字节。由于 STM32H563 有 8 个端点,因此它最多可以消耗 64 字节。
在本例中,我们使用从 0 到 3 的端点,因此可以不使用剩余的其余部分。如果需要可以减少 TXEp 0 缓冲区的偏移量,优化内存的使用。但是,按照这个表,您可以毫无问题地分配所有 8 个端点缓冲区。
CDC 类的配置描述符一般包含一个接口 0(Interface 0),一个控制接口,另外一个是数据接口(Interface 1), 除此之外, IAD(Interface Association Description),这个是可选的,根据实际情况来确定是否需要。
下一个调用的函数是 ux_dcd_stm32_initialize(…),它负责将 HAL USB 驱动程序链接到 USBX 应用程序。最后,我们调用 HAL_PCD_Start(..)来启动 USB PCD 外设。
第四步:在 app_usbx_device.c 中 MX_USBX_Device_Init(…)函数的最后用户代码部分,创建两个线程来处理数据的写和读,以及一个消息句柄,具体的代码如下:最后一个参数为 TX_DONT_START,意思是任务先挂起,之后再启动。
第五步:下面的 usb_connect()函数是根据客户需要设计的。在 PC 端连接到设备端STM32H563,VBUS 连接时触发中断后调用的函数(客户产品中把 VBUS 分压后连接到一个 GPIO口,由于客户第一版本的 PCB 没有设计这部分电路,因此调试时使用按键中断替换了 Device 连接到PC 的情况)。Usb_disconnect()函数,是处理 STM32H563 从 PC 断开的情况(调试时使用按键再次按下来替换 VBUS 断开的具体功能)。
第六步 ,在 ux_device_cdc_acm.h 文件并添加必要的头文件包含和函数声明。
第七步 ,在 ux_device_cdc_acm.c 添加私有变量 并在“USBD_CDC_ACM_Activate”初始化。
这样,我们已经有了 USB 应用程序的功能。类资源在 ux_device_cdc_acm.c 文件中可用。
第八步:在“ux_device_cdc_acm.c”中定义线程的实现程序。
4、对代码进行的测试
对软件工程添加代码后就可以进入编译和调试环节。
客户第一版的硬件产品板上无PC13按键,要手动触发按键中断,需要在下面蓝色栏中写‘1’,然后按下键盘中的回车键来模拟按键按下的动作。(NUCLEO_H563ZI 硬件有这个按键,可以直接使用这个按键来生成按键中断)
5、小结
具体的软件工程放在了附件中,使用 NUCLEO_H563ZI,然后修改硬件就可以进行测试。