阅读:1230回复:5
usb在枚举的时候令牌包是怎么回事的,当需要两次传输的情况下(急需你的帮忙)
当在usb枚举中,usb的配置描述府一般还包括接口描述府和端点描述府,此时的数据不可能一次发送完,而是分几次发送完的。
我的问题是,当一开始,主机会发送一个读取配置描述府的命令, 然后下面就有IN令牌包,这时设备发送数据给主机。 当数据没有发送完,主机检测到还有剩下的内容时,IN包是主机自己产生,然后才有设备发数据到FIFO, 还是设备先把数据送入FIFO,然后产生中断,这个时候主机才产生一个IN令牌包 谢谢 |
|
沙发#
发布于:2005-01-12 11:07
应该是当数据没有发送完,主机检测到还有剩下的内容时,IN包是主机自己产生,然后才有设备发数据到FIFO
|
|
板凳#
发布于:2005-01-12 11:26
谢谢
如果是这样,那么看来是主机的程序要修改的了, 就不是从机的程序有问题 |
|
地板#
发布于:2005-01-12 11:31
再问一下guowf
这个情况哪里资料有说的,那些主机芯片上面有的吗? |
|
地下室#
发布于:2005-01-12 13:47
///////给你一个程序你看看吧
#include <reg51.h> #include <usbtest.h> char ii[5]; void main() { P1=0xff; XmtBuff.out = 0x00; XmtBuff.in = 0x01; D12_COMMAND = 0xf3;D12_DATA = 0x06;D12_DATA = 0x03;//初始化频率 12MHz D12_COMMAND = 0xd0;D12_DATA = 0x80;//设置地址 0 使能 D12_COMMAND = 0xf3;D12_DATA = 0x16;//连接主机 while(1) { if(!D12_int_n) { D12_COMMAND = 0xf4;// 读中断寄存器 XmtBuff.b[0] = D12_DATA; if(XmtBuff.b[0] & 0x80) { if(D12_suspend == 1) { /** / D12_suspend=0;//处理挂起事务 D12_COMMAND = 0xf6;//发送恢复命令 D12_suspend = 1; /**/ } else { if(XmtBuff.b[0] & 0x15)// 收到 OUT 包 { if(ii[0]==12) ii[0]=ii[0]; if(XmtBuff.b[0] & 0x01) { D12_COMMAND = 0x40;//读 OUT 最后状态 if(D12_DATA & 0x20)// 收到 SETUP 包 { SETUP_read(); HandleSetup(); } }else if(XmtBuff.b[0] & 0x04) { D12_COMMAND = 0x42;//读 OUT 最后状态 }else if(XmtBuff.b[0] & 0x10) { D12_COMMAND = 0x44;//读 OUT 最后状态 } } else if(XmtBuff.b[0] & 0x2a)// 收到 IN 包 { if(ii[1]==18) ii[0]=ii[0]; if(XmtBuff.b[0] & 0x02)XmtBuff.in = 1; else if(XmtBuff.b[0] & 0x08)XmtBuff.in = 3; else if(XmtBuff.b[0] & 0x20)XmtBuff.in = 5; D12_COMMAND = (XmtBuff.in | 0x40);// 读 IN 最后状态 XmtBuff.b[1] = D12_DATA; //if(D12_DATA & 0x01) { ii[1]++; //if(ii[1]==4) //ii[0]=ii[0]; USB_submit(); } } } } } } void HandleSetup(void) { if(ii[0]==10) ii[0]=ii[0]; ii[0]++; if(XmtBuff.b[0] & 0x20)//类请求跳转表 { if (XmtBuff.b[1] <= 0x0B) { //(*ClassFunctionTable[XmtBuff.b[1]])(); return; } } else { if (XmtBuff.b[1] <= 0x0B)//标准请求跳转表 { if (XmtBuff.b[1] == 15) { SetConfiguration(); }else { (*StandardFunctionTable[XmtBuff.b[1]])(); } } return; } } void SETUP_read(void) { char i; D12_COMMAND = 0x00;// 选择端点0(指针指向0位置) D12_COMMAND = 0xf0;// 读标准控制码 XmtBuff.b[0] = D12_DATA; XmtBuff.b[1] = D12_DATA; for(i=0;i<8;i++) { XmtBuff.b = D12_DATA; } D12_COMMAND = 0xf1;// 应答SETUP包,使能(清 OUT 缓冲区、使能 IN 缓冲区)命令 D12_COMMAND = 0xf2;// 清 OUT 缓冲区 } void USB_submit(void) { ii[3]++; if(XmtBuff.rLength>XmtBuff.pNum)XmtBuff.rLength = XmtBuff.pNum; D12_COMMAND = XmtBuff.in;// 选择 IN 端点(指针指向0位置) D12_COMMAND = 0xf0;// 写缓冲区 D12_DATA = 0x00; D12_DATA = XmtBuff.rLength; for(XmtBuff.b[7]=0;XmtBuff.b[7]<XmtBuff.rLength ;XmtBuff.b[7]++) { D12_DATA = *(XmtBuff.p++); } XmtBuff.pNum-=XmtBuff.rLength; if(XmtBuff.in == 1)D12_COMMAND = 0xf1;// 应答SETUP包,使能(清 OUT 缓冲区、使能 IN 缓冲区)命令 D12_COMMAND = 0xfa;// 设置 IN 缓冲区有效(满标志) } void voidfunction(void) { D12_COMMAND = 0x40;// 0 端点停止(用于发送Stall包) D12_DATA = 0x01; D12_COMMAND = 0x41;// 1 端点停止(用于发送Stall包) D12_DATA = 0x01; D12_COMMAND = 0xf1;// 应答SETUP包,使能(清 OUT 缓冲区、使能 IN 缓冲区)命令 } void SetAddress(void) { ii[4]++; D12_COMMAND = 0xd0;//设置新地址使能 D12_DATA = 0x80 | XmtBuff.b[2]; XmtBuff.rLength = 0; USB_submit(); } void GetDescriptor(void) { ii[2]++; XmtBuff.rLength=16; switch (XmtBuff.b[3]) { case 0x01: //USB_DEVICE XmtBuff.pNum = sizeof(device_descriptor); XmtBuff.p = device_descriptor; break; case 0x02:// USB_CONFIGURATION XmtBuff.pNum = Configuration_Descriptor[2]; XmtBuff.p = Configuration_Descriptor; if(XmtBuff.b[6]<16)XmtBuff.pNum = XmtBuff.b[6]; break; case 0x03: //USB_STRING switch(XmtBuff.b[2]) { case 0x00 : XmtBuff.pNum = sizeof(USBStringLanguageDescription); XmtBuff.p = USBStringLanguageDescription; break; case 0x01 : XmtBuff.pNum = sizeof(USBStringDescription1); XmtBuff.p = USBStringDescription1; break; case 0x02 : XmtBuff.pNum = sizeof(USBStringDescription2); XmtBuff.p = USBStringDescription2; break; default : voidfunction(); return; } break; default : voidfunction(); return; } USB_submit(); } void (void) { if (XmtBuff.b[0] == 0x00) { XmtBuff.rLength = 0; USB_submit(); D12_COMMAND = 0xd8; if(XmtBuff.b[2] == 0x00) { D12_DATA = 0x00; // 使用端点0 }else if(XmtBuff.b[2] == 0x01) { D12_DATA = 0x01; // 使用端点1 } } else voidfunction(); } void GetStatus(void) { switch (XmtBuff.b[0]) { case 0x80://返回设备状态 //发送两个字节数据:第一字节D1为1支持远程唤醒,D0为0是总线供电,其它位为0;第二字节为0。 XmtBuff.b[0] = 0x03; XmtBuff.b[1] = 0x00; break; case 0x81://返回接口状态 //发送两个字节数据:第一字节为0;第二字节为0。 //XmtBuff.b[5] 为接口号 XmtBuff.b[0] = 0x00; XmtBuff.b[1] = 0x00; break; case 0x82://返回端点状态 //发送两个字节数据:第一字节D0为1端点处于暂停,否则D0为0,其它位为0;第二字节为0。 //XmtBuff.b[5] D7为方向,D3~0为端点号 XmtBuff.b[0] = 0x00; XmtBuff.b[1] = 0x00; break; } XmtBuff.rLength = 2; XmtBuff.pNum = 2; XmtBuff.p = XmtBuff.b; USB_submit(); } //自定义头文件 usbtest.h sbit D12_suspend=P1^0; sbit D12_int_n=P1^1; sbit D12_eot_n=P1^2; sbit D12_DMAck_n=P1^3; sbit D12_DMAreq=P1^4; sbit p15=P1^5; sbit p16=P1^6; sbit p17=P1^7; #define D12_COMMAND (*(unsigned char xdata *)0x8000) #define D12_DATA (*(unsigned char xdata *)0x0000) void HandleSetup(void); void SETUP_read(void); void USB_submit(void); void GetStatus(void); void ClearFeature(void); void SetFeature(void); void SetAddress(void); void GetDescriptor(void); void SetDescriptor(void); void GetConfiguration(void); void SetConfiguration(void); void GetInterface(void); void SetInterface(void); void voidfunction(void); code void (* StandardFunctionTable[])(void)= { GetStatus,voidfunction,voidfunction,voidfunction, voidfunction,SetAddress,GetDescriptor,voidfunction, voidfunction,SetConfiguration,voidfunction,voidfunction }; /**/ void GetReport(void); void GetIdle(void); void GetProtocol(void); void SetIdle(void); void SetProtocol(void); code void (* ClassFunctionTable[])(void)= { voidfunction, GetReport, GetIdle,GetProtocol, voidfunction, voidfunction, voidfunction,voidfunction, voidfunction, voidfunction, SetIdle,SetProtocol }; /**/ typedef struct { unsigned char b[8]; unsigned char out; unsigned char in; unsigned char rLength; unsigned char pNum; unsigned char *p; }TRANSMIT_STRUCT; TRANSMIT_STRUCT XmtBuff; code char device_descriptor[] = { 0x12, // 描述表大小 (18 bytes) 0x01, // 设备描述表类型 0x10, 0x01, // 兼容设备版本号(BCD码) 0x00, // 设备类码 0x00, // 子类码 0x00, // 协议码 0x10, // 端点0最大包大小(8,16,32,64) 0x71, 0x04, // 厂商ID 0x11, 0x11, // 产品ID 0x01, 0x00, // 设备发行号(BCD码) 0x01, // 厂商信息字符串索引 0x02, // 产品信息字符串索引 0x00, // 设备序列号字符串索引(不支持设为0) 0x01 // 配置数 }; code char Configuration_Descriptor[] = { 0x09, // 配置描述表长度 0x02, // 配置描述表类型 0x20,0x00, // 配置描述表及附带表长度 0x01, // 接口配置数 0x01, // 配置描述表标识 0x00, // 配置描述表字符串描述表索引 0xa0, // 配置属性 0x64 // 总线供电最大值(*2mA) }; code char Interface_Descriptor[] = { 0x09, // 接口描述表长度(9) 0x04, // 接口描述表类型 0x00, // 接口数(0) 0x00, // 轮寻设置(0 号端点) 0x02, // 端点数 (4) 0x03, // 接口类属 0x01, // 子类码 0x02, // 协议码 0x00 // 接口字符串描述表索引(不支持) }; code char Endpoint_Descriptor_t[] = { 0x07, // 端点描述表长度(7) 0x05, // 端点描述表类型 0x81, // IN 端点(1) 0x02, // 传输模式(0 控制、1 同步、2 批、3 中断传输) 0x10, 0x00, // 最大包大小(16) 0x0A // 轮寻时间 (10ms) }; code char Endpoint_Descriptor_r[] = { 0x07, // 端点描述表长度(7) 0x05, // 端点描述表类型 0x01, // OUT 端点(1) 0x02, // 传输模式(0 控制、1 同步、2 批、3 中断传输) 0x10, 0x00, // 最大包大小(16) 0x0A // 轮寻时间 (10ms) }; code char USBStringLanguageDescription[] = { sizeof(USBStringLanguageDescription), // 字符串描述表长度 0x03, // 字符串描述表类型 0x09, // 语言标识(9 英语) 0x04 // 子语言标识: Default }; code char USBStringDescription1[] = { sizeof(USBStringDescription1), 0x03, 'C',0,'y',0,'p',0,'r',0,'e',0,'s',0,'s',0,' ' }; code char USBStringDescription2[] = { sizeof(USBStringDescription2), 0x03, 'C',0,'y',0,'p',0,'r',0,'e',0,'s',0,'s',0,' ' }; |
|
5楼#
发布于:2005-01-12 15:19
谢,偶要好好研究一下
|
|