我用CH375分別做master、slaver,成功對接,兩片51的串口分別接PC的com口,可以通過com口收發(fā)數(shù)據,下面是我的程序,供大家參考 master.c /*************************************** ** USB 1.1 Host for CH375 ** ** 單片機用89C51 ** ****************************************/ /* 如果設備端不是CH37X,那么分析描述符 */ /* CH375中斷為查詢方式 */
#include #include #include #include #include "CH375INC.H"
#define DELAY_START_VALUE 1 /* 根據單片機的時鐘選擇延時初值 */ #define UNKNOWN_USB_DEVICE 0xF1 #define USB_INT_RET_NAK 0x2A /* 00101010B,返回NAK */
typedef struct _USB_DEVICE_DESCRIPTOR { unsigned char bLength; unsigned char bDescriptorType; unsigned short bcdUSB; unsigned char bDeviceClass; unsigned char bDeviceSubClass; unsigned char bDeviceProtocol; unsigned char bMaxPacketSize0; unsigned short idVendor; unsigned short idProduct; unsigned short bcdDevice; unsigned char iManufacturer; unsigned char iProduct; unsigned char iSerialNumber; unsigned char bNumConfigurations; } USB_DEV_DESCR, *PUSB_DEV_DESCR;
typedef struct _USB_CONFIG_DESCRIPTOR { unsigned char bLength; unsigned char bDescriptorType; unsigned short wTotalLength; unsigned char bNumInterfaces; unsigned char bConfigurationValue; unsigned char iConfiguration; unsigned char bmAttributes; unsigned char MaxPower; } USB_CFG_DESCR, *PUSB_CFG_DESCR;
typedef struct _USB_INTERF_DESCRIPTOR { unsigned char bLength; unsigned char bDescriptorType; unsigned char bInterfaceNumber; unsigned char bAlternateSetting; unsigned char bNumEndpoints; unsigned char bInterfaceClass; unsigned char bInterfaceSubClass; unsigned char bInterfaceProtocol; unsigned char iInterface; } USB_ITF_DESCR, *PUSB_ITF_DESCR;
typedef struct _USB_ENDPOINT_DESCRIPTOR { unsigned char bLength; unsigned char bDescriptorType; unsigned char bEndpointAddress; unsigned char bmAttributes; unsigned short wMaxPacketSize; unsigned char bInterval; } USB_ENDP_DESCR, *PUSB_ENDP_DESCR;
typedef struct _USB_CONFIG_DESCRIPTOR_LONG { USB_CFG_DESCR cfg_descr; USB_ITF_DESCR itf_descr; USB_ENDP_DESCR endp_descr[4]; } USB_CFG_DESCR_LONG, *PUSB_CFG_DESCR_LONG;
unsigned char RECV_LEN; /* 剛接收到的數(shù)據的長度 */ unsigned char idata RECV_BUFFER[ CH375_MAX_DATA_LEN ]; /* 數(shù)據緩沖區(qū),用于保存接收到的下傳數(shù)據,長度為0到64字節(jié) */ unsigned char idata *cmd_buf; unsigned char idata *ret_buf;
#define p_dev_descr ((PUSB_DEV_DESCR)RECV_BUFFER) #define p_cfg_descr ((PUSB_CFG_DESCR_LONG)RECV_BUFFER)
unsigned char endp_out_addr; /* USB數(shù)據接收端點的端點地址 */ unsigned char endp_out_size; /* USB數(shù)據接收端點的端點尺寸 */ unsigned char endp_in_addr; /* USB狀態(tài)發(fā)送端點的端點地址,為0則只支持單向接口 */ unsigned char endp6_mode, endp7_mode;
/* Ch375與51等的連接 CH375 51 D0 P1.0 . . . . . . D7 P1.7 A0 P3.7 RD P3.5 WR P3.4 CS 接地 INT P3.2(int0) */ #define CH375_DATA_PORT P1 /* CH375端口的I/O地址 */ sbit CH375_CMD_DAT = P3^7; /* CH375地址線輸入A0,A0=1時寫命令,A0=0時讀寫數(shù)據 */ sbit CH375_RD = P3^5; /* CH375讀選通輸入,低電平有效 */ sbit CH375_WR = P3^4; /* CH375寫選通輸入,低電平有效 */ sbit led = P3^3; /* 指示燈 */ sbit CH375_INT_WIRE = P3^2; /* CH375中斷請求輸出,低電平有效 */
void delay50ms(void); void delay1s(void); void flash_led(void); void CH375_WR_CMD_PORT( unsigned char cmd ); void CH375_WR_DAT_PORT( unsigned char dat ); unsigned char CH375_RD_DAT_PORT(void); unsigned char wait_interrupt(void); void set_usb_mode( unsigned char mode ); void toggle_recv(void); void toggle_send(void); unsigned char clr_stall6( void); unsigned char clr_stall7( void); unsigned char rd_usb_data( unsigned char *buf ); void wr_usb_data( unsigned char len, unsigned char *buf ); unsigned char issue_token( unsigned char endp_and_pid ); void host_send( unsigned char len, unsigned char *buf ); unsigned char host_recv( unsigned char *buf ); unsigned char get_descr( unsigned char type ); unsigned char set_addr( unsigned char addr ); unsigned char set_config( unsigned char cfg ); void CH375_Init( void ); unsigned char init_USB_device(void); void ComInit(void); void SendChar(unsigned char buff); //void SendChars( unsigned char *buff );
void delay2us(void) { unsigned char i; for ( i=DELAY_START_VALUE*2+1; i!=0; i-- ); }
void delay50ms(void) { unsigned char i, j; for( i=100; i!=0; i-- ) for( j=250; j!=0; j-- ); }
void delay1s(void) { unsigned char i,j,k;
for( i=10; i!=0; i-- ) for( j=200; j!=0; j-- ) for( k=250; k!=0; k-- ); }
void flash_led(void) { unsigned char i;
for( i=10;i>0;i-- ) { led=!led; delay1s(); } }
/* 與CH372/CH375有關的基本I/O操作 */ /* 向CH375的命令端口寫入命令,周期不小于4uS,如果單片機較快則延時 */ 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; }
/* 向CH375的數(shù)據端口寫入數(shù)據,周期不小于1.5uS,如果單片機較快則延時 */ void CH375_WR_DAT_PORT( unsigned char dat ) { _nop_(); CH375_CMD_DAT = 0; /* 數(shù)據 */ CH375_DATA_PORT = dat; CH375_RD = 1; CH375_WR = 0; _nop_(); CH375_WR = 1; CH375_DATA_PORT = 0xFF; }
/* 從CH375的數(shù)據端口讀出數(shù)據,周期不小于1.5uS,如果單片機較快則延時 */ unsigned char CH375_RD_DAT_PORT(void) { unsigned char rev_data;
CH375_DATA_PORT = 0xFF; CH375_CMD_DAT = 0; /* 數(shù)據 */ CH375_WR = 1; CH375_RD = 0; _nop_(); rev_data = CH375_DATA_PORT; CH375_RD = 1;
return( rev_data ); }
/* 主機端等待操作完成, 返回操作狀態(tài) */ unsigned char wait_interrupt(void) { CH375_INT_WIRE = 1; while( CH375_INT_WIRE ) /* 查詢等待CH375操作完成中斷(INT#低電平) */ { if( RI==1 ) /* 串口接收到數(shù)據 */ { CH375_WR_CMD_PORT( CMD_ABORT_NAK ); /* 放棄當前操作 */ return( 0xEF ); } } CH375_WR_CMD_PORT( CMD_GET_STATUS ); /* 產生操作完成中斷, 獲取中斷狀態(tài) */ return( CH375_RD_DAT_PORT() ); }
/* 設置CH37X的工作模式 */ 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; /* 主機端復位USB數(shù)據同步標志 */
for( i=100; i!=0; i-- ) /* 等待設置模式操作完成,不超過30uS */ { if( CH375_RD_DAT_PORT() == CMD_RET_SUCCESS ) return; /* 成功 */ }
while(1) { flash_led(); /* CH375出錯 */ } }
/************************************************************************************ 數(shù)據同步 USB的數(shù)據同步通過切換DATA0和DATA1實現(xiàn): 在設備端, USB設備可以自動切換; 在主機端, 必須由SET_ENDP6和SET_ENDP7命令控制CH375切換DATA0與DATA1. 主機端的程序處理方法是為設備端的各個端點分別提供一個全局變量, 初始值均為DATA0, 每執(zhí)行一次成功事務后取反, 每執(zhí)行一次失敗事務后將其復位為DATA1 *************************************************************************************/ void toggle_recv(void) /* 主機接收成功后,切換DATA0和DATA1實現(xiàn)數(shù)據同步 */ { CH375_WR_CMD_PORT( CMD_SET_ENDP6 ); CH375_WR_DAT_PORT( endp6_mode ); endp6_mode^=0x40; delay2us(); }
void toggle_send(void) /* 主機發(fā)送成功后,切換DATA0和DATA1實現(xiàn)數(shù)據同步 */ { CH375_WR_CMD_PORT( CMD_SET_ENDP7 ); CH375_WR_DAT_PORT( endp7_mode ); endp7_mode^=0x40; delay2us(); }
unsigned char clr_stall6(void) /* 主機接收失敗后,復位設備端的數(shù)據同步到DATA0 */ { CH375_WR_CMD_PORT( CMD_CLR_STALL ); CH375_WR_DAT_PORT( 2 | 0x80 ); /* 如果設備端不是CH37X芯片,那么需要修改端點號 */ // CH375_WR_DAT_PORT( endp_out_addr | 0x80 ); /* 如果設備端不是CH37X芯片,那么需要修改端點號 */ endp6_mode=0x80; return( wait_interrupt() ); }
unsigned char clr_stall7(void) /* 主機發(fā)送失