基于STM32的USB程序开发笔记(四)——USB设备的枚举(上)

发布者:Mengyun最新更新时间:2020-11-09 来源: eefocus关键字:STM32  USB程序  USB设备  枚举 手机看文章 扫描二维码
随时随地手机看文章

USB设备能否工作,枚举步骤,用“乡村爱情”里的话说,“必须的!”,网上也有很多资料,圈圈就提供了一份详细的枚举过程,但对STM32是怎么响应的没有说明,一会详细道来,先上圈圈的提供的那个枚举图示,希望圈圈支持,如果不妥,请与我联系,谢谢。 

我将此转换成了PDF文件,方便查看。

首先说明一个变量,定义在usb_core.c中: 

volatile DEVICE_INFO vsDeviceInfo; 

看意思就知道他的作用了,DEVICE_INFO是个结构,定义在usb_type.h中: 

// ***************************************************************************** 

// DEVICE_INFO 

// ***************************************************************************** 

typedef struct _DEVICE_INFO 

  unsigned char bDeviceAddress; 


  unsigned char bCurrentFeature; 

  unsigned char bCurrentConfiguration; 

  unsigned char bCurrentInterface; 

  unsigned char bCurrentAlternateSetting; 


  WORD_2BYTE    uStatusInfo; 


  DEVICE_STATE  eDeviceState; 

  RESUME_STATE  eResumeState; 

  CONTROL_STATE eControlState; 


  SETUP_DATA    SetupData; 


  TRANSFER_INFO TransInfo; 

DEVICE_INFO, 

*PDEVICE_INFO; 


在枚举过程中,就是如何处理好SETUP事件,如果STM32 USB接收到正确的SETUP事件,将响应函数CTR_SETUP0(),SETUP事件是特殊的OUT事件,数据方向 Host->Device,SETUP事件数据长度固定为8,数据定义在DEVICE_INFO.SetupData,其数据结构是(定义在 usb_type.h中): 

typedef struct _SETUP_DATA 

  unsigned char bmRequestType;            // request type 

  unsigned char bRequest;                 // request code 


  WORD_2BYTE wValue; 

  WORD_2BYTE wIndex; 

  WORD_2BYTE wLength; 

SETUP_DATA, 

*PSETUP_DATA; 


WORD_2BYTE是定义的一个共用体: 

typedef union _WORD_2BYTE 

  unsigned short w; 

  struct 

  { 

    unsigned char LSB; 

    unsigned char MSB; 

  }b; 

WORD_2BYTE; 


为什么将SETUP数据结构中的wValue,wIndex,wLength如此定义? 

1:USB协议中所有数据传输都是依照低位在先的原则 

2:高地位字节可能功能复用 

这样在后续的程序编写中就变得十分方便,ST提供的USB固件方法同样如此,但这方面的处理让人有些摸不着头脑,详情可参阅。至于具体的SETUP数据结构含义如何,还是要具备基本知识:了解USB协议 


CTR_SETUP0() 函数将SETUP数据提取出来,SETUP数据结构有0长度和非0长度的数据结构,详细参阅USB2.0官方协议第9章。在这将两种区别开来分别执行 SETUP0_NoData()和SETUP0_Data()函数,并返回结果,根据返回结果再响应USB主机 

// ***************************************************************************** 

// Function Name  : CTR_SETUP0 

// Description    : 

// Input          : 

// Output         : 

// Return         : 

// ***************************************************************************** 

void CTR_SETUP0(void) 

  RESULT eResult; 


  BufferCopy_PMAToUser( (unsigned char *)&vsDeviceInfo.SetupData, 

                        GetBuffDescTable_RXAddr(ENDP0), 

                        GetBuffDescTable_RXCount(ENDP0)); 


  if(vsDeviceInfo.SetupData.wLength.w == 0) 

  { 

    eResult = SETUP0_NoData(); 

  } 

  else 

  { 

    eResult = SETUP0_Data(); 

  } 


  switch(eResult) 

  { 

  case RESULT_SUCCESS: 


    break; 


  case RESULT_LASTDATA: 


    break; 


  case RESULT_ERROR: 

  case RESULT_UNSUPPORT: 

    SetEPR_RXStatus(ENDP0, EP_RX_VALID); 

    SetEPR_TXStatus(ENDP0, EP_TX_STALL); 

    break; 

  } 


SETUP0_Data() 和SETUP0_NoData()函数支持的所有USB请求类型只有罗列的这些,有多少种组合都定义在USB协议中,程序根据请求代码,再去执行对应函数,这样做的目的就是让程序结构明了。其中注释为"// done"的部分表明此部分功能已完成。对于未完成部分,希望大家在交流中完善。 


// ***************************************************************************** 

// Routine Groups: SETUP_Data 

// ***************************************************************************** 

RESULT SETUP0_Data(void) 

  // SetupData.bRequest: request code 

  switch(vsDeviceInfo.SetupData.bRequest) 

  { 

  case SR_GET_STATUS:         return SR_GetStatus();                  // done 

  case SR_GET_DESCRIPTOR:     return SR_GetDescriptor();              // done 

  case SR_SET_DESCRIPTOR:     return SR_SetDescriptor();              // unsupport 

  case SR_GET_CONFIGURATION:  return SR_GetConfiguration();           // done 

  case SR_GET_INTERFACE:      return SR_GetInterface();               // unsupport 

  case SR_SYNCH_FRAME:        return SR_SynchFrame();                 // unsupport 


  default: return RESULT_UNSUPPORT; 

  } 


// ***************************************************************************** 

// Routine Groups: SETUP_NoData 

// ***************************************************************************** 

RESULT SETUP0_NoData(void) 

  // SetupData.bRequest: request code 

  switch(vsDeviceInfo.SetupData.bRequest) 

  { 

  case SR_CLEAR_FEATURE:      return SR_ClearFeature();        // unsupport 

  case SR_SET_FEATURE:        return SR_SetFeature();          // unsupport 

  case SR_SET_ADDRESS:        return SR_SetAddress();          // done 

  case SR_SET_CONFIGURATION:  return SR_SetConfiguration();    // done 

  case SR_SET_INTERFACE:      return SR_SetInterface();        // unsupport 


  default: return RESULT_UNSUPPORT; 

  } 

}


关键字:STM32  USB程序  USB设备  枚举 引用地址:基于STM32的USB程序开发笔记(四)——USB设备的枚举(上)

上一篇:STM32的嵌套中断系统NVIC和RCC详细整理
下一篇:基于STM32的USB枚举过程学习笔记

推荐阅读最新更新时间:2024-11-04 04:05

基于STM32微处理器的GPRS数据传输技术的研究
STM32是意法半导体(ST)公司推出的基于ARM Cortex-M3内核的主流产品之一,它是ST公司专门针对要求高性能、低功耗和低成本的嵌入式应用而设计的,目前已在各领域得到广泛的应用。SIM900A是SIMCom公司主推的一款紧凑型的GSM/GPRS双频模块产品,它以性能稳定、外观精巧及性价比高的优点深受广大工程师青睐。  本文通过对STM32底层配置以及数据传输的研究,介绍STM32主要的底层配置,并着重介绍数据传输的实现。通过关键步骤的程序源代码的介绍,阐述实现数据传输的细节以及注意事项。该方法对其他项目或芯片有一定的实现价值和参考价值,且简单可靠,具有普遍性和通用性。 1 STM32底层配置  为了实现STM32单片机与
[单片机]
STM32的ADC实验的原理简介
ADC简介 Analog-to-Digital Converter的缩写。指模/数转换器或者模拟/数字转换器。是指将连续变量的模拟信号转换为离散的数字信号的器件。 STM32的ADC的配置 战舰V3开发板的ADC通道与引脚的对应关系 模拟量输入的范围(ADC正常工作的范围) STM32F103ZET6芯片中的电源部分(VREF与VSSA): 我们看到Vref-连接到了GND,而VREF+通过跳线帽连接到了VDD(VDD连接到了开发板的3.3V供电电源上),因此我们的DAC通道正常工作的模拟量输入范围为(2.4V,3.3V)。 ADC工作逻辑图解析(以ADC通道1为例) ADC中断的三种类型 注入
[单片机]
<font color='red'>STM32</font>的ADC实验的原理简介
STM32使用J-Link仿真相关汇总
目录: 一、SWD实时仿真接线 二、仿真设置 三、仿真时问题的解决 1、仿真时添加变量或数组 2、程序下载 3、尽量不要由J-Link给线路板供电 4、仿真器与线路板连接需可靠 5、使用J-Link时,Keil软件出现无响应 ---------------------------------------- 所有的操作基于WIN XP,stm32使用J-Link(SWD模式)。 另可参见 系统、软件、数码 / Keil编译软件的使用汇总 (三、Keil5.12编译报错的处理)。 ----------------------------------------------------------------------------
[单片机]
<font color='red'>STM32</font>使用J-Link仿真相关汇总
STM32外部中断步骤
tm32外部中断就是某种外部事件发生时,单片机的中断系统将迫使CPU暂停正在执行的程序,转而去进行中断事件的处理的一个过程,此博客的目的就是我在学习外部中断的程序步骤: 1.首先进行分配时钟: //以按键的外部中断为例 RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);//给按键的GPIO进行分配时钟; typedef struct { uint16_t GPIO_Pin; GPIOSpeed_TypeDef GPIO_Speed; //设置GPIOD的速度,有10hz、20hz、50hz GPIOMode_TypeDef GPI
[单片机]
STM32---定时器的ETR功能
  在使用定时器的时候,在引脚复用功能中看到了TIM2_CH1_ETR,这个ETR是什么意思呢?   答:TIM2_CH1_ETR表示两个功能选一个,分别是TIM2_CH1和TIM2_ETR,TIM2_CH1表示让这个引脚作为TIM2的第一通道对应引脚;TIM2_ETR表示让这个引脚作为TIM2外部时钟提供引脚,这种功能有两种模式,如下图:
[单片机]
STM32---定时器的ETR功能
STM32ADC单次转换DMA读取
DMA读取方式很适合高频率的ADC采样信号。 ADC的DMA读取方式,其实和上一篇的中断读取方式差不多,初始化代码更是相似。初始化代码如下: static void ADC_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //ʹÄÜPB,PE¶Ë¿ÚʱÖÓ GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN; GPIO_Init(
[单片机]
基于STM32的矿用本质安全型电源设计
0 引言 本安电源是本安型电气设备的一个重要组成部分,由于煤矿的机械化,井下传感器、弯道报警器等设备的供电,通信、报警都需要供电设备。但是基于井下复杂的环境,对供电设备的要求也是非常严格的,它要求电源电路的内部和引出线无论是在正常工作还是在故障状态下都是安全的并且产生的电火花不会点燃周围环境中的爆炸性混合物。本安电源有“ia”和“ib”两个等级。在本文中介绍的本安电源是井下常用的“ia”等级,也就是说在一个故障,一套保护电路损坏的情况下也能继续工作。 1 本安电源的组成及工作原理 1.1 电源 本系统中本安电源的输入+Vin、-Vin为48 V直流电源,经过DC/DC电源转换模块(U1)输出12 V直流电,U2是7
[单片机]
基于<font color='red'>STM32</font>的矿用本质安全型电源设计
STM32-(31):独立看门狗
在嵌入式系统中,由于MCU(微控制单元:Microcontroller Unit)的工作常常会受到来自外界电磁场的干扰,造成程序的跑飞,而陷入死循环,程序的正常运行被打断,由单片机控制的系统无法继续工作,会造成整个系统的陷入停滞状态,发生不可预料的后果,所以出于对单片机运行状态进行实时监测的考虑,便产生了一种专门用于监测程序运行状态的模块,俗称 看门狗 (watchdog) 在系统运行以后也就启动了看门狗的计数器,看门狗就开始自动计数,如果到了一定的时间还不去清看门狗,那么看门狗计数器就会溢出从而引起看门狗中断,造成系统复位。所以在使用有看门狗的时候要注意清看门狗。 看门狗是恢复系统的正常运行及有效的监视管理器(具有锁定光驱,锁定
[单片机]
STM32-(31):独立看门狗
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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