GD32F3x0 USB CDC应用案例

本文详述了在GD32F3x0单片机上移植和应用USB CDC驱动的过程,包括从准备、阅读、分析到修改代码的详细步骤。作者通过实践解决了初始化和数据接收的问题,实现了USB虚拟COM口的双向通讯。文章最后总结了移植的难点并分享了驱动代码。
摘要由CSDN通过智能技术生成

GD32F3x0 USB CDC应用
本文有点长,描述了从0开始移植驱动到应用的过程和思路

准备工作:

因项目需求这两天需要做个USB的虚拟COM口发卡器,实现双向通讯,由于功能较为简单我们选择GD32F350来开发。
先跑跑官方例程:

GD32F3x0_Firmware_Library_V2.2.1\Examples\USBFS\USB_Device\cdc_acm

安装GD32 USB驱动:

USB_Virtual_Com_Port_Driver_v2.0.2.2673

我这里采用keil MDK5来开发,keil的安装这里省略。
安装GD32的DFP包:

https://www.gd32mcu.com/cn/download?kw=GD32F3x&lan=cn
GD32F3x0 AddOn 3.0.0

由于我是用的MDK5,例程采用MDK4,这里我们修改工程后缀

\Examples\USBFS\USB_Device\cdc_acm\MDK-ARM\cdc_acm.uvproj
复制 cdc_acm.uvproj,修改为 cdc_acm.uvprojx

打开项目后是无法编译的(原因MDK5是采用CMSIS驱动),按以下方法添加CMSIS
在这里插入图片描述
接下来就可以正常编译和下载了
运行起来,能正常打开COM口,发数据能正常接收,验证板子和例程都没问题。

阅读代码:

阅读例程,不难发现CDC用到了USB类文件

\Firmware\GD32F3x0_usbfs_library\device\class\cdc\Source\cdc_acm_core.c

正式开始阅读:找到app.c main()函数

int main(void)
{
   
    usb_rcu_config();	//初始化时钟
    usb_timer_init();	//初始化定时器器,USB需要用到定时器做精准延时
    usbd_init(&cdc_acm, USB_CORE_ENUM_FS, &cdc_desc, &cdc_class);	//初始化USB
    usb_intr_config();	//初始化中断
    while(1) {
       /* main loop */
        if(USBD_CONFIGURED == cdc_acm.dev.cur_status) {
   	//检查USB是否准备就续
            if(0U == cdc_acm_check_ready(&cdc_acm)) {
   	//检查数据是否准备好,当为0时说明有数据需要接
                cdc_acm_data_receive(&cdc_acm);			//接收数据,这里不难发现我们不知道接收到的数据在哪里
            } else {
   
                cdc_acm_data_send(&cdc_acm);			//发送数据,这里也不知道发的数据在哪里,\
                											或者说我们想法自己的数据该 怎么发?
            }}}}	//为了节约点文章篇幅,我们改改格式

接下来我们把收发的三个函数贴上来

uint8_t cdc_acm_check_ready(usb_dev *udev)	//检查数据是否就绪
{
   
    if (NULL != udev->dev.class_data[CDC_COM_INTERFACE]) {
   
        usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE];
        if ((1U == cdc->packet_receive) && (1U == cdc->packet_sent)) {
   //这里发现接收和发送都为1才就续--为什么?
            return 0U;
        }
    }
    return 1U;
}
void cdc_acm_data_receive (usb_dev *udev)
{
   
    usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE];
    cdc->packet_receive = 0U;	//接收数据前已经把这两个标识置为0了
    cdc->packet_sent = 0U;
    
    //不难发现这个是从数据out端点读数据,数据存放在cdc->data中,每个包最大接收64Byte。
    //实际收到多少数据我们知道吗?  -》NO,这里先不管吧,先大致过一下程序
    usbd_ep_recev(udev, CDC_DATA_OUT_EP, (uint8_t*)(cdc->data), USB_CDC_DATA_PACKET_SIZE);//这里才是接收数据
}
  • 16
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yuleying

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值