[求助]CH374枚舉HUB

[font=Arial][size=4]各位好!有個問題想請教各位大蝦: 現(xiàn)在有個項目是要用單片機+CH374通過HUB完成對外設(shè)的數(shù)據(jù)傳輸。程序是照著抄的,但是枚舉一個USB鼠標(低速)時,可以得到正確的設(shè)備描述符;枚舉 HUB 時,則老是有問題,數(shù)據(jù)時常不定時的出錯,以下是 HUB 返回的描述符: 0x12 0x01 0x44 0x42 0x09 0x00 0x06 0x44 0xE3 0x55 0x18 0x86 0x41 0x09 0x38 0x39 0x00 0x01 而正確的描述符應(yīng)該是: 12 01 00 02 09 00 00 40 e3 05 08 06 01 09 00 01 00 01 雖然每次的錯誤都不一定一樣,但是基本上這幾個字節(jié)都是不正確的。 HUB 的硬件部分是正確的,可以正常使用;而 CH374 與單片機的通信是正常的(單片機向374寫數(shù)據(jù)后讀出正確)。 另外,在枚舉過程中有個意外的情況:我第一次由CH374向設(shè)備發(fā)出設(shè)備描述符請求,建立過程返回正確,但數(shù)據(jù)過程(即要求設(shè)備返回描述符)則出現(xiàn)了一次的NAK,要再進行一次數(shù)據(jù)過程才能返回描述符(雖然后來證明得到的數(shù)據(jù)有誤)。 請各位大蝦指教,謝謝! [/size][/font]


熱門產(chǎn)品 : USB3.0 HUB控制器:CH634

請問下你使用的單片機是什么?和CH374的硬件接口是什么?是否可以把三個讀寫子函數(shù)貼出來看下?按照你給出的數(shù)據(jù)來看,應(yīng)該是三個讀寫子函數(shù)在時序上面有點問題。


[font=Arial][size=3] 謝謝回復。單片機就是 stc 的51,接的是30MHz的晶振(之前接過24MHz的晶振效果也一樣),通過并口與 374 通信,A8、CS與普通IO口連接,INT連接 51 的INT口。 CH374工作應(yīng)該是正常的,枚舉鼠標返回的描述符正確。當然鼠標為低速設(shè)備,接的 HUB 為高速設(shè)備。

讀寫函數(shù)是照抄的,如下: /* CH374傳輸事務(wù),輸入目的端點地址/PID令牌/同步標志,返回同CH375,NAK不重試,超時/出錯重試 */ UINT8 HostTransact374( UINT8 endp_addr, UINT8 pid, BOOL tog ) { // 本子程序著重于易理解,而在實際應(yīng)用中,為了提供運行速度,應(yīng)該對本子程序代碼進行優(yōu)化 UINT8 i, retry; UINT8 s=1, r, u; for ( retry = 0; retry < 3; retry ++ ) { print("retry number in HostTranact374() is ",retry); Write374Byte( REG_USB_H_PID, M_MK_HOST_PID_ENDP( pid, endp_addr ) ); // 指定令牌PID和目的端點號 // Write374Byte( REG_USB_H_CTRL, BIT_HOST_START | ( tog ? ( BIT_HOST_TRAN_TOG | BIT_HOST_RECV_TOG ) : 0x00 ) ); // 設(shè)置同步標志并啟動傳輸 Write374Byte( REG_USB_H_CTRL, ( tog ? ( BIT_HOST_START | BIT_HOST_TRAN_TOG | BIT_HOST_RECV_TOG ) : BIT_HOST_START ) ); // 設(shè)置同步標志并啟動傳輸 // Write374Byte( REG_INTER_FLAG, BIT_IF_USB_PAUSE ); // 取消暫停 // mDelayuS( 200 ); s = Wait374Interrupt( ); for(i=0;i<18;i++) print("this value is ",Read374Byte(RAM_HOST_RECV+i)); if(s==0) send_str("in transfer: interrupt occurs.\r\n"); if ( s == ERR_USB_UNKNOWN ) { send_str("in transfer: unknown error.\r\n"); return( s ); // 中斷超時,可能是硬件異常 } s = Read374Byte( REG_INTER_FLAG ); // 獲取中斷狀態(tài) print("REG_INTER_FLAG = ",s); /* if ( s & BIT_IF_DEV_DETECT ) { // USB設(shè)備插拔事件 send_str("in transfer: device detected.\r\n"); delay_us( 200 ); // 等待傳輸完成 Write374Byte( REG_INTER_FLAG, BIT_IF_USB_PAUSE | BIT_IF_DEV_DETECT | BIT_IF_TRANSFER ); // 清中斷標志 if ( s & BIT_IF_DEV_ATTACH ) { // USB設(shè)備連接事件 send_str("in transfer: device attached.\r\n"); u = Read374Byte( REG_USB_SETUP ); if ( s & BIT_IF_USB_DX_IN ) { // 速度匹配,不需要切換速度 if ( u & BIT_SETP_USB_SPEED ) return( USB_INT_CONNECT_LS ); // 低速USB設(shè)備 return( USB_INT_CONNECT ); // 全速USB設(shè)備 } else { // 速度失配,需要切換速度 if ( u & BIT_SETP_USB_SPEED ) return( USB_INT_CONNECT ); // 全速USB設(shè)備 return( USB_INT_CONNECT_LS ); // 低速USB設(shè)備 } } else return( USB_INT_DISCONNECT ); // USB設(shè)備斷開事件 } else*/ if ( s & BIT_IF_TRANSFER ) { // 傳輸完成 send_str("in transfer: transfer complete.\r\n"); Write374Byte( REG_INTER_FLAG, BIT_IF_USB_PAUSE | BIT_IF_TRANSFER ); // 清中斷標志 s = Read374Byte( REG_USB_STATUS ); // USB狀態(tài) print("REG_USB_STATUS = ",s); r = s & BIT_STAT_DEV_RESP; // USB設(shè)備應(yīng)答狀態(tài) switch ( pid ) { case DEF_USB_PID_SETUP: case DEF_USB_PID_OUT:

send_str("setup or out event.\r\n"); if ( r == DEF_USB_PID_ACK ) return( USB_INT_SUCCESS ); else if ( r == DEF_USB_PID_STALL || r == DEF_USB_PID_NAK ) { send_str("status is STALL or NAK.\r\n"); return( r | 0x20 ); } else if ( ! M_IS_HOST_TIMEOUT( s ) ) { send_str("status is unknown error.\r\n"); return( r | 0x20 ); // 不是超時/出錯,意外應(yīng)答 } break;

case DEF_USB_PID_IN:

send_str("in event.\r\n"); if ( M_IS_HOST_IN_DATA( s ) ) { // DEF_USB_PID_DATA0 or DEF_USB_PID_DATA1 if ( s & BIT_STAT_TOG_MATCH ) { send_str("status is tog matched.\r\n"); return( USB_INT_SUCCESS ); // 不同步則需丟棄后重試 } } else if ( r == DEF_USB_PID_STALL || r == DEF_USB_PID_NAK ) { send_str("status is STALL or NAK.\r\n"); for(i=0;i<18;i++) print("this value is ",Read374Byte(RAM_HOST_RECV+i)); return( r | 0x20 ); } else if ( ! M_IS_HOST_TIMEOUT( s ) ) { send_str("status is unknown error.\r\n"); return( r | 0x20 ); // 不是超時/出錯,意外應(yīng)答 } break;

default: return( ERR_USB_UNKNOWN ); // 不可能的情況 break; } } else { // 其它中斷,不應(yīng)該發(fā)生的情況 delay_us( 200 ); // 等待傳輸完成 Write374Byte( REG_INTER_FLAG, BIT_IF_USB_PAUSE | BIT_IF_INTER_FLAG ); /* 清中斷標志 */ if ( retry ) return( ERR_USB_UNKNOWN ); // 不是第一次檢測到則返回錯誤 } } return( 0x20 ); // 應(yīng)答超時 }

/* CH374傳輸事務(wù),輸入目的端點地址/PID令牌/同步標志/以mS為單位的NAK重試總時間(0xFFFF無限重試),返回同CH375,NAK重試,超時出錯重試 */ UINT8 WaitHostTransact374( UINT8 endp_addr, UINT8 pid, BOOL tog, UINT16 timeout ) { UINT8 i, s; while ( 1 ) { send_str("try WaitHostTransact() for 40 times.\r\n"); for ( i = 0; i < 40; i ++ ) { s = HostTransact374( endp_addr, pid, tog ); if ( s != ( DEF_USB_PID_NAK | 0x20 ) || timeout == 0 ) { return( s ); } send_str("retry in WaitHostTransact374() NAK or timeout.\r\n"); delay_us( 20 ); } if ( timeout < 0xFFFF ) timeout --; else send_str("time out in WaitHostTransact374().\r\n"); } }

/* 執(zhí)行控制傳輸,ReqBuf指向8字節(jié)請求碼,DatBuf為收發(fā)緩沖區(qū) */ UINT8 HostCtrlTransfer374( PUINT8 ReqBuf, PUINT8 DatBuf, PUINT8 RetLen ) // 如果需要接收和發(fā)送數(shù)據(jù),那么DatBuf需指向有效緩沖區(qū)用于存放后續(xù)數(shù)據(jù),實際成功收發(fā)的總長度保存在ReqLen指向的字節(jié)變量中 { UINT8 s, len, count, total, i; BOOL tog; Write374Block( RAM_HOST_TRAN, RequestNum, ReqBuf ); //write command to CH374 that ask for describtor Write374Byte( REG_USB_LENGTH, RequestNum ); //and the length number of sending package delay_us( 100 ); send_str(" start setup transfer.\r\n"); s = WaitHostTransact374( 0, DEF_USB_PID_SETUP, FALSE, 200 ); // SETUP階段,20uS延時重試200次超時 if ( s == USB_INT_SUCCESS ) // SETUP成功 { send_str(" setup success.\r\n"); tog = TRUE; // 默認DATA1,默認無數(shù)據(jù)故狀態(tài)階段為IN if((*(ReqBuf+3))==0x22) { total=*( ReqBuf + 6 )-0x40; } else { send_str("length of data equals Buf[6].\r\n"); total = *( ReqBuf + 6 ); } if ( total && DatBuf ) // 需要收數(shù)據(jù) { len = total; if ( *ReqBuf & 0x80 ) // 收 { send_str("get data from device.\r\n"); while ( len ) { send_str(" start to read.\r\n"); delay_us( 100 ); Write374Byte(RAM_HOST_RECV+0,0); Write374Byte(RAM_HOST_RECV+1,1); Write374Byte(RAM_HOST_RECV+2,2); Write374Byte(RAM_HOST_RECV+3,3); Write374Byte(RAM_HOST_RECV+4,4); Write374Byte(RAM_HOST_RECV+5,5); Write374Byte(RAM_HOST_RECV+6,6); Write374Byte(RAM_HOST_RECV+7,7); i = Read374Byte(RAM_HOST_RECV+0); print("the third byte is ",i); i = Read374Byte(RAM_HOST_RECV+1); print("the forth byte is ",i); i = Read374Byte(RAM_HOST_RECV+2); print("the sixth byte is ",i); i = Read374Byte(RAM_HOST_RECV+3); print("the third byte is ",i); i = Read374Byte(RAM_HOST_RECV+4); print("the forth byte is ",i); i = Read374Byte(RAM_HOST_RECV+5); print("the sixth byte is ",i); i = Read374Byte(RAM_HOST_RECV+6); print("the third byte is ",i); i = Read374Byte(RAM_HOST_RECV+7); print("the forth byte is ",i); s = WaitHostTransact374( 0, DEF_USB_PID_IN, tog, 200 ); // IN數(shù)據(jù) if ( s != USB_INT_SUCCESS ) break; count = Read374Byte( REG_USB_LENGTH ); print("read count is ",count); //Read374Block( RAM_HOST_RECV, count, DatBuf ); i = Read374Byte(RAM_HOST_RECV+3); print("the third byte is ",i); i = Read374Byte(RAM_HOST_RECV+3); print("the third byte is ",i); i = Read374Byte(RAM_HOST_RECV+3); print("the third byte is ",i); i = Read374Byte(RAM_HOST_RECV+3); print("the third byte is ",i); i = Read


[font=Arial][size=4]這個帖子的排版有點問題,謝謝大蝦的回復。 再問,在 HostTransact374()這個函數(shù)中,說要進行優(yōu)化,請問應(yīng)該做怎么樣的優(yōu)化呢?請稍微給點提示。 謝謝! [/size][/font]


上面的程序沒什么問題,但是我需要看下你的三個讀寫子函數(shù),寫索引,寫數(shù)據(jù),讀數(shù)據(jù)三個函數(shù)。


[font=Arial][size=3]你指的是以下這一系列宏和函數(shù)么? // P2.0 A0 // P2.1 CS# 如果并口上只有CH374,那么CS#可以直接接低電平,強制片選 */ UINT8XV CH374_IDX_PORT _at_ 0x0FDFF; /* 假定CH374索引端口的I/O地址 */ UINT8XV CH374_DAT_PORT _at_ 0x0FCFF; /* 假定CH374數(shù)據(jù)端口的I/O地址 */

#define Write374Index( a ) { CH374_IDX_PORT = a; } /* 向索引端口寫入索引地址 */ #define Write374Data( d ) { CH374_DAT_PORT = d; } /* 向數(shù)據(jù)端口寫入數(shù)據(jù),索引地址自動加1 */ #define Read374Data( ) ( CH374_DAT_PORT ) /* 從數(shù)據(jù)端口讀出數(shù)據(jù),索引地址自動加1 */ #define Read374Data0( ) ( CH374_IDX_PORT ) /* 從索引端口讀出數(shù)據(jù),索引地址不變,適用于[讀出->修改->寫回]操作 */ UINT8 Read374Byte( UINT8 mAddr ) /* 從指定寄存器讀取數(shù)據(jù) */ { Write374Index( mAddr ); return( Read374Data( ) ); } void Write374Byte( UINT8 mAddr, UINT8 mData ) /* 向指定寄存器寫入數(shù)據(jù) */ { Write374Index( mAddr ); Write374Data( mData ); } 另外,查詢函數(shù)如下: // 查詢CH374中斷(INT#低電平) BOOL Query374Interrupt( void ) { #ifdef CH374_INT_WIRE send_str("................................\r\n"); return( CH374_INT_WIRE ? FALSE : TRUE ); /* 如果連接了CH374的中斷引腳則直接查詢中斷引腳 */ #else return( Read374Byte( REG_INTER_FLAG ) & BIT_IF_INTER_FLAG ? TRUE : FALSE ); /* 如果未連接CH374的中斷引腳則查詢中斷標志寄存器 */ #endif }

// 等待CH374中斷(INT#低電平),超時則返回ERR_USB_UNKNOWN UINT8 Wait374Interrupt( void ) { UINT16 i; for ( i = 0; i < 10000; i ++ ) { // 計數(shù)防止超時 if ( Query374Interrupt( ) ) return( 0 ); } return( ERR_USB_UNKNOWN ); // 不應(yīng)該發(fā)生的情況 } [/size][/font]


你把這2個函數(shù)按照我寫的程序修改下:

void Read374Block( UINT8 mAddr, UINT8 mLen, PUINT8 mBuf ) /* 從指定起始地址讀出數(shù)據(jù)塊 */ { while ( mLen -- ){ Write374Index( mAddr ); *mBuf++ = Read374Data( ); mAddr++; } }

void Write374Block( UINT8 mAddr, UINT8 mLen, PUINT8 mBuf ) /* 向指定起始地址寫入數(shù)據(jù)塊 */ { while ( mLen -- ){ Write374Index( mAddr ); mAddr++; Write374Data( *mBuf++ ); } }


[font=Arial][size=3]你好,謝謝你的耐心回復。 已經(jīng)把之前的程序修改了,并去掉了一些多余的判斷,數(shù)據(jù)仍然出現(xiàn)問題: the device descriptor is 0x12 0x01 0x44 0x42 0x09 0x00 0x02 0x40 0xE3 0x85 0x1A 0x86 0x01 0x09 0x28 0x39 0x00 0x01 另外用該程序枚舉鼠標仍然正確。這里還有個現(xiàn)象: 我在獲得中斷信號后,對 374 進行讀動作,反復讀取描述符其中的某個字節(jié),比如第4個字節(jié),返回的數(shù)據(jù)一直為“0x42”,我的推測是:可能 HUB 返回數(shù)據(jù)到 374 的RAM_HOST_RECV 中,數(shù)據(jù)已經(jīng)是有問題的了(HUB 芯片是GL850A,2.0協(xié)議,并可以正常連接電腦工作)。 不知大蝦有什么看法。 [/size][/font]


按照HUB的設(shè)計應(yīng)該不會出現(xiàn)你說的現(xiàn)象。因為即使是設(shè)備描述符,2.0和1.1基本上是一樣的。估計還是在讀取數(shù)據(jù)上面有問題。那你枚舉U盤有這個問題嗎?


[font=Arial][size=3]向U盤發(fā)出獲取設(shè)備描述符命令,得到的數(shù)據(jù)為: the device descriptor is 0x12 0x01 0xA8 0x06 0x00 0x04 0x02 0x40 0x51 0x49 0x36 0x96 0x00 0x02 0x29 0x32 0x03 0x01 但是我也不知道正確的描述符應(yīng)該是多少啊,用 Bus Hound 在電腦看U盤連接數(shù)據(jù),竟然沒有獲取描述符的申請,真奇怪。 請問,是否有 51+374 連接 Hub 成功的實例啊?應(yīng)該有吧,可以下載么?要不我再試試。這次我什么都不改,就用提供的例子來試。是否硬件要求為 51 接24MHz的晶振?還有什么其他的么? 謝謝! [/size][/font]


你發(fā)一份E-MAIL到我郵箱,我給你發(fā)份例子


[font=Arial][size=3]你好,郵件已發(fā),題目是“求助 CH374 枚舉 HUB”。 [/size][/font]


[font=Arial][size=3]不好意思,到現(xiàn)在才看到,郵箱竟然把郵件認到**郵件里了,真是詭異。 請問,硬件條件呢?晶振是24MHz的么?還有其他的么? 我今晚才有時間試,現(xiàn)在比較忙,嘿嘿,還是謝謝了。 [/size][/font]


24M是可以工作的。其他沒什么,你需要拿串口來跟蹤下程序運行。


[font=Arial][size=3]大蝦你好,謝謝你的回復。我今天看了程序,發(fā)現(xiàn)其關(guān)聯(lián)關(guān)系比較混亂。 我已經(jīng)將頭文件:HAL.H包含,也在工程中加入了以前下載的 HAL_BASE.C 和 PARA_HW.C。但是 CH374的頭文件呢? 我加入了 CH374INC.H,報編譯出錯,關(guān)于 HUB 的寄存器 REG_HUB_SETUP 沒有定義,就又下了一個 CH374HFC.H,包含編譯了又報一些類型沒有定義,增加完類型定義后又報 multiple public definition 的錯誤。 請問是否可以發(fā)個比較完整的程序,因為我還不知道另外還有什么我沒修補好的奇怪錯誤。 謝謝!關(guān)于此問題我將全程回復。 [/size][/font]


已經(jīng)將工程做好E-MAIL給你。有什么問題可以進行E-MAIL進行聯(lián)系。


只有登錄才能回復,可以選擇微信賬號登錄

国产91精品新入口,国产成人综合网在线播放,九热这里只有精品,本道在线观看,美女视频a美女视频,韩国美女激情视频,日本美女pvp视频