STM32 USB 基础

USB协议简介

简介

USB采用差分串行输入数据,在USB2.0以及之前的版本中,总共包括四个引脚,包括供电端,GOUND,以及数据的D+端和D-端。

USB支持的设备有很多种,常见的包括音频接口,打印机,人机交互设备,下文中的举例主要以人机交互设备(HID)为主

总线信号

信号功能引脚电平
J、K状态用于表示一般逻辑高低J: D+=1, D-=0 K:D+=1, D-=0
Reset设置到未配置状态D+=0,D-=0, 持续10ms
Idle数据发送前后状态电平和J一致
Sync同步信号3次KJ状态切换,后跟随2位时间的K状态
Resume从Idle中恢复
SOP开始状态从Idle切换到k状态
EOP结束状态持续2位时间D+=0, D-=1,后跟随1位时间的J状态

传输包结构

USB传输有清晰的层次结构。一次传输包括多个Transaction,一个Transaction包括多Packet

一个Packet由四部分组成:

SOPSYNCContentEOP
起始信号同步内容结束

包分为四类,命令 (Token) 、Packet 帧首 (Start of Frame) 、Packet 数据 (Data) 、Packet 握手 (Handshake) Packet

其中的SOP、SYNC和EOP的功能在总线信号中已经粗略介绍过

其中的Content分为多个部件,Content的结构一般如下,各个Content包含内容部件会有所不同

PID地址帧号数据校验
包类型目标地址,由8位设备地址和4位端点地址累计发送帧CRC

PID将包分为令牌、数据、握手以及特殊包等。

一个Transaction总是由主机发起,定义四种传输类型:中断传输,等时传输,控制传输和批量传输。注意传输都是由主机发起的,中断传输实际上是周期性向外设发起传输

描述符

当USB设置插入主机时,主机会去尝试获取各个描述符,主要包括设备描述符、配置描述符、接口描述符,相当于设备的初始化过程

设备描述符,主要用于描述厂家,设备版本等

配置描述符,主要用于接口数量和功率设置

接口描述符,主要用于设置接口编号和接口类

端点描述符,主要设置每个端点的地址速度

报告描述符,针对某些设备的设置描述

STM32 USB 库函数

设备描述符

在源文件usbd_desc.c中记录了设备描述符的描述数组

可以通过Cubemx修改字符串的设置

// 各类的描述符和字符串
USBD_DescriptorsTypeDef FS_Desc =
{
  USBD_FS_DeviceDescriptor //设备描述符
, USBD_FS_LangIDStrDescriptor // 字符串的语言ID 
, USBD_FS_ManufacturerStrDescriptor // 厂商字符串
, USBD_FS_ProductStrDescriptor // 产品字符串
, USBD_FS_SerialStrDescriptor // 序列字符串
, USBD_FS_ConfigStrDescriptor // 设置字符串
, USBD_FS_InterfaceStrDescriptor //接口字符串
};

以USB_HID 为例,STM32库函数中在接口描述符码中定义为0x00,表示设备用途在类描述符中定义而非设备描述符中

在usbd_hid*.c中记录了其他的描述符

USBD_ClassTypeDef  USBD_HID =
{
  USBD_HID_Init,    //初始化函数指针
  USBD_HID_DeInit,  //恢复复位函数指针
  USBD_HID_Setup,   
  NULL, /*EP0_TxSent*/
  NULL, /*EP0_RxReady*/
  USBD_HID_DataIn, /*DataIn*/
  NULL, /*DataOut*/
  NULL, /*SOF */
  NULL,
  NULL,
    /*
        不同速度下的其他各类描述符
    */
  USBD_HID_GetHSCfgDesc,
  USBD_HID_GetFSCfgDesc,
  USBD_HID_GetOtherSpeedCfgDesc,
  USBD_HID_GetDeviceQualifierDesc,
};

报告描述符

USB的HID设备通过报告描述符确定通信的格式,在设备的初始化的过程中完成。

报告描述符由通用Item组成,Item分为两种,在HID中主要使用Short Item

Item在起始的1字节中描述了后方数据的长度,Item的类型,Item各个类型的分类标签

Item类型分为三种,包括Main类,Global类、Local类,不同Item描述的数据作用范围不同,这部分可以由生成工具自动生成

在usbd_hid.c中定义了报告描述符

   //自动生成的代码中,没有数据的注释
   //在参考中,有报告描述符的详细解释,我简单介绍下操作的逻辑结构
static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE]={ 
    //描述用途
    //创建集合{
        //集合用途
        //创建数据集合{
            //数据说明
            //}
        //}
}

数据说明中说明了每次传输的各个字节对应位的用处,默认第一个数据的前三位为三个按钮的状态,第二三四个数据分别表示xy和滚轮偏移量。

设置完成后,每次USB发送报告只需要安装报告描述符写好的规定的数据传输即可。

使用函数USBD_HID_SendReport实现发送数据

修改主函数实现如下

#include "main.h"
#include "usb_device.h"
#include "usbd_hid.h"
extern USBD_HandleTypeDef hUsbDeviceFS;
​
void SystemClock_Config(void);
int main(void)
{
    int8_t buff[4]={0};
​
    HAL_Init();
​
    SystemClock_Config();
    MX_USB_DEVICE_Init();
​
    while(1){
        //鼠标左键
        buff[0] = 0x01;
        USBD_HID_SendReport(&hUsbDeviceFS, buff, sizeof(buff));
        HAL_Delay(10);
        buff[0] = 0x00;
        USBD_HID_SendReport(&hUsbDeviceFS, buff, sizeof(buff));
        HAL_Delay(100);
        //鼠标左移
        buff[1] = -100;
        USBD_HID_SendReport(&hUsbDeviceFS, buff, sizeof(buff));
        HAL_Delay(1000);
        buff[1] = 0;
    }
​
}
// 时钟设置应该按照各个芯片的时钟树设置,本实验使用的是STM32F3DISCOVERY
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
​
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB|RCC_PERIPHCLK_USART1
                              |RCC_PERIPHCLK_TIM8;
  PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
  PeriphClkInit.USBClockSelection = RCC_USBCLKSOURCE_PLL_DIV1_5;
  PeriphClkInit.Tim8ClockSelection = RCC_TIM8CLK_HCLK;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}

参考

STMCU USB2.0协议详解

USB协议详解第10讲(USB描述符-报告描述符)一个早起的程序员的博客-CSDN博客usb报告描述符

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: STM32 USB例程是一种用于STM32单片机的USB通信协议示例,它提供了一种可靠而稳定的方式,可以在STM32单片机和其他USB设备之间进行通信和数据传输。 在STM32 USB例程中,STM32单片机作为USB设备,可以与PC、手机、音频设备、键盘、鼠标等USB主机进行通信,支持常见的USB协议,如HID、CDC、MSC等。 使用STM32 USB例程可以快速实现STM32单片机与外界USB设备的通信和数据传输。该例程提供了各种API和函数,可用于配置USB外设、数据收发、状态判断和错误处理等操作,使得开发者可以方便地实现各种USB应用。 同时,STM32 USB例程还提供了丰富的开发工具和示例代码,使得开发者可以快速上手,迅速开发出符合自身需求的USB应用。 总之,STM32 USB例程是一种非常实用的USB通信协议示例,它为STM32单片机提供了可靠和高效的USB通信功能,为各种USB应用的开发提供了强有力的支持。 ### 回答2: STM32 USB例程是指一种用于STM32系列单片机USB通信的程序模板。STM32是意法半导体(STMicroelectronics)公司推出的一款微控制器,拥有广泛的应用领域,包括通信、物联网、工业控制、电子设备等多个领域。而USB则是一种通用的、用于连接计算机和外部设备的接口。使用STM32 USB例程,可以让STM32单片机通过USB接口与计算机进行数据传输、固件升级等操作。 STM32 USB例程一般包含USB 器件驱动和应用程序两部分。其中,USB器件驱动是指实现USB通信的底层软件支持,它实质上是USB协议栈的一种实现,可以与操作系统进行交互,提供底层的USB通讯接口。而应用程序则包括具体的业务逻辑代码,例如数据收发、升级等,它需要在USB器件驱动的基础上实现。 STM32 USB例程的实现需要掌握一定的硬件、软件知识和开发技巧。具体来说,需要了解STM32单片机硬件结构、外设功能及使用方法;掌握USB协议栈的实现原理和相关API函数;熟悉C语言编程、调试、版本控制等基本开发技巧。 总之,STM32 USB例程为STM32单片机提供了一种高效、可靠、快速的USB通信方式,对于工业控制、智能家居、医疗设备等多个领域的应用都具有广泛的意义。通过学习和实践,我们可以深入了解STM32的硬件、软件特性,熟悉嵌入式系统开发流程,提高自己的编程技巧和项目实践能力。 ### 回答3: STM32是一款非常流行的嵌入式系统芯片,它也支持USB接口,用户可以通过USB数据传输接口将STM32与其他设备进行连接,实现数据的输入、输出等功能。 STM32 USB例程是一种通常由STM32芯片厂家或者第三方开发者提供的USB应用程序演示程序。这种USB例程可以帮助用户更快、更容易地开发STM32与其他USB设备之间的交互功能。 例如,STM32 USB例程可以让开发者更快地了解如何与USB设备进行连接、如何实现USB数据传输、如何进行USB设备的控制等等。同时,STM32 USB例程还提供了一些基础USB驱动程序,方便开发者快速开始项目开发。 当然,对于STM32 USB例程,用户还需要具备相关的编程知识和经验。在使用STM32 USB例程时,用户需要先了解USB协议、USB数据传输等基础知识,然后再根据需要进行修改和拓展,以实现自己的项目需求。 总之,STM32 USB例程是一种非常实用的开发工具,它可以帮助开发者更快、更方便地进行USB相关开发。同时,通过学习和使用STM32 USB例程,用户也可以更深入地了解STM32芯片的特性和应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值