cubeIDE开发, stm32的USB从设备串口驱动设计

news2024/11/19 5:55:59

一、USB_OTG简介

        USB_OTG(OTG,ON THE GO)是一款双角色设备(DRD) 控制器,同时支持从机(USB DEVICE)功能和主机(USB HOST)功能。在主机模式下,OTG 支持全速(OTG_FS,12 Mb/s)和低速(OTG_LS,1.5 Mb/s)收发器,而从机模式下则仅支持全速(FS,12 Mb/s)收发器。主机模式下需要的唯一外部设备是提供VBUS的电荷泵。在驱动实现层面,USB OTG是USB Device和USB Host 的基础。在实际使用,USB OTG是USB Device和USB Host 的底层驱动。

        stm32芯片的通常USB物理接口管理两个引脚:

            DP/DM:内置上下拉,由控制器来设置不同类型的需求

        OTG实现时,额外配置ID引脚:
            ID:检测插入的线是B端还是A端,用于区分A类和B类设备,

        USB Host 模式下,需加配置Vbus引脚:
            Vbus:内置检测器,用于测试UBUS的有效性

        额外地需要支持SOF和NOF时,需要加配置SOF和NOF引脚。

        例如本文采用的STM32L496VGT3芯片,其配置支持到的引脚如下:

USB协议栈的层次划分

    一个Host可能有一个或者多个Device
    一个Device可能有一个或者多个Interface
    一个Interface可能有一个或者多个Endpoint

        Host(主机)连的是Device(设备),这一层是走物理连接的,也就是信号线实际连接两台设备。

        Device(设备)下可能有多个Interfece(接口),从这开始是逻辑概念,一个Interface,就是一个独立的功能接口,每个Interface模拟一个设备功能,比如集成了键盘和鼠标的USB设备,里面就是两个interface,一个是键盘,另一个是鼠标。Interface之间通常是隔离的,互相不干扰。
        每个Interface(接口)下面有一个或者多个Endpoint(端点),这也是逻辑概念,例如控制信号端口、数据信号端口等。端点是USB设备通信的基本单位,所有通信几乎都是从端点发起的。

二、创建工程及USB_Device配置

        本博文基于STM32L496VGTX3芯片实现,参考本专栏的博文:

cubeIDE开发, stm32的OLED点亮及字符显示设计(基于SPI通信)_py_free的博客-CSDN博客_stm32 hal spi oled

        基于该工程的(.ioc)文件创建了新工程stm32L496VGTx_USB,并移植了相关源码,实现了lpusart通信以及lcd显示字体。

        现打开工程的(.ioc)配置文件,进入cubeMX配置界面,开启USB_OTG_FS的USB Device功能,参数保持默认配置。

        确保USB_OTG_FS的中断功能已经开启。

         开启USB_OTG_FS的USB Device选项后,Middleware栏目可以去配置USB_Device信息,本文MCU作为USB_Device与笔记本电脑USB_HOST相连接,实现串口通信收发数据,因此选择通信类型虚拟串口功能,如下图所示,参数保持默认。

         设备描述符按默认设置:

         由于USB驱动引入了中间件代码,并比较复杂,需要更多缓存支持,现进入工程配置页面,调整min heap size和min stack size为合适的值,防止因数值较少而出现无法编译、编译异常、运行错误等情况出现。

         点击保存输出生成代码,关于USB_Device驱动相关代码如下,其中usb_cdc_if.h/c源码是用户可修改源文件:

 三、USB_Device驱动实现设计

        【1】在usb_cdc_if.h中,添加USB相关全局变量(接收缓存数组、最大长度、接收标记及长度)

/* USER CODE BEGIN INCLUDE */
#define USB_REC_LEN   256//定义USB串口最大接收字节数
extern uint8_t USB_RX_BUF[USB_REC_LEN];//接收缓冲,最大USB_REC_LEN个字节.末字节为换行符
extern uint16_t USB_RX_STA;//接收状态标记(接收到的有效字节数量)
/* USER CODE END INCLUDE */

        【2】在usb_cdc_if.h中,添加USB打印输出函数USB_printf声明

/* USER CODE BEGIN EXPORTED_VARIABLES */
void USB_printf(const char *format,  ...);//USB模拟串口的打印函数
/* USER CODE END EXPORTED_VARIABLES */

        【3】在usb_cdc_if.c中,调整USB接收函数

static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
  /* USER CODE BEGIN 6 */
  //新增代码开始处
	if(*Len<USB_REC_LEN)//判断收到数据量是否小于寄存器上限
    {
       uint16_t i;
       USB_RX_STA = *Len;//将数据量值放入标志位
       for(i=0;i<*Len;i++)//循环(循环次数=数据数量)
           USB_RX_BUF[i] = Buf[i];//将数据内容放入数据寄存器
    }
  //新增代码结束处
  USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
  USBD_CDC_ReceivePacket(&hUsbDeviceFS);
  return (USBD_OK);
  /* USER CODE END 6 */
}

        【4】在usb_cdc_if.c中,调整USB发送函数

uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
  uint8_t result = USBD_OK;
  /* USER CODE BEGIN 7 */
  //注释旧代码
//  USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
//  if (hcdc->TxState != 0){
//    return USBD_BUSY;
//  }
//  USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
//  result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
  //新增新代码
  uint32_t TimeStart = HAL_GetTick();
  USBD_CDC_HandleTypeDef *hcdc =  (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
  while(hcdc->TxState)
  {
     if(HAL_GetTick()-TimeStart > 10)
    	 return USBD_BUSY;
     else
    	 break;
  }
  USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf,  Len);
  result =  USBD_CDC_TransmitPacket(&hUsbDeviceFS);
  TimeStart = HAL_GetTick();
  while(hcdc->TxState)
  {
     if(HAL_GetTick()-TimeStart > 10)
       return USBD_BUSY;
  }
  /* USER CODE END 7 */
  return result;
}

        【5】在usb_cdc_if.c中,实现USB打印输出函数USB_printf定义

/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
#include <stdarg.h>
void USB_printf(const char *format, ...)//USB模拟串口的打印函数
{
    va_list args;
    uint32_t length;
    va_start(args, format);
    length = vsnprintf((char  *)UserTxBufferFS, APP_TX_DATA_SIZE, (char  *)format, args);
    va_end(args);
    CDC_Transmit_FS(UserTxBufferFS, length);
}
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */

        【6】在main.c文件中,添加USB驱动头文件支持

/* USER CODE BEGIN Includes */
#include "../../ICore/led/led.h"
#include "../../ICore/oled/oled.h"
#include "../../USB_DEVICE/App/usbd_cdc_if.h"
/* USER CODE END Includes */

        【7】在main主函数初始化处

  /* USER CODE BEGIN 2 */
  OLED_init();
  //设置OLED蓝色背景显示
  BSP_LCD_Clear_DMA(LCD_DISP_BLUE);
  printf("OLED_Clear_DMA\r\n");
  /* USER CODE END 2 */

         【8】在main主函数循环体内实现

  /* USER CODE BEGIN WHILE */
  while (1)
  {
	  //USB模拟串口的查寻接收处理(其编程原理与USART1串口收发相同)
	  if(USB_RX_STA!=0)//判断是否有数据
	  {
		  OLED_printf(10,42,"%.*s",USB_RX_STA, USB_RX_BUF);
		  Toggle_led1();
		  USB_RX_STA=0;//数据标志位清0
		  memset(USB_RX_BUF,0,sizeof(USB_RX_BUF));//USB串口数据寄存器清0
		  HAL_Delay(10);//等待
	  }
    /* USER CODE END WHILE */

四、编译及下载

        编译下载,该开发板原理框图,需要将跳线帽重新插拔设置,相当于原理的USB-ST-LINK连接到USB_MCU上,即原理lpusart通信及ST-LINK下载的USB接口改为连接到USB_MCU的DM/DP引脚上实现通信。

         更改调线帽后,打开串口工具,发送数据,顺利在点(10,42)位置绘制输入文字,LED1等会切换状态。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2022圣诞在即,出海品牌如何做好网红营销?

随着2022圣诞节逐渐临近&#xff0c;节日气氛也开始浓郁起来&#xff0c;尤其在社交媒体上&#xff0c;圣诞主题的内容越来越多&#xff0c;随之而来的则是各种营销与折扣。受经济形势影响&#xff0c;性价比在当下显得尤为重要&#xff0c;有60%的消费者表示&#xff0c;今年圣…

【能效分析】安科瑞变电所运维云平台解决方案应用分析

概述 安科瑞 李亚俊 壹捌柒贰壹零玖捌柒伍柒 AcrelCloud-1000变电所运维云平台基于互联网&#xff0b;大数据、移动通讯等技术开发的云端管理平台&#xff0c;满足用户或运维公司监测众多变电所回路运行状态和参数、室内环境温湿度、电缆及母线运行温度、现场设备或环境视频场…

CentOS MySQL安装

1.查询是否已经存在mariadb。 rpm -qa|grep mariadb如果存在需要卸载。 rpm -e --nodeps mariadb-libs-5.5.68-1.el7.x86_642.通过xftp上传MySQL和Hive压缩包。 3.解压压缩包。 tar -zxvf apache-hive-2.3.4-bin.tar.gz -C /opt/apps/ tar -zxvf mysql-5.7.27-el7-x86_64.ta…

042-推箱子游戏源代码2

上一讲:041-推箱子游戏1_CSDN专家-赖老师(软件之家)的博客-CSDN博客 摘要: 1、使用JAVA基础知识 2、GUI界面编程实现推箱子界面,常用控件的综合应用; 3、使用JAVA绘图技术实现推箱子过程的绘图功能; 4、使用键盘事件,通过方向键实现推箱子过程; 5、使用音频技术,…

Android实现车辆检测(含Android源码 可实时运行)

Android实现车辆检测(含Android源码 可实时运行) 目录 Android实现车辆检测(含Android源码 可实时运行) 1. 前言 2. 车辆检测数据集说明 3. 基于YOLOv5的车辆检测模型训练 4.车辆检测模型Android部署 &#xff08;1&#xff09; 将Pytorch模型转换ONNX模型 &#xff08…

Python编程 圣诞树教程 (附代码)程序员的浪漫

作者简介&#xff1a;一名在校计算机学生、每天分享Python的学习经验、和学习笔记。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.python 做圣诞树 1.turtle库 2.python函数的定义规则 2.引入库 3.定…

中断系统中的设备树__在S3C2440上使用设备树描述中断体验

目录 1 怎么描述一个中断 2 怎么描述一个中断控制器 3 总结 1 怎么描述一个中断 我们想在设备树文件中描述一个中断&#xff0c;那么需要两个东西 a.指定是哪一个中断控制器 b.是中断控制器里面的哪一个中断。 假设我们有一个网卡&#xff0c;当网卡有数据时会产生一个中…

论文速度系列三:SA-SSD、CIA-SSD、SE-SSD

如有错误&#xff0c;恳请指出。 参考网上资料&#xff0c;对一些经典论文进行快速思路整理 文章目录1. SA-SSD2. CIA-SSD3. SE-SSD1. SA-SSD paper&#xff1a;《Structure Aware Single-stage 3D Object Detection from Point Cloud》&#xff08;2020CVPR&#xff09; 结构…

网络工程师备考4章

4.1 历年考点分布 4.2 局域网和城域网 4.2.1 局域网体系与拓扑结构 一般数据链路层的协议都是IEEE这个组织规范的,网络层是有RFC这个组织规范的。 数据链路层是可以划分为两个子层的,第一个叫逻辑链路控制LLC(对接上面的网络层),第二个叫MAC子层(更偏向于物理层)。 最…

【hadoop】Hadoop 3.3.4 集群安装及简单使用

目录环境信息1. 准备1.1 服务器规划1.2 主机名及hosts文件修改1.2.1 hostname修改1.2.2 hosts文件修改1.3 创建hadoop用户&#xff08;建议&#xff09;1.4 为hadoop用户添加sudo权限1.5 互信免密登录1.6 快速文件同步&#xff08;可选&#xff09;2. 安装2.1 下载并安装jdk2.2…

变量学习笔记

一:作用域 说起变量第一个要说到的肯定就是作用域,正是因为不熟悉JS的作用域,往往就会把面向对象的作用域张冠李戴,毕竟有些东西总是习惯性 的这样,但是并不是每次照搬都是可以的,那么下一个问题就来了,js到底是什么作用域,当然是函数作用域了,我们的浏览器就是一个被…

基于工业物联网的温度监测系统在钢铁行业的应用

随着钢铁行业的快速发展&#xff0c;越来越多电气设备被接入到工业生产系统中&#xff0c;对自动化和连续性的生产提出新的要求&#xff0c;需要关注到供电的稳定可靠&#xff0c;也要关注到用电设备的运行状态。电气设备在长期运行中会面临越来越高的风险&#xff0c;引发危险…

ncurses交叉编译

1.环境 编译环境&#xff1a;ubuntu18.04虚拟机 板端&#xff1a;移远AG550平台 编译链aarch64-oe-linux 2.ncurses下载 ncurses库下载地址&#xff1a;Index of /pub/gnu/ncurses 下载5.9的版本 3.解压并且编译 tar xvf ncurses-5.9.tar.gz cd ncurses-5.9 执行configure命…

Android与H5(Vue)交互

Android与H5互调 实现效果&#xff1a; JS调用Android方法实现dialog弹窗&#xff0c;Android点击弹窗确定/取消按钮调用JS方法&#xff0c;在H5界面展示传递的参数。 Vue准备&#xff1a; 执行 npm run serve 命令启动项目&#xff0c;启动成功后会在命令行看到两个地址&am…

beego框架学习之安装框架

Beego 是一个快速开发 Go 应用的 HTTP 框架&#xff0c;可以用来快速开发 API、Web 及后端服务等各种应用&#xff0c;是一个 RESTful 的框架&#xff0c;相对于echo框架仅包含路由和控制器核心模块&#xff0c;beego是一个完整的MVC框架包括路由&控制器、model 数据库ORM封…

GitLab结合fortify实现自动化代码审计实践

一、背景 在甲方做安全的同学可能会有一项代码审计的工作&#xff0c;通常需要从gitlab把代码拉取下来&#xff0c;然后使用代码审计工具进行扫描&#xff0c;然后对结果进行人工确认&#xff1b; 在这个流程中需要做的事情比较繁琐&#xff0c;比如说gitlab如何配置token、如…

.net开发安卓入门 - 基本交互(Button,输入EditText,TextView,Toast)

.net开发安卓入门 - 基本交互前言TextViewEditTextButtonxml代码如下C#代码如下运行效果优化代码先看原生Android给一个View添加点击事件的三种方式在Xamarin.Android中添加onClick也的两种办法使用onClick绑定前后台调用处理逻辑第一步&#xff1a;第二步&#xff1a;第三步&a…

【实操篇】Linux组管理

目录 ●组管理 ●linux组的基本介绍 ●组的创建以及对用户的操作&#xff08;复习&#xff09; ●查看文件的所有者 ●改变文件所有者 ●修改文件所在的组 ●改变用户所在组 ●linux组的基本介绍 在Linux中的每个用户必须属于一个组&#xff0c;不能独立于组外。并且在Li…

[附源码]Python计算机毕业设计SSM基于云服务器网上论坛设计(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

软件测试 | 版本控制神器GitHub的基本使用与踩坑,教你一铲子填平!

首先需要申请GitHub帐号&#xff0c;这个就不多说了&#xff0c;大家自行百度或Google吧哈。这里默认大家都已经有GitHub账号了~ PS:&#xff08;如果已经配置好的小伙伴可以跳过配置GitHub这部分&#xff09; 配置GitHub 踩坑时刻 - 配置 第一次使用&#xff0c;如果没有配…