我用外部控件模式,获取描述符,读回的长度始终只有8个字节。也就是只有端点一的fifo大小。怎么可以连续读到更多的字符?
想问一下,你向端点一写的话,PC端能找到设备吗?
哦,忘记了说明一下,我是主控模式,读取usb打印机的描述符,只读回了8个字节。 代码如下: //端点 const UINT8 SetupGetDevId[] = {// dir type recipient (DEVICE_to_HOST|CLASS_TYPE|INTERFACE_RECIPIENT),//bmRequestTyep 0xA1 0x00, //bRequest 0x00 0x00,0x00, //wValue ConfigIndex 0x00,0x00 0x00, 0x00, //wIndex Interface&AlternateSetting 0x00,0x00 0xf1, 0x03 //wLength 0x01,0x00 };
//获得厂商/设备字符串信息 UINT8 GetStringDescribe(UINT8 type) { UINT8 rstatus; switch(type) { case 0: rstatus = SetupStage(SetupGetStr0Descr); break; case 1: rstatus = SetupStage(SetupGetStr1Descr); break; case 2: rstatus = SetupStage(SetupGetStr2Descr); break; case 3: rstatus = SetupStage(SetupGetDevId); break; default: break; } if((rstatus==USB_INT_SUCCESS)||(rstatus == USB_INT_CONNECT)) /* SETUP阶段操作成功 */ { rstatus=DataStage(); if((rstatus==USB_INT_SUCCESS) ||(rstatus == USB_INT_CONNECT) ) //发送out令牌*/ { ReadUsbData(buffer);//只能读到8个字节 rstatus = StatusStage(); } } return rstatus; }
只留这个问题了。大家帮费费心看看。谢谢了!
你的程序不全啊,这样找不到问题的。
#define USB_CTR_PORT PORTC #define USB_CTR_DDR DDRC #define USB_CTR_PIN PINC #define USB_CS_BIT (1<<7) #define USB_INIT_BIT (1<<6) #define USB_WR_BIT (1<<5) #define USB_RD_BIT (1<<4) #define USB_AO_BIT (1<<3)
#define USB_INT_PIN USB_CTR_PIN&USB_INIT_BIT #define USB_CMD_OPT USB_CTR_PORT|=USB_AO_BIT #define USB_DATA_OPT USB_CTR_PORT&=~USB_AO_BIT #define USB_WR_OPT USB_CTR_PORT&=~USB_WR_BIT #define USB_RD_OPT USB_CTR_PORT&=~USB_RD_BIT
#define USB_DATA_PORT PORTD #define USB_DATA_DDR DDRD #define USB_DATA_PIN PIND
#define USB_OUT_DIR USB_DATA_DDR=0xFF #define USB_IN_DIR USB_DATA_DDR=0x00
#define USB_CMD_WR USB_CMD_OPT;USB_WR_OPT;USB_OUT_DIR #define USB_CMD_RD USB_IN_DIR;USB_CMD_OPT;USB_RD_OPT #define USB_DATA_WR USB_DATA_OPT;USB_WR_OPT;USB_OUT_DIR #define USB_DATA_RD USB_IN_DIR;USB_DATA_OPT;USB_RD_OPT #define USB_ENABLE USB_CTR_PORT&=~USB_CS_BIT #define USB_RELEASE USB_CTR_PORT|=(USB_WR_BIT|USB_RD_BIT|USB_CS_BIT) void InitUsbPort(void) { USB_DATA_DDR=0x00;//输入 USB_DATA_PORT=0xFF;//上拉 USB_CTR_PORT|=(USB_CS_BIT|USB_WR_BIT|USB_RD_BIT|USB_AO_BIT|USB_INIT_BIT); //CS,WR,RD,AO输出高电平,INIT输入上拉 USB_CTR_DDR|=(USB_CS_BIT|USB_WR_BIT|USB_RD_BIT|USB_AO_BIT);//CS,WR,RD,AO输出 USB_CTR_DDR&=~USB_INIT_BIT;//INIT输入 } /* 向CH375的命令端口写入命令,周期不小于4uS,如果单片机较快则延时 */
void Ch375WriteCmdPort(UINT8 cmd) {
USB_DATA_PORT=cmd;//赋值 USB_ENABLE; //打开USB USB_CMD_WR; USB_RELEASE; DelayNus(5); } /* 向CH375的数据端口写入数据,周期不小于1.5uS,如果单片机较快则延时 */
void Ch375WriteDataPort(UINT8 data) { USB_DATA_PORT=data; USB_ENABLE; USB_DATA_WR; USB_DATA_PORT=data; USB_RELEASE; DelayNus(5); } /* 从CH375的数据端口读出数据,周期不小于1.5uS,如果单片机较快则延时 */ UINT8 Ch375ReadDataPort(void) { UINT8 rt; USB_ENABLE; USB_DATA_RD; PORTC=0b00100000; rt=PIND; USB_RELEASE; DelayNus(2); return (rt); } /* CH375初始化子程序 */ BOOL CheckCh375(void) { UINT8 i,j; Ch375WriteCmdPort(CMD_RESET_ALL);/* 多次重复发命令,执行硬件复位 */ DelayNms(40); for(i=0;i<100;i++) { Ch375WriteCmdPort(CMD_CHECK_EXIST); /* 测试CH375是否正常工作 */ Ch375WriteDataPort(0x5A); /* 写入测试数据, 返回数据应该是测试数据取反 */ if((Ch375ReadDataPort())!=0xA5)/* CH375不正常 */ { for(j=0;j<5;j++) { Ch375WriteCmdPort(CMD_RESET_ALL);/* 多次重复发命令,执行硬件复位 */ } DelayNms(40);//ch375要求40ms } else return TRUE; } if(i==100) return FALSE; }
UINT8 Ch375CmdProg(UINT8 cmd,UINT8 arg) { UINT8 i,rdata; for(i=0;i<100;i++) { Ch375WriteCmdPort(cmd); if(arg != 0xFF) Ch375WriteDataPort(arg); rdata=Ch375ReadDataPort(); if((rdata==CMD_RET_SUCCESS)||(rdata==USB_INT_CONNECT)) return TRUE; } return FALSE; }
UINT8 TestConnect(void) { Ch375WriteCmdPort(CMD_TEST_CONNECT); return(Ch375ReadDataPort()); } BOOL WaitInterrupt(void) { // UINT8 i; while(USB_INT_PIN);
// for(i=0;USB_INT_PIN != 0;i++)/* 如果CH375的中断引脚输出高电平则等待,通过计数防止超时 */ // { // DelayUs(); // if(i ==0xF000 ) // Ch375WriteCmdPort(CMD_ABORT_NAK); /* 如果超时达61mS以上则强行终止NAK重试,中断返回USB_INT_RET_NAK */ // } Ch375WriteCmdPort(CMD_GET_STATUS); return(Ch375ReadDataPort()); }
UINT8 GetDescr(UINT8 type ) /* 从设备端获取描述符 */ { Ch375WriteCmdPort(CMD_GET_DESCR); Ch375WriteDataPort(type);/* 描述符类型, 只支持1(设备)或者2(配置) */ return(WaitInterrupt());/* 描述符类型, 只支持1(设备)或者2(配置) */ }
UINT8 SetAddr(UINT8 addr ) /* 设置设备端的USB地址 */ { BOOL rstatus; Ch375WriteCmdPort(CMD_SET_ADDRESS); /* 设置USB设备端的USB地址 */ Ch375WriteDataPort(addr);/* 地址, 从1到127之间的任意值, 常用2到20 */ rstatus=WaitInterrupt(); if((rstatus==USB_INT_SUCCESS)||(rstatus == USB_INT_CONNECT))/* 等待CH375操作完成 */ { Ch375WriteCmdPort(CMD_SET_USB_ADDR);/* 设置USB主机端的USB地址 */ Ch375WriteDataPort(addr); /* 当目标USB设备的地址成功修改后,应该同步修改主机端的USB地址 */ DelayNms(5); } return( rstatus ); } UINT8 SetConfig(UINT8 cfg ) /* 设置设备端的USB配置 */ { tog_send=tog_recv=0;/* 复位USB数据同步标志 */ Ch375WriteCmdPort(CMD_SET_CONFIG);/* 设置USB设备端的配置值 */ Ch375WriteDataPort(cfg);/* 此值取自USB设备的配置描述符中 */ return(WaitInterrupt()); /* 等待CH375操作完成 */ }
// 向CH37X写入数据块 void WriteUsbData(UINT8 len,UINT8 *buf) { Ch375WriteCmdPort(CMD_WR_USB_DATA7);/* 向CH375的端点缓冲区写入准备发送的数据 */ Ch375WriteDataPort(len); /* 后续数据长度, len不能大于64 */ while(len--) { Ch375WriteDataPort(*buf); buf++; } } /* 向CH37X写入数据块 */ void WriteUsbFlashData(UINT8 len,flash UINT8 *buf) { Ch375WriteCmdPort(CMD_WR_USB_DATA7);/* 向CH375的端点缓冲区写入准备发送的数据 */ Ch375WriteDataPort(len); /* 后续数据长度, len不能大于64 */ while(len--) { Ch375WriteDataPort(*buf); buf++; } } // 从CH37X读出数据块 UINT8 ReadUsbData( UINT8 *buf ) { UINT8 i, len,j; Ch375WriteCmdPort(CMD_RD_USB_DATA); /* 从CH375的端点缓冲区读取接收到的数据 */ len=Ch375ReadDataPort(); /* 后续数据长度 */ j=(len>64)? 64 : len; for ( i=0; i { *buf=Ch375ReadDataPort(); buf++; } return( len ); }
/************************************************************************************ 数据同步 USB的数据同步通过切换DATA0(奇数包)和DATA1(偶数包)实现: 在设备端, USB设备可以自动切换; 在主机端, 必须由SET_ENDP6和SET_ENDP7命令控制CH375切换DATA0与DATA1. 主机端的程序处理方法是为设备端的各个端点分别提供一个全局变量, 初始值均为DATA0, 每执行一次成功事务后取反, 每执行一次失败事务后将其复位为DATA1 *************************************************************************************/
/* 主机接收同步控制:0=DATA0,1=DATA1 */ void ToggleRecv(BOOL tog) { Ch375WriteCmdPort(CMD_SET_ENDP6); Ch375WriteDataPort(tog?0xC0:0x80); DelayNus(5); } void ToggleSend( BOOL tog ) /* 主机发送同步控制:0=DATA0,1=DATA1 */ { Ch375WriteCmdPort(CMD_SET_ENDP7); Ch375WriteDataPort(tog?0xC0:0x80); DelayNus(5); } /* 执行USB事务 */ BOOL IssueToken(UINT8 endp_and_pid) /* 高4位目的端点号, 低4位令牌PID */ { /* 执行完成后, 将产生中断通知单片机, 如果是USB_INT_SUCCESS就说明操作成功 */ Ch375WriteCmdPort(CMD_ISSUE_TOKEN); Ch375WriteDataPort(endp_and_pid); return (WaitInterrupt()); /* 等待CH375操作完成 */ } /* // 执行USB事务,适用于CH375A UINT8 IssueTokenX(UINT8 endp_and_pid,UINT8 tog) { // 执行完成后, 将产生中断通知单片机, 如果是USB_INT_SUCCESS就说明操作成功 Ch375WriteCmdPort(CMD_ISSUE_TKN_X); Ch375WriteDataPort(tog); //同步标志的位7为主机端点IN的同步触发位, 位6为主机端点OUT的同步触发位, 位5~位0必须为0 Ch375WriteDataPort(endp_and_pid);// 高4位目的端点号, 低4位令牌PID return(WaitInterrupt()); }*/ //控制传输三个阶段 UINT8 SetupStage(flash UINT8 *pag)//设置事务 { tog_send=tog_recv=0;//复位USB数据同步标志 ToggleSend(0);//SETUP阶段为DATA0 WriteUsbFlashData(8,pag);//SETUP数据总是8字节 return (IssueToken((0<<4)|DEF_USB_PID_SETUP)); } UINT8 DataStage()//输入事务 { ToggleRecv(1); //从接收器接收DATA1 return (IssueToken(( 0 << 4 ) | DEF_USB_PID_IN )); }
UINT8 StatusStage()//输出事务 {