我想用CH375,CH374和导航仪的USB口连接,把单片机采集的数据发给导航仪,目前用参考样例的程序可以连接并发送数据了,但不是很流畅,有时收不到。有两个问题需要大家帮帮忙: 1。作为host跟其他usb设备通讯,是否CH374更好? 2。USB_INT_DISK_WRITE,USB_INT_DISK_READ 是否只能用在读U盘时,返回中断状态中才会出现?
1,如果对速度有要求的话,同时是高速单片机和CH374芯片连接的话,那么推荐使用CH374 2 你所说的2条命令是只能用于对U盘的读写时中断状态返回。 不知道你采集的速度是多快?导航仪是个什么USB设备?和计算机通信的速度是多快?这样也好确定问题在什么地方?
1. 我用的是STC89C52单片机,速度不快,不知道CH374编程是否需要更多理解USB协议 我的现在是单片机用串口连接PC的串口,用CH375连接导航仪的USB otg(device)。用PC电脑模拟把数据传给导航仪,采集数据方面还没试。
2。如果这个状态不能查询,是否还能用其他的方法知道,当CH375置中断位为零时,我如何知道我是可以写数据还是可以读数据。以下是我的部分程序:
void CH375_WR_CMD_PORT( unsigned char cmd ) { _nop_(); _nop_(); CH375_CMD_DAT = 1; /* ?üá? */ CH375_DATA_PORT = cmd; CH375_RD = 1; CH375_WR = 0; _nop_(); _nop_(); CH375_WR = 1; CH375_CMD_DAT = 0; CH375_DATA_PORT = 0xFF; }
void CH375_WR_DAT_PORT( unsigned char dat ) { _nop_(); CH375_CMD_DAT = 0; /* êy?Y */ CH375_DATA_PORT = dat; CH375_RD = 1; CH375_WR = 0; _nop_(); CH375_WR = 1; CH375_DATA_PORT = 0xFF; }
unsigned char CH375_RD_DAT_PORT(void) { unsigned char rev_data; CH375_DATA_PORT = 0xFF; CH375_CMD_DAT = 0; CH375_WR = 1; CH375_RD = 0; _nop_(); rev_data = CH375_DATA_PORT; CH375_RD = 1; return( rev_data ); }
unsigned char wait_interrupt(void) { CH375_INT_WIRE = 1; while( CH375_INT_WIRE ) { if( RI==1 ) /* ´®¿Ú½ÓÊÕµ½Êý¾Ý */ { CH375_WR_CMD_PORT( CMD_ABORT_NAK ); /* ·ÅÆúµ±Ç°²Ù×÷ */ return( 0xEF ); } } CH375_WR_CMD_PORT( CMD_GET_STATUS ); return( CH375_RD_DAT_PORT() ); }
/* éè??CH37Xμ?1¤×÷?£ê? */ void set_usb_mode( unsigned char mode ) { unsigned char i; CH375_WR_CMD_PORT( CMD_SET_USB_MODE ); CH375_WR_DAT_PORT( mode ); endp6_mode=endp7_mode=0x80; for( i=100; i!=0; i-- ) { if( CH375_RD_DAT_PORT() == CMD_RET_SUCCESS ) return; } while(1) { flash_led(); } }
void toggle_recv(void) { CH375_WR_CMD_PORT( CMD_SET_ENDP6 ); CH375_WR_DAT_PORT( endp6_mode ); endp6_mode^=0x40; delay2us(); }
void toggle_send(void) { CH375_WR_CMD_PORT( CMD_SET_ENDP7 ); CH375_WR_DAT_PORT( endp7_mode ); endp7_mode^=0x40; delay2us(); }
unsigned char clr_stall6(void) { CH375_WR_CMD_PORT( CMD_CLR_STALL ); CH375_WR_DAT_PORT( 2 ); endp6_mode=0x80; return( wait_interrupt() ); }
unsigned char clr_stall7(void) { CH375_WR_CMD_PORT( CMD_CLR_STALL ); CH375_WR_DAT_PORT( endp_out_addr ); endp7_mode=0x80; return( wait_interrupt() ); }
unsigned char rd_usb_data( unsigned char *buf ) { unsigned char len, length; CH375_WR_CMD_PORT( CMD_RD_USB_DATA ); len=CH375_RD_DAT_PORT(); length=len; while( len-- ) { *buf = CH375_RD_DAT_PORT(); buf++; } return( length ); }
void wr_usb_data( unsigned char len, unsigned char *buf ) { CH375_WR_CMD_PORT( CMD_WR_USB_DATA7 ); CH375_WR_DAT_PORT( len ); while( len-- ) { CH375_WR_DAT_PORT( *buf ); buf++; } }
unsigned char issue_token( unsigned char endp_and_pid ) { unsigned char status; CH375_WR_CMD_PORT( CMD_ISSUE_TOKEN ); CH375_WR_DAT_PORT( endp_and_pid ); status = wait_interrupt(); return( status ); }
void host_send( unsigned char len, unsigned char *buf ) { unsigned char status; unsigned char length; led=1; while( len ) { if( len>endp_out_size ) length=endp_out_size; else length=len; wr_usb_data( length, buf ); toggle_send(); status = issue_token( ( endp_out_addr << 4 ) | DEF_USB_PID_OUT ); if( status==USB_INT_SUCCESS ) { len -= length; buf += length; } else if( status==0xEF ) { led=0; return; } else if( status != 0xEF ) { clr_stall7(); } } led=0; }
unsigned char host_recv( unsigned char *buf ) { unsigned char status; if( endp_in_addr ) { toggle_recv(); status = issue_token( ( endp_in_addr << 4 ) | DEF_USB_PID_IN ); // status = issue_token( ( 2 << 4 ) DEF_USB_PID_IN ); if( status==USB_INT_SUCCESS ) { status = rd_usb_data( buf ); return( status ); } else if( status==USB_INT_DISCONNECT ) { return( 0xFE ); } else { clr_stall6(); return( 0xFF ); } } return( 0xFF ); /* ·μ??2ù×÷꧰ü */ }
unsigned char get_descr( unsigned char type ) /* ′óéè±?????è??èê?·? */ { CH375_WR_CMD_PORT( CMD_GET_DESCR ); CH375_WR_DAT_PORT( type ); /* ?èê?·?ààDí, ???§3?1(éè±?)?ò??2(????) */ return( wait_interrupt() ); /* μè′yCH3752ù×÷íê3é */ }
unsigned char set_addr( unsigned char addr ) /* éè??éè±???μ?USBμ??· */ { unsigned char status; CH375_WR_CMD_PORT( CMD_SET_ADDRESS ); /* éè??USBéè±???μ?USBμ??· */ CH375_WR_DAT_PORT( addr ); /* μ??·, ′ó1μ?127????μ?è?òa?μ, 3£ó?2μ?20 */ status=wait_interrupt(); /* μè′yCH3752ù×÷íê3é */ if( status==USB_INT_SUCCESS ) /* 2ù×÷3é1| */ { CH375_WR_CMD_PORT( CMD_SET_USB_ADDR ); /* éè??USB?÷?ú??μ?USBμ??· */ CH375_WR_DAT_PORT( addr ); /* μ±??±êUSBéè±?μ?μ??·3é1|DT??oó,ó|??í?2?DT???÷?ú??μ?USBμ??· */ } return( status ); }
unsigned char set_config( unsigned char cfg ) /* éè??éè±???μ?USB???? */ { endp6_mode=endp7_mode=0x80; /* ?′??USBêy?Yí?2?±ê?? */ CH375_WR_CMD_PORT( CMD_SET_CONFIG ); /* éè??USBéè±???μ??????μ */ CH375_WR_DAT_PORT( cfg ); /* ′??μè?×?USBéè±?μ??????èê?·??D */ return( wait_interrupt() ); /* μè′yCH3752ù×÷íê3é */ }
void SendChars( unsigned char *buff ) { unsigned char buf; while(1) { buf = *buff; if( buf == 0x00 ) break; SBUF = buf; buff++; while( !TI ); TI=0; } }
void receive(void) { unsigned int count; unsigned char buf; RECV_LEN=0; cmd_buf = RECV_BUFFER; /* ?óê??o3??? */ while( 1 ) { RI=0; *cmd_buf = SBUF; cmd_buf++; RECV_LEN++; if( RECV_LEN == 64 ) { while( 1 ) { count=10000; while( RI==0 ) { count--; if( count==0 ) return; } RI=0; buf=SBUF; } } count=10000; while( RI==0 ) { count--; if( count==0 ) return; } } }
void main(void) { unsigned char i; unsigned char length; delay1s(); CH375_Init(); //initial CH375 host , test and set mode 6; ComInit(); //init Uart Port SendChars("USB Init OK\n");
led=0; while(1) { led=0; while (1) { if( wait_interrupt() == USB_INT_CONNECT ) { SendChars( "Device Connect\n" ); break; } } set_usb_mode( 7 ); delay50ms(); set_usb_mode( 6 ); while (1) { if( wait_interrupt() == USB_INT_CONNECT ) SendChars( "Device re-connect\n" ); break; } delay1s(); for( i=5;i!=0;i-- ) { if( init_USB_device() != USB_INT_SUCCESS ) { SendChars("device init failed\n"); flash_led(); //′í?ó } else { break; } } if( i==0 ) { flash_led(); continue; } while(1) { ret_buf = RECV_BUFFER; length = host_recv( ret_buf ); if( length == 0xEF ) { led=1; receive(); led=0; ret_buf = RECV_BUFFER; length = RECV_LEN; if( length!=0 ) host_send( length, ret_buf ); } else if( length == 0xFE ) { SendChars( "USB_Disconnect\n" ); break; } else if( length != 0xFF ) { ret_buf = RECV_BUFFER; while( length-- ) { SendChar( *ret_buf ); ret_buf++; } } } } }
1,首先你需要确认你通信不流畅是因为串口那边的问题还是USB口这边的问题,需要确认问题之后才好解决问题。 2,根据USB特性,作为USB主机端是是通信的发起者,所以你应该自己确认应该发还是应该收数据,按照计算机的操作方式是这样,在检测到设备连接之后,是不断的发送IN的令牌包,这个IN的令牌包的间隔为1MS左右。运用到你的实际设备上面应该这样: 串口开中断接收数据,单片机不断的通过CH375发送IN的令牌包来取数据,当有取到数据就通过串口发送出去。如果没有就继续取数据。当串口来数据时,这个时候主机发送一包OUT令牌包出去,同时把数据发送出去。这样应该就没有问题了。
感谢hcn提醒,你真热心啊,我再根据你的思路研究研究。 另外还有一个问题是我的CH375链接导航仪USB otg(device)时,这个usb otg老是不断的连接,过几秒后又断开,又开始链接,如果发送或接受数据时,它就不会断开或连接,根据设备描述符2的得到的信息,这个usb otg设备是自供电,最大需求电流0(即:配置描述符的bmAttributes=1100 0000,MaxPower=0)。 如果我把usb otg连到电脑上,在设备管理器里也是这样链接又断开,又连接。只有打开microsoft activesync后,usb otg就一直连着PC,在设备管理器里也不闪了,不知道CH375是否能设置一直让它连接着?
建议你使用一款软件叫“BUSHOUND”,你采用这个软件看下在你打开microsoft activesync软件之后,计算机给你的导航仪发送了什么命令,CH375按照导航仪的命令来发,这样的话就不会出现你说的问题。
还是网上高人多啊!