我在使用CH357中出现如下问题: 用 get_descr(0x01);//获取设备描述符成功后 用提供的 get_descr(0x02);//获取配置描述符 就可以正常获取配置描述符; 但采用如下:就是所谓的外部固件的方法,就会在 SETUP阶段操作成功后转DATA 阶段错误。 toggle_send(0); wr_usb_data(8,Request.Req_buf); /* Request.Req.bmRequestType=0x80; Request.Req.bRequest=0x06; Request.Req.wValue=0x0002; Request.Req.wIndex=0x0000; Request.Req.wLength=0x0900; */ status=issue_token(( 0 << 4 ) | DEF_USB_PID_SETUP); if(status==USB_INT_SUCCESS)/* SETUP阶段操作成功 */ toggle_recv(0xff); else return(0); // status=issue_token(( 0 << 4 ) | DEF_USB_PID_IN); //在此错误 返回 0x2E if(status==USB_INT_SUCCESS)/* DATA阶段操作成功 */ { ..... }
那肯定是你的程序有问题,可以不可以将程序帖全看下啊
请hcn帮忙指正:
/* 用CH375A操作USB设备 */
#include #include #include "..\SUN\CH375INC.H" #define uchar unsigned char #define uint unsigned int
#define CH375_INT_WIRE (PINE&0x80) /* P3.2, INT0, 连接CH375的INT#引脚 */
unsigned char flag_config_1=0; //第二次获取描述符标志位 unsigned char data_buf[96]; //描述符缓冲区可以适当减小 union _REQUEST //请求包结构 { struct { unsigned char bmRequestType; unsigned char bRequest; unsigned int wValue; unsigned int wIndex; unsigned int wLength; }Req; unsigned char Req_buf[8]; }Request;
// void UART_INIT(void); void TX_OUT(uchar gs); void YS_XXms(uchar loop); void YS_XXus(uchar loop); void CH375_PORT_INIT ( void ); void CH375_WR_CMD_PORT ( uchar commd ); void CH375_WR_DAT_PORT ( uchar data ); uchar CH375_RD_DAT_PORT( void );
#define TRUE 1 #define FALSE 0 //--------------- uchar set_usb_mode( uchar mode ) //设置CH37X的工作模式 { uchar i; // CH375_WR_CMD_PORT( CMD_SET_USB_MODE ); CH375_WR_DAT_PORT( mode ); for( i=0; i!=100; i++ ) { if ( CH375_RD_DAT_PORT()==CMD_RET_SUCCESS ) return( TRUE ); /* 成功 */ } return( FALSE ); /* CH375出错,例如芯片型号错或者处于串口方式或者不支持 */ }
//-------------- void toggle_recv( uchar tog ) { /* 主机接收成功后,切换DATA0和DATA1实现数据同步 */ CH375_WR_CMD_PORT( CMD_SET_ENDP6 ); CH375_WR_DAT_PORT( tog ? 0xC0 : 0x80 ); YS_XXus(2); }
//-------------- void toggle_send( uchar tog ) /* 主机发送成功后,切换DATA0和DATA1实现数据同步 */ { CH375_WR_CMD_PORT( CMD_SET_ENDP7 ); CH375_WR_DAT_PORT( tog ? 0xC0 : 0x80 ); YS_XXus(2); }
//--------------- uchar rd_usb_data( uchar *buf ) //读出数据块 { uchar i, len; // CH375_WR_CMD_PORT( CMD_RD_USB_DATA ); //从CH375的端点缓冲区读取接收到的数据 len=CH375_RD_DAT_PORT(); //后续数据长度 for ( i=0; i!=len; i++ ) *buf++=CH375_RD_DAT_PORT(); return( len ); }
//-------------- void wr_usb_data( uchar len, uchar *buf ) //写入数据块 命令+长度+数据 { CH375_WR_CMD_PORT(CMD_WR_USB_DATA7); //向CH375的端点缓冲区写入准备发送的数据 CH375_WR_DAT_PORT(len); //后续数据长度, len不能大于64 while(len--) CH375_WR_DAT_PORT(*buf++); }
//--------------- uchar wait_interrupt( void ) //主机端等待操作完成, 返回操作状态 { uint i; // for(i=0x00;(CH375_INT_WIRE)!=0;i++) //如果CH375的中断引脚输出高电平则等待,通过计数防止超时 { YS_XXus(1); if(i==0xF000) //如果超时达61mS以上则强行终止NAK重试,中断返回USB_INT_RET_NAK { CH375_WR_CMD_PORT(CMD_GET_STATUS); //产生操作完成中断, 获取中断状态 return(CH375_RD_DAT_PORT()); } } CH375_WR_CMD_PORT(CMD_GET_STATUS); //产生操作完成中断, 获取中断状态 return(CH375_RD_DAT_PORT()); }
//--------------- uchar issue_token( uchar endp_and_pid ) //执行USB事务 { CH375_WR_CMD_PORT( CMD_ISSUE_TOKEN ); CH375_WR_DAT_PORT( endp_and_pid ); /* 高4位目的端点号, 低4位令牌PID */ // return( wait_interrupt() ); /* 等待CH375操作完成 */ }
//----------------- uchar get_report_descr_ex( void ) { uchar descr_len; uchar *p=data_buf; uchar time=1; uchar status; // toggle_send(0); wr_usb_data(8,Request.Req_buf); status=issue_token(( 0 << 4 ) | DEF_USB_PID_SETUP); if(status==USB_INT_SUCCESS)/* SETUP阶段操作成功 */ toggle_recv(0xff); else return(0); // status=issue_token(( 0 << 4 ) | DEF_USB_PID_IN); //在此错误 // data_buf[0]=status; //返回错误 0x2E TX_OUT(1); // if(status==USB_INT_SUCCESS)/* DATA阶段操作成功 */ { if(flag_config_1) descr_len=data_buf[2]-rd_usb_data(data_buf); else descr_len=data_buf[0]-rd_usb_data(data_buf); while(descr_len>0) { if(time) { toggle_recv(0); time=0; } else { toggle_recv(0xff); time=1; } p+=0x08; status=issue_token(( 0 << 4 ) | DEF_USB_PID_IN); if(status==USB_INT_SUCCESS) /* DATA阶段操作成功 */ descr_len-=rd_usb_data(p); else return(0); } } else return(0); // toggle_send(1); wr_usb_data(0,Request.Req_buf); status=issue_token(( 0 << 4 ) | DEF_USB_PID_OUT); if(status==USB_INT_SUCCESS)/* 状态阶段操作成功 */ return(1); else return(0); }
//----------------- void reset_device(void) //复位该设备 { /* USB规范中未要求在USB设备插入后必须复位该设备, 但是计算机的WINDOWS总是这样做, 所以有些USB设备也要求在插入后必须先复位才能工作 */ set_usb_mode( 7 ); //复位USB设备,CH375向USB信号线的D+和D-输出低电平 YS_XXms(10); set_usb_mode( 6 ); //结束复位 YS_XXms(100); while ( wait_interrupt()!=USB_INT_CONNECT ); //等待复位之后的设备端再次连接上来 YS_XXms(200); }
//----------------- uchar get_descr( uchar type ) //从设备端获取描述符 { CH375_WR_CMD_PORT( CMD_GET_DESCR ); CH375_WR_DAT_PORT( type ); //描述符类型, 只支持1(设备)或者2(配置) return( wait_interrupt() ); //等待CH375操作完成 }
//---------------------- void TX_OUT(uchar gs) { uchar tx_data_p; // tx_data_p=0x00; // do{ while( ! (UCSR0A & (1< UDR0=data_buf[tx_data_p]; tx_data_p++; }while(--gs); }
//--------------- void main(void) { uchar len; uchar status; // CH375_PORT_INIT( );//初始化端口 PORTD&=~BIT(2); //开绿色LED UART_INIT( ); //初始化串口 // YS_XXms(250); set_usb_mode( 6 ); //设置USB主机模式, 如果设备端是CH37X, 那么5和6均可 // data_buf[0]=0xaa; //发出AA表示主程序开始 TX_OUT(1); // while(1) { while ( wait_interrupt()!=USB_INT_CONNECT ); //等待设备端连接上来 YS_XXms(5); reset_device(); //复位USB总线 使USB设备重新连接 // status=get_descr(0x01);//获取设备描述符 len=rd_usb_data( data_buf ); TX_OUT(len); //发出设备描述符内容 // /* len=get_descr(0x02);//获取配置描述符 len=rd_usb_data( data_buf ); TX_OUT(len); //发出设备描述符内容 */ Request.Req.bmRequestType=0x80; Request.Req.bRequest=0x06; Request.Req.wValue=0x0002; Request.Req.wIndex=0x0000; Request.Req.wLength=0x0900; // status=get_report_descr_ex(); data_buf[0]=status; TX_OUT(1); //查看是否返回成功 // //TX_OUT(18); //发出获取到的配置描述符内容 // YS_XXms(250); while ( wait_interrupt()!=USB_INT_DISCONNECT ); /* 等待设备端连接上来 */ } }
可以操作的程序已经通过E-MAIL发送给你了,你可以去参考下,主要问题是你在获取设备描述符之后没有设置地址,导致获取配置描述符的时候出现问题
hcn您好! 您发的E-MAIL我没有收到,请在发一次可以吗? 个人信息保护,已隐藏 谢谢!
我也出现这样的问题 麻烦高手帮忙说详细点好吗 获取设备描述符之后要设置地址?
设为多少?