历史上的今天
今天是:2024年11月09日(星期六)
2020年11月09日 | 基于STM32的USB程序开发笔记(四)——USB设备的枚举(上)
2020-11-09 来源:eefocus
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;
}
}
史海拾趣
|
恒颐AT91RM9200+CPLD高速大缓存AD采集方案 北京恒颐高科技术有限公司 Beijing Hengyi Embedded System Co.,ltd. 『恒颐高速数据采集产品图』 数据采集系统在工业测控、环境监测等方面的应用非常广泛。随着科学技术的发展,数据采集技术 ...… 查看全部问答> |
|
开关电源变压器铁芯磁滞回线测量-part2开关电源原理与设计(连载60) 从原理上来说,只有RC积分电路输出电压的特性与磁场强度取样电路输出电压的特性(速率)基本一致的时候,磁滞回线的显示失真才会最小。那么u1电压的变化特性与u2电压的变化特性是否基本一致呢?为了简单和便于分析,这里我们把输入电压看成是交流脉 ...… 查看全部问答> |
|
#include void __irq IRQ_TIMER0(void) { T0IR = 0X01; VICVectAddr = 0X00; } int main(void) { VICIntSelect = 0X0 ...… 查看全部问答> |
|
http://campus.chinahr.com/2010/pages/mediatekbj/jobs.asp 看看这个网页 我是做手机驱动与系统开发的 主要是做什么的?迷茫...… 查看全部问答> |
|
wince 5.0 3G如何拨号上网?和GPRS拨号上网有区别吗? wince 5.0 3G如何拨号上网?和GPRS拨号上网有区别吗?以前在WINCE 5.0是通过GPRS拨号上网的。现在要改为3G了,但是拨号拨不上去?怎么回事?高手指点啊。… 查看全部问答> |
|
编译的时候出现: “/cygdrive/d/EmbestIDE/Build/xgcc-arm-elf/bin/arm-elf-ld:.\\ldscript.ld:3: parse error” 然后双击它找错误就会提示: “E:\\cygdrive\\d\\EmbestIDE\\Build\\xgcc-arm-elf\\bin\\arm-elf-ld:.\\ldscript.ld:3中包含 ...… 查看全部问答> |
|
这篇文章从网看发现的,不敢独享拿出共享。 Actel的最新开发环境,我着磨两三天,今天终于装上了。 在附件里: 没安的朋友看看吧,再也不用注册发愁啦 … 查看全部问答> |
|
本帖最后由 paulhyde 于 2014-9-15 03:20 编辑 图中的三极管用来定时放电,电路中可以不焊接, 我还有一个疑惑,就是两个27K电阻是用来作为电压补偿的,但是我在测试时没有27K电阻发现去掉电阻没有什么关系,求解释 … 查看全部问答> |
|
请问:(stm32),tim_period& TIM_PrescalerConfig的区别与应用,如何理解?? TIM_Period 设置了在下一个更新事件装入活动的自动重装载寄存器周期的值。它的取值必须在0x0000和 0xffff之间。 TIM_Prescaler 设置了用来作为TIMx时钟频率除数的预分频值。它的取值必须在0x0000和0xFFFF之间。 但是 ...… 查看全部问答> |




