STM32CubeMx+HAL库实现USB CDC+MSC复合设备

之前的文章中介绍过STM32的USB应用,包括虚拟串口(CDC)和大容量存储设备(MSC)。今天来介绍USB实现CDC和MSC复合设备的方法。

硬件:STM32F407VET6

软件:STM32CubeMx v6.5+F4库v1.27.1

编译环境:MDK 5.30

1.准备两个工程

首先用STM32CubeMX分别生成CDC和MSC两个工程,测试正常。具体可参考之前的文章。

STM32实现USB转串口功能(含源码)

STM32&SD卡实现USB虚拟U盘(含源码)

2.拷贝到一个工程中 

以其中一个工程为模板,将另一个工程中需要的文件拷贝过来。这里以MSC的工程为模板,将CDC工程中的下列文件/文件夹拷贝过来,并添加到工程中。

         

添加完成后的工程目录如下:

复制过来的只有usbd_cdc_if.c和usbd_cdc.c及对应的.h文件,usbd_msccdc.c文件是需要自己实现的USB复合设备的代码。

3.修改程序

a)首先,原有的工程已经有USB复合设备的框架了,要使用的话需要添加一个宏定义:USE_USBD_COMPOSITE,直接在编译器里添加就行:

b)然后编写usbd_msccdc.c和对应的.h文件。该文件主要是USB复合设备的描述符等,这里不详细介绍。文件内容见文章末尾链接。         

c)其次修改USB CDC和MSC的端点,在usbd_cdc.h和usbd_msc.h文件中:

CDC使用的是0x81  0x01 和0x82三个端点

#ifndef CDC_IN_EP
#define CDC_IN_EP                                   0x81U  /* EP1 for data IN */
#endif /* CDC_IN_EP */

#ifndef CDC_OUT_EP
#define CDC_OUT_EP                                  0x01U  /* EP1 for data OUT */
#endif /* CDC_OUT_EP */

#ifndef CDC_CMD_EP
#define CDC_CMD_EP                                  0x82U  /* EP2 for CDC commands */

MSC使用的是0x83和0x03端点

  • #ifndef MSC_EPIN_ADDR
    #define MSC_EPIN_ADDR                0x83U
    
    #ifndef MSC_EPOUT_ADDR
    #define MSC_EPOUT_ADDR               0x03U

d)然后把usbd_conf.h文件中USBD_MAX_NUM_INTERFACES的值1修改为3

e)修改usbd_conf.c文件,如下:

f)修改usbd_msc.c和usbd_cdc.c文件如下:

        g) 最后修改usb_device.c文件:

void MX_USB_DEVICE_Init(void)
{
  /* USER CODE BEGIN USB_DEVICE_Init_PreTreatment */
  /* USER CODE END USB_DEVICE_Init_PreTreatment */

  /* Init Device Library, add supported class and start the library. */
 if (USBD_Init(&hUsbDeviceFS, &usbCmpsitFS_Desc, DEVICE_FS) != USBD_OK)
  {
    Error_Handler();
  }
  /* if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_MSC) != USBD_OK)
  {
    Error_Handler();
  } */

  if(USBD_RegisterClassComposite(&hUsbDeviceFS, &USBD_CDC,CLASS_TYPE_CDC,0) != USBD_OK)
  {
    Error_Handler();
  }

  if(USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS) != USBD_OK)
  {
    Error_Handler();
  }
  if(USBD_RegisterClassComposite(&hUsbDeviceFS, &USBD_MSC,CLASS_TYPE_MSC,0) != USBD_OK)
  {
    Error_Handler();
  }
  if (USBD_MSC_RegisterStorage(&hUsbDeviceFS, &USBD_Storage_Interface_fops_FS) != USBD_OK)
  {
    Error_Handler();
  }
  if (USBD_Start(&hUsbDeviceFS) != USBD_OK)
  {
    Error_Handler();
  }

  /* USER CODE BEGIN USB_DEVICE_Init_PostTreatment */

  /* USER CODE END USB_DEVICE_Init_PostTreatment */
}

最后,编译成功后下载程序测试。可以看到USB虚拟出了一个串口和1个U盘,这里的U盘是一张32G的TF卡。测试一下串口收发和U盘读写,都正常。

链接:https://pan.baidu.com/s/1ZsH1C65ywMlmuznY7IrxRw?pwd=r4zr

提取码:r4zr

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/9909.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

自动驾驶概述

自动驾驶是指利用计算机视觉、机器学习、传感器等技术,使汽车或其他交通工具能够在没有人类干预的情况下,完成自主导航和行驶任务。自动驾驶技术可以提高交通安全、减少交通拥堵、提高车辆利用率等,并对未来的城市交通和交通工具设计产生深远…

采购招投标系统-高效管控招采流程-降低采购成本

项目说明 随着公司的快速发展,企业人员和经营规模不断壮大,公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境,最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范,以及…

【SpringBoot技术专题】「实战指南」从实战开发角度去分析操作RestTemplate的应用及使用技巧

前提介绍 当你的应用程序需要访问远程接口时,很容易被不同的浏览器和API调用协议弄晕。幸运的是,Spring框架已为我们提供了一个简单而功能强大的RestTemplate工具,它可以轻松地处理这些基础任务并提供一个简单的方式来访问各种API。 RestTe…

零售数据分析之操作篇12:子查询的应用

各位数据的朋友,大家好,我是老周道数据,和你一起,用常人思维数据分析,通过数据讲故事。 上期内容与作业 上一讲讲了占比相关内存计算的应用场景,包括占比、TOP占比、累计占比等,不同的占比&am…

Explain分析示例

Explain分析示例示例表explain 两个变种explain中的列1. id列2. select_type列3. table列4. type列NULL:const, system:eq_ref:ref:range:index:ALL:5.possible_keys列6. key列7. key_len列8. r…

Matlab simulink上手控制仿真学习笔记3-常用模块S Function及使用案例

讲得真的十分细致!个人感觉看完前4节就差不多了。 今天记录的是S Function。 内容比较多,加个目录: S Function前置工作1.1 parameter.m1.2 plant.mfunction [sys,x0,str,ts,simStateCompliance] plant(t,x,u,flag,pa)function [sys,x0,str…

《Kubernetes部署篇:Ubuntu20.04基于containerd二进制部署K8S 1.24.12集群(一主多从)》

一、架构图 如下图所示: 如下图所示: 二、环境信息 1、部署规划 主机名IP地址操作系统内核版本软件说明etcd01192.168.1.62Ubuntu 20.04.5 LTS5.15.0-69-genericetcd02192.168.1.63Ubuntu 20.04.5 LTS5.15.0-69-genericetcd03192.168.1.64Ubuntu 20.04.…

第三章 运算符

文章目录1. 什么是运算符2 算术运算符2.1 基本四则运算符 、-、*、/、%2.2 增量赋值运算符 、- 、* 、/ 、%2.3 自增/自减运算符 、--3. 关系运算符4. 逻辑运算符5. 位运算符6. 移位运算7. 条件运算符8. 运算符的优先级1. 什么是运算符 计算机的最基本的用途之一就是执行数学运…

Web Components 技术分析

简括: Web Components 基于四个主要的规范: Custom Elements,Shadow DOM,HTML Templates 和 HTML Imports。 Custom Elements 可以让开发人员创建自定义的 HTML 标签。 Shadow DOM 可以让开发人员将样式和行为封装到自定义元素内…

C/C++|物联网开发入门+项目实战|C语言基础|玩转c代码---从输入输出开始-学习笔记(6)

文章目录玩转c代码---从输入输出开始参考教程:C语言编程:一本全面的C语言入门教程(第3版)第16章需要掌握的内容需要了解的内容常见的人机交互接口串口的输入输出PC常用的几个输入输出函数示例代码3 printf函数使用难点分析A.格式控制字符串的基本形式:示…

今天给大家介绍一篇基于springboot的医院管理系统的设计与实现

临近学期结束,你还在做java程序网络编程,期末作业,老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下,你想解决的问题,今天给大家介绍一篇基…

APK一键注入网络验证后台PHP源码ThinkPHP开发版

APK一键注入网络验证后台PHP源码ThinkPHP开发版 APK一键注入网络验证后台PHP源码ThinkPHP开发版 源码: https://url11.ctfile.com/d/25976711-55383299-827d49?p6724 (访问密码:6724) 修复 已去除登录提示到期问题。 功能简介 - 无注…

软考-套接字(scoket)

💤SocketSocket套接字:是由系统提供用于网络通信的技术,是基于TCP/IP协议的网络通信的基本操作单元。将OSI模型中从传输层到物理层封装起来的抽象层,把网络协议隐藏在Socket抽象层中,只对使用者暴露API接口&#xff0c…

Redis实现分布式锁原理和Redisson框架实现分布式锁,全网最详细讲解

声明:我的大部分篇幅都讲的分布式锁的原理和实现,如果想直接用Redisson框架实现分布式锁,可以直接翻至最后面 关于分布式锁,适用于并发量特别大的微服务集群,能做到同步的实现资源的获取 我其实没有经过真实项目的分布…

【ROS2指南-1】配置ROS2环境

资料来源Configuring your ROS 2 environment — ROS 2 Documentation: Dashing documentationhttp://docs.ros.org/en/dashing/Tutorials/Configuring-ROS2-Environment.html 目标:本教程将向您展示如何准备 ROS 2 环境。 教程级别:初学者 时间&…

MyBatis(十一)、MyBatis查询语句专题

准备工作: 模块名:mybatis-007-select 打包方式:jar 引入依赖:mysql驱动依赖、mybatis依赖、logback依赖、junit依赖。 引入配置文件:jdbc.properties、mybatis-config.xml、logback.xml 创建pojo类:Car 创…

【华为机试真题详解JAVA实现】—从单向链表中删除指定值的节点

目录 一、题目描述 二、解题代码 一、题目描述 输入一个单向链表和一个节点的值,从单向链表中删除等于该值的节点,删除后如果链表中无节点则返回空指针。 链表的值不能重复。 构造过程,例如输入一行数据为: 6 2 1 2 3 2 5 1 4 5 7 2 2 则第一个参数6表示输入总共6个节点,…

AI又进化了,声音克隆革命性突破

大家好,我是 Jack。 因 ChatGPT、Stable Diffusion 让 AI 在文本、图像生成领域火出了圈。 但 AI 在生成方面的能力,可不仅如此,音频领域也出现了很多优秀的项目。 我用我本人的音频数据,训练了一个 AI 模型,生成了…

数据结构系列17——lambda表达式

目录 1. 基本概念 2. 基本语法 3. 函数式接口 4. Lambda表达式的基本使用 4.1 语法精简 5. 变量捕获 6. Lambda在集合当中的使用 1. 基本概念 Lambda表达式是Java SE 8中一个重要的新特性。lambda表达式允许你通过表达式来代替功能接口。 lambda表达式就和方法一样,它提供了一…

循环依赖详解及解决方案

介绍 上图就是循环依赖的三种情况,虽然方式不同,但是循环依赖的本质是一样的,就A的完整创建要依赖与B,B的完整创建要依赖于A,相互依赖导致没办法完整创建造成失败. 循环依赖代码演示 public class Demo {public static void main(String[] args) {new Demo1();} }class Demo1…