saite136
驱动牛犊
驱动牛犊
  • 注册日期2004-05-12
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分51分
  • 威望10点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:1230回复:5

usb在枚举的时候令牌包是怎么回事的,当需要两次传输的情况下(急需你的帮忙)

楼主#
更多 发布于:2005-01-12 10:14
当在usb枚举中,usb的配置描述府一般还包括接口描述府和端点描述府,此时的数据不可能一次发送完,而是分几次发送完的。

我的问题是,当一开始,主机会发送一个读取配置描述府的命令,
然后下面就有IN令牌包,这时设备发送数据给主机。

当数据没有发送完,主机检测到还有剩下的内容时,IN包是主机自己产生,然后才有设备发数据到FIFO,
还是设备先把数据送入FIFO,然后产生中断,这个时候主机才产生一个IN令牌包

谢谢
guowf
驱动牛犊
驱动牛犊
  • 注册日期2002-12-15
  • 最后登录2006-04-27
  • 粉丝0
  • 关注0
  • 积分20分
  • 威望3点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2005-01-12 11:07
应该是当数据没有发送完,主机检测到还有剩下的内容时,IN包是主机自己产生,然后才有设备发数据到FIFO
saite136
驱动牛犊
驱动牛犊
  • 注册日期2004-05-12
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分51分
  • 威望10点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2005-01-12 11:26
谢谢
如果是这样,那么看来是主机的程序要修改的了,
就不是从机的程序有问题
saite136
驱动牛犊
驱动牛犊
  • 注册日期2004-05-12
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分51分
  • 威望10点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2005-01-12 11:31
再问一下guowf
这个情况哪里资料有说的,那些主机芯片上面有的吗?
guowf
驱动牛犊
驱动牛犊
  • 注册日期2002-12-15
  • 最后登录2006-04-27
  • 粉丝0
  • 关注0
  • 积分20分
  • 威望3点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
地下室#
发布于: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,' '
};

saite136
驱动牛犊
驱动牛犊
  • 注册日期2004-05-12
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分51分
  • 威望10点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2005-01-12 15:19
谢,偶要好好研究一下
游客

返回顶部