1375|1

548

帖子

0

TA的资源

纯净的硅(初级)

楼主
 

【兆易GD32H759I-EVAL】--12.USB虚拟串口 [复制链接]

  本帖最后由 dirty 于 2024-6-12 09:13 编辑

      开发板MCU集成有两个USBFS/HS接口,可用作USB设备/USB主机/OTG设备。本篇讲述USBHS1 被 USB 主机枚举为一个 USB 虚拟串口,可通过USB口回传数据。

一.硬件原理与准备

      开发板硬件USB原理图如下图1。这里使用到CN3 USB_HS1接口,跳线帽JP65、JP70打到USB引脚端。从官网可下载虚拟串口驱动并安装如下图2.

图1:USB原理
图2:USB虚拟串口驱动

 

二.代码准备

      虚拟串口 CDC 例程遵循了 USB 通信类相关子协议,可以将 USB 虚拟成 COM 口,可以像普通的串口一样进行操作。官方提供了USBFS固件库实现 USB 的数据通信。USBFS 固件库分为应用层和驱动层,用户层用户可以修改,驱动层包括 USB 主机或设备驱动和 USB 底层驱动。

1.关于CDC库。可以参阅下官方“GD32 USBFS&USBHS 固件库使用指南”文档,做更深入全面了解。

      在GD32H7xx_Firmware_Library\GD32H7xx_usbhs_library\device\class\cdc下是CDC设备功能代码。包含了USBD_VID 和USBD_PID的定义、CDC 相关的描述符项。

      CDC 本身包含两个接口,一个命令接口、一个数据接口,命令接口相关描述符如下:

图3:CDC命令接口描述符

      CDC 设备类接口函数如下,这里主要关注后三个

图4:CDC 设备类接口函数

      CDC 设备类请求类如下:

图5:CDC 设备类请求

      CDC 用户接口函数如下,这个是我们应用需要的。

图6:CDC 用户接口函数

2.打开CDC_ACM工程,在Options里配置宏USE_USB_HS使用高速USB;配置USE_USBHS1,以使用USB_HS1。

图7:USB宏定义

3.配置USB时钟

  • void usb_rcu_config(void)
  • {
  • pmu_usb_regulator_enable();
  • pmu_usb_voltage_detector_enable();
  • while (pmu_flag_get(PMU_FLAG_USB33RF) != SET) {
  • }
  • #ifdef USE_USB_FS
  • #ifndef USE_IRC48M
  • #ifdef USE_USBHS0
  • rcu_usb48m_clock_config(IDX_USBHS0, RCU_USB48MSRC_PLL0R);
  • #endif /* USE_USBHS0 */
  • #ifdef USE_USBHS1
  • rcu_usb48m_clock_config(IDX_USBHS1, RCU_USB48MSRC_PLL0R);
  • #endif /* USE_USBHS1 */
  • #else
  • /* enable IRC48M clock */
  • rcu_osci_on(RCU_IRC48M);
  • /* wait till IRC48M is ready */
  • while (SUCCESS != rcu_osci_stab_wait(RCU_IRC48M)) {
  • }
  • #ifdef USE_USBHS0
  • rcu_usb48m_clock_config(IDX_USBHS0, RCU_USB48MSRC_IRC48M);
  • #endif /* USE_USBHS0 */
  • #ifdef USE_USBHS1
  • rcu_usb48m_clock_config(IDX_USBHS1, RCU_USB48MSRC_IRC48M);
  • #endif /* USE_USBHS1 */
  • #endif /* USE_IRC48M */
  • #endif /* USE_USB_FS */
  • #ifdef USE_USBHS0
  • rcu_periph_clock_enable(RCU_USBHS0);
  • #endif /* USE_USBHS0 */
  • #ifdef USE_USBHS1
  • rcu_periph_clock_enable(RCU_USBHS1);
  • #endif /* USE_USBHS1 */
  • #ifdef USE_ULPI_PHY
  • rcu_periph_clock_enable(RCU_ULPI);
  • #endif /* USE_ULPI_PHY */
  • }

4.配置USB delay定时器。这里使用到Timer2,在gd32h7xx_it.c里有其定时中断函数TIMER2_IRQHandler。

  • void usb_timer_init (void)
  • {
  • /* configure the priority group to 2 bits */
  • nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
  • /* enable the TIM2 global interrupt */
  • nvic_irq_enable((uint8_t)TIMER2_IRQn, 1U, 0U);
  • rcu_periph_clock_enable(RCU_TIMER2);
  • }

5.初始化cdc参数。这里使用USBHS1 usb外设,选用高速USB_SPEED_HIGH,通过结构体指针,初始化后将cdc_acm赋值带出。

  • void usb_para_init(usb_core_driver *udev, uint32_t usb_periph, uint32_t usb_speed)
  • {
  • usb_core_basic *usb_basic = &udev->bp;
  • /* configure USB default transfer mode as FIFO mode */
  • usb_basic->transfer_mode = (uint8_t)USB_USE_FIFO;
  • /* USB default speed is full-speed */
  • usb_basic->core_speed = (uint8_t)USB_SPEED_FULL;
  • /* USB basic register address setting */
  • switch(usb_periph){
  • case USBHS0:
  • usb_basic->base_reg = (uint32_t)USBHS0_REG_BASE;
  • break;
  • case USBHS1:
  • usb_basic->base_reg = (uint32_t)USBHS1_REG_BASE;
  • break;
  • default:
  • break;
  • }
  • /* set the host channel numbers */
  • usb_basic->num_pipe = USBHS_MAX_CHANNEL_COUNT;
  • /* set the device endpoint numbers */
  • usb_basic->num_ep = USBHS_MAX_EP_COUNT;
  • if (USB_SPEED_HIGH == usb_speed) {
  • #ifdef USB_EXTERNAL_ULPI_PHY_ENABLED
  • usb_basic->phy_itf = USB_ULPI_PHY_EXTERNAL;
  • #endif /* USB_EXTERNAL_ULPI_PHY_ENABLED */
  • #ifdef USB_EMBEDDED_HS_PHY_ENABLED
  • usb_basic->phy_itf = USB_EMBEDDED_PHY_HS;
  • #endif /* USB_EMBEDDED_HS_PHY_ENABLED */
  • } else if (USB_SPEED_FULL == usb_speed) {
  • #ifdef USB_EMBEDDED_FS_PHY_ENABLED
  • usb_basic->phy_itf = USB_EMBEDDED_PHY_FS;
  • #endif /* USB_EMBEDDED_FS_PHY_ENABLED */
  • } else {
  • /* no operation */
  • }
  • #ifdef USB_INTERNAL_DMA_ENABLED
  • usb_basic->transfer_mode = USB_USE_DMA;
  • #endif /* USB_INTERNAL_DMA_ENABLED */
  • usb_basic->sof_enable = (uint8_t)USB_SOF_OUTPUT;
  • usb_basic->low_power = (uint8_t)USB_LOW_POWER;
  • #if (1U == LPM_ENABLED)
  • usb_basic->lpm_enable = 1U;
  • #endif /* LPM_ENABLED */
  • }

6.初始化USB设备模式,并加载驱动。这里使用到了前面初始化的cdc_acm,初始化usb描述符和USB内核。这里面引用到了CDC库。

  • void usbd_init(usb_core_driver *udev, usb_desc *desc, usb_class_core *class_core)
  • {
  • udev->dev.desc = desc;
  • /* class callbacks */
  • udev->dev.class_core = class_core;
  • /* create serial string */
  • serial_string_get(udev->dev.desc->strings[STR_IDX_SERIAL]);
  • /* configure USB capabilities */
  • (void)usb_basic_init(&udev->bp, &udev->regs);
  • /* initializes the USB core*/
  • (void)usb_core_init(udev->bp, &udev->regs);
  • /* set device disconnect */
  • usbd_disconnect(udev);
  • /* initializes device mode */
  • (void)usb_devcore_init(udev);
  • /* set device connect */
  • usbd_connect(udev);
  • udev->dev.cur_status = (uint8_t)USBD_DEFAULT;
  • }

7.配置USB中断。宏定义使用USE_USBHS1。在gd32h7xx_it.c里有其中断函数USBHS1_IRQHandler,USBHS1_WKUP_IRQHandler,USBHS1_EP1_OUT_IRQHandler。

  • /*!
  • \brief configure USB interrupt
  • \param[in] none
  • \param[out] none
  • \retval none
  • */
  • void usb_intr_config(void)
  • {
  • nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
  • #ifdef USE_USBHS0
  • nvic_irq_enable((uint8_t)USBHS0_IRQn, 3U, 0U);
  • #endif /* USE_USBHS0 */
  • #ifdef USE_USBHS1
  • nvic_irq_enable((uint8_t)USBHS1_IRQn, 3U, 0U);
  • #endif /* USE_USBHS0 */
  • /* enable the power module clock */
  • rcu_periph_clock_enable(RCU_PMU);
  • #ifdef USE_USBHS0
  • /* USB wakeup EXTI line configuration */
  • exti_interrupt_flag_clear(EXTI_31);
  • exti_init(EXTI_31, EXTI_INTERRUPT, EXTI_TRIG_RISING);
  • exti_interrupt_enable(EXTI_31);
  • nvic_irq_enable((uint8_t)USBHS0_WKUP_IRQn, 1U, 0U);
  • #endif /* USE_USBHS0 */
  • #ifdef USE_USBHS1
  • /* USB wakeup EXTI line configuration */
  • exti_interrupt_flag_clear(EXTI_32);
  • exti_init(EXTI_32, EXTI_INTERRUPT, EXTI_TRIG_RISING);
  • exti_interrupt_enable(EXTI_32);
  • nvic_irq_enable((uint8_t)USBHS1_WKUP_IRQn, 1U, 0U);
  • #endif /* USE_USBHS1 */
  • #ifdef USB_DEDICATED_EP1_ENABLED
  • #ifdef USE_USBHS0
  • nvic_irq_enable((uint8_t)USBHS0_EP1_OUT_IRQn, 1U, 0U);
  • nvic_irq_enable((uint8_t)USBHS0_EP1_IN_IRQn, 1U, 0U);
  • #endif /* USE_USBHS0 */
  • #ifdef USE_USBHS1
  • nvic_irq_enable((uint8_t)USBHS1_EP1_OUT_IRQn, 1U, 0U);
  • nvic_irq_enable((uint8_t)USBHS1_EP1_IN_IRQn, 1U, 0U);
  • #endif /* USE_USBHS1 */
  • #endif /* USB_DEDICATED_EP1_ENABLED */
  • }

8.main函数实现USB虚拟串口接收完全后回显。

  • int main(void)
  • {
  • /*
  • //USB HS1 CDC初始化
  • ......
  • */
  • while (1)
  • {
  • if (USBD_CONFIGURED == cdc_acm.dev.cur_status)
  • {
  • if (0U == cdc_acm_check_ready(&cdc_acm))
  • {
  • cdc_acm_data_receive(&cdc_acm);
  • }
  • else
  • {
  • cdc_acm_data_send(&cdc_acm);
  • }
  • }
  • }
  • }

 

三.测验

      编译烧录后,复位运行,可以在设备管理器找到虚拟串口。用串口工具打开,发送一串字符,在接收区会接收到一串相同的字符。如下图

图8:USB虚拟串口测试

 

 

      至此,实现USB 虚拟串口功能。

 

最新回复

USB虚拟串口可能增加系统的功耗 这个功耗可以测试一下     详情 回复 发表于 2024-6-14 07:36
点赞 关注
个人签名

保持热爱

 
 

回复
举报

7020

帖子

0

TA的资源

五彩晶圆(高级)

沙发
 

USB虚拟串口可能增加系统的功耗

这个功耗可以测试一下

 

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
推荐帖子
ARM JTAG调试常见问题

1 - 检测不到目标系统 调试前,请把目标板连接好,然后用调试软件检测目标系统。如果检测不到目标系统,请做 以下的检查。 A - ...

AVR单片机工具软件集锦---连载中

从网上搜集来的AVR相关的小工具软件,供大家分享 需要特别说明的是,这些软件是从网上搜集来的,我本人无意侵占相关作者的版权, ...

再上一辑,FPGA示波器!双通200M+200M采样,模拟带宽25M,开源,正学习FPGA网友细看了。

俯身苦干几个月,软硬件终于调试差不多了!出关,给大家看个鲜。 感谢坛中avic及各位高手的贴子,从中学习了很多!!! 性能目标 ...

读取LPC ARM芯片唯一序列号的方法

对于ARM芯片基本都有唯一序列号,这产权保护,产品加密,产品序列号设置带来了极大的方便。但是不同厂家,甚至同一厂家不同系列 ...

MSP430单片机的开关电源

作者:Freedomz 1 引 言 MSP430系列单片机是美国TI公司生产的新一代16位单片机,是一种超低功耗的混合信号处理器(MixedSigna ...

以太网LED不亮

484575 万能的论坛大神们,问一下,这个硬件电路设计上是否存在问题,把网线连接上去,网口LED都不会亮的,更不用说后面的收 ...

单片机中PWM的工作原理解析

PWM在单片机中的应用是非常广泛的,它的基本原理很简单,但往往应用于不同场合上意义也不完全一样,这里我先把基本概念和基本原 ...

电压比较器LM393两路输出不正常

电路要实现的目的:输入一信号Vin,与参考电压比较,输出对应两路信号,一输出为高电平,一输出为低电平。使用电压比较器lm393 ...

[ST NUCLEO-WBA52CG] 7 - 在BLE协议栈的后台处理函数中添加自己的代码

前面测评的时候,提到了BLE的协议栈是使用sequencer来实现后台任务的管理的,除了sequence以外还提供了定时器函数。因此如果我们 ...

喜欢奥迪的不要错过

本帖最后由 小斯克 于 2023-12-8 17:22 编辑 通过百度网盘分享的文件:奥迪 链接:https://pan.baidu.com/s/1vpPjdXKnTaj_gbVl ...

关闭
站长推荐上一条 1/10 下一条
有奖探索 | 和村田一起,深挖 GNSS 开发!
活动时间:即日起-5月11日
活动奖励:智能手环、螺丝刀套装、双肩包

查看 »

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网 10

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表