[求助]CH374无法识别

小弟的下位机系统配置如下LPC2132+CH374S实现USB device,24M晶体,电源3.3V,使用硬件SPI连接。现在已经可以正确写入寄存器值,如可以更改CKO,使用CH374EVT中\pub\exam\device下面的代码,只对硬件相关的代码做了改动。初始化374后立即进入中断,读出中断状态字0xC4,然后根据终端服务程序374进入休眠状态。插入USB,又进入中断,读出中断状态字0xDF,然后374锁死,中断线一直为0,PC显示无法识别USB设备。插入USB后大约10秒PC出现无法识别的提示,这中间用示波器观察D+ D-会看到有波形。

请问中断状态字是不是不正确?可能是哪种原因?望前辈不吝赐教

刚开始会进入复位中断,然后进入休眠,唤醒,再进入传输完成中断, 再初试化时要把所有的中断清除掉,然后进入每个中断后都要清除,不知道您这样做了没 可以把您的程序贴出来看看.


void Init374Device( void ) // 初始化USB设备 { Read374Byte(REG_SYS_INFO); Write374Byte( REG_USB_ADDR, 0x00 ); Write374Byte( REG_USB_SETUP, 0x00 ); Write374Byte( REG_USB_ENDP0, M_SET_EP0_TRAN_NAK( 0 ) ); Write374Byte( REG_USB_ENDP1, M_SET_EP1_TRAN_NAK( 0 ) ); Write374Byte( REG_USB_ENDP2, M_SET_EP2_TRAN_NAK( 0 ) ); Write374Byte( REG_INTER_FLAG, BIT_IF_USB_PAUSE | BIT_IF_INTER_FLAG ); // 清所有中断标志 Write374Byte( REG_INTER_EN, BIT_IE_TRANSFER | BIT_IE_BUS_RESET | BIT_IE_USB_SUSPEND |0x20); // 允许传输完成中断和USB总线复位中断以及USB总线挂起中断,芯片唤醒完成中断 Write374Byte( REG_SYS_CTRL, BIT_CTRL_OE_POLAR | BIT_CTRL_USB_POWER ); // 对于CH374T或者UEN引脚悬空的CH374S必须置BIT_CTRL_OE_POLAR为1 Write374Byte( REG_USB_SETUP, BIT_SETP_TRANS_EN | BIT_SETP_PULLUP_EN | BIT_SETP_LED_ACT); // 启动USB设备 }

void __irq IRQ_Eint0 (void) {

UINT8 s, l; // static UINT8 SetupReq, SetupLen; // static PUINT8 pDescr; UINT8 SetupReq, SetupLen; unsigned char *pDescr; s = Read374Byte( REG_INTER_FLAG ); // 获取中断状态 if ( s & BIT_IF_BUS_RESET ) { // USB总线复位 Write374Byte( REG_USB_ADDR, 0x00 ); // 清USB设备地址 Write374Byte( REG_USB_ENDP0, M_SET_EP0_TRAN_NAK( 0 ) ); Write374Byte( REG_USB_ENDP1, M_SET_EP1_TRAN_NAK( 0 ) ); Write374Byte( REG_USB_ENDP2, M_SET_EP2_TRAN_NAK( 0 ) ); Write374Byte( REG_INTER_FLAG, BIT_IF_USB_PAUSE | BIT_IF_BUS_RESET ); // 清中断标志 } else if ( s & BIT_IF_TRANSFER ) { // USB传输完成 s = Read374Byte( REG_USB_STATUS ); switch( s & BIT_STAT_PID_ENDP ) { // USB设备中断状态 case USB_INT_EP2_OUT: { // 批量端点下传成功 UINT8 buf[64]; if ( s & BIT_STAT_TOG_MATCH ) { // 仅同步包 l = Read374Byte( REG_USB_LENGTH ); Read374Block( RAM_ENDP2_RECV, l, buf ); for ( s = 0; s < l; s ++ ) buf[s] ^= 0xFF; // 数据取反由计算机验证 Write374Block( RAM_ENDP2_TRAN, l, buf ); // 演示回传 Write374Byte( REG_USB_LENGTH, l ); Write374Byte( REG_USB_ENDP2, M_SET_EP2_TRAN_ACK( Read374Byte( REG_USB_ENDP2 ) ) ^ BIT_EP2_RECV_TOG ); // Write374Index( REG_USB_ENDP2 ); // 对于并口连接可以用本行及下面一行代替上一行的程序,减少写一次index的时间,提高效率 // Write374Data( M_SET_EP2_TRAN_ACK( Read374Data0( ) ) ^ BIT_EP2_RECV_TOG ); } break; } case USB_INT_EP2_IN: { // 批量端点上传成功,未处理 Write374Byte( REG_USB_ENDP2, M_SET_EP2_TRAN_NAK( Read374Byte( REG_USB_ENDP2 ) ) ^ BIT_EP2_TRAN_TOG ); // Write374Index( REG_USB_ENDP2 ); // 对于并口连接可以用本行及下面一行代替上一行的程序,减少写一次index的时间,提高效率 // Write374Data( M_SET_EP2_TRAN_NAK( Read374Data0( ) ) ^ BIT_EP2_TRAN_TOG ); break; } case USB_INT_EP1_IN: { // 中断端点上传成功,未处理 Write374Byte( REG_USB_ENDP1, M_SET_EP1_TRAN_NAK( Read374Byte( REG_USB_ENDP1 ) ) ^ BIT_EP1_TRAN_TOG ); break; } case USB_INT_EP0_SETUP: { // 控制传输 USB_SETUP_REQ SetupReqBuf; l = Read374Byte( REG_USB_LENGTH ); if ( l == sizeof( USB_SETUP_REQ ) ) { Read374Block( RAM_ENDP0_RECV, l, (PUINT8)&SetupReqBuf ); SetupLen = SetupReqBuf.wLengthL; if ( SetupReqBuf.wLengthH || SetupLen > 0x7F ) SetupLen = 0x7F; // 限制总长度 l = 0; // 默认为成功并且上传0长度 if ( ( SetupReqBuf.bType & DEF_USB_REQ_TYPE ) != DEF_USB_REQ_STAND ) { /* 只支持标准请求 */ l = 0xFF; // 操作失败 } else { // 标准请求 SetupReq = SetupReqBuf.bReq; // 请求码 switch( SetupReq ) { case DEF_USB_GET_DESCR: switch( SetupReqBuf.wValueH ) { case 1: pDescr = (PUINT8)( &MyDevDescr[0] ); l = sizeof( MyDevDescr ); break; case 2: pDescr = (PUINT8)( &MyCfgDescr[0] ); l = sizeof( MyCfgDescr ); break; case 3: switch( SetupReqBuf.wValueL ) { case 1: pDescr = (PUINT8)( &MyManuInfo[0] ); l = sizeof( MyManuInfo ); break; case 2: pDescr = (PUINT8)( &MyProdInfo[0] ); l = sizeof( MyProdInfo ); break; case 0: pDescr = (PUINT8)( &MyLangDescr[0] ); l = sizeof( MyLangDescr ); break; default: l = 0xFF; // 操作失败 break; } break; default: l = 0xFF; // 操作失败 break; } if ( SetupLen > l ) SetupLen = l; // 限制总长度 l = SetupLen >= RAM_ENDP0_SIZE ? RAM_ENDP0_SIZE : SetupLen; // 本次传输长度 Write374Block( RAM_ENDP0_TRAN, l, pDescr ); /* 加载上传数据 */ SetupLen -= l; pDescr += l; break; case DEF_USB_SET_ADDRESS: SetupLen = SetupReqBuf.wValueL; // 暂存USB设备地址 break; case DEF_USB_GET_CONFIG: Write374Byte( RAM_ENDP0_TRAN, UsbConfig ); if ( SetupLen >= 1 ) l = 1; break; case DEF_USB_SET_CONFIG: UsbConfig = SetupReqBuf.wValueL; break; case DEF_USB_CLR_FEATURE: if ( ( SetupReqBuf.bType & 0x1F ) == 0x02 ) { // 不是端点不支持 switch( SetupReqBuf.wIndexL ) { case 0x82: Write374Byte( REG_USB_ENDP2, M_SET_EP2_TRAN_NAK( Read374Byte( REG_USB_ENDP2 ) ) ); break; case 0x02: Write374Byte( REG_USB_ENDP2, M_SET_EP2_RECV_ACK( Read374Byte( REG_USB_ENDP2 ) ) ); break; case 0x81: Write374Byte( REG_USB_ENDP1, M_SET_EP1_TRAN_NAK( Read374Byte( REG_USB_ENDP1 ) ) ); break; case 0x01: Write374Byte( REG_USB_ENDP1, M_SET_EP1_RECV_ACK( Read374Byte( REG_USB_ENDP1 ) ) ); break; default: l = 0xFF; // 操作失败 break; } } else l = 0xFF; // 操作失败 break; case DEF_USB_GET_INTERF: Write374Byte( RAM_ENDP0_TRAN, 0 ); if ( SetupLen >= 1 ) l = 1; break; case DEF_USB_GET_STATUS: Write374Byte( RAM_ENDP0_TRAN, 0 ); Write374Byte( RAM_ENDP0_TRAN + 1, 0 ); if ( SetupLen >= 2 ) l = 2; else l = SetupLen; break; default: l = 0xFF; // 操作失败 break; } } } else l = 0xFF; // 操作失败 if ( l == 0xFF ) { // 操作失败 Write374Byte( REG_USB_ENDP0, M_SET_EP0_RECV_STA( M_SET_EP0_TRAN_STA( 0 ) ) ); // STALL } else if ( l <= RAM_ENDP0_SIZE ) { // 上传数据 Write374Byte( REG_USB_ENDP0, M_SET_EP0_TRAN_ACK( M_SET_EP0_RECV_ACK( Read374Byte( REG_USB_ENDP0 ) ), l ) | BIT_EP0_TRAN_TOG ); // DATA1 } else { // 下传数据或其它 Write374Byte( REG_USB_ENDP0, M_SET_EP0_TRAN_NAK( M_SET_EP0_RECV_ACK( Read374Byte( REG_USB_ENDP0 ) ) ) | BIT_EP0_RECV_TOG ); // DATA1 } break; } case USB_INT_EP0_IN: { switch( SetupReq ) { case DEF_USB_GET_DESCR: l = SetupLen >= RAM_ENDP0_SIZE ? RAM_ENDP0_SIZE : SetupLen; // 本次传输长度 Write374Block( RAM_ENDP0_TRAN, l, pDescr ); /* 加载上传数据 */ SetupLen -= l; pDescr += l; Write374Byte( REG_USB_ENDP0, M_SET_EP0_TRAN_ACK( Read374Byte( REG_USB_ENDP0 ), l ) ^ BIT_EP0_TRAN_TOG ); break; case DEF_USB_SET_ADDRESS: Write374Byte( REG_USB_ADDR, SetupLen ); default: Write374Byte( REG_USB_ENDP0, M_SET_EP0_TRAN_NAK( 0 ) ); // 结束 break; } break; } case USB_INT_EP0_OUT: { switch( SetupReq ) { // case download: // get_data; // break; case DEF_USB_GET_DESCR: default: Write374Byte( REG_USB_ENDP0, M_SET_EP0_TRAN_NAK( 0 ) ); // 结束 break; } break; } default: { break; } } Write374Byte( REG_INTER_FLAG, BIT_IF_USB_PAUSE | BIT_IF_TRANSFER ); // 清中断标志 } else if ( s & BIT_IF_USB_SUSPEND ) { // USB总线挂起 Write374Byte( REG_INTER_FLAG, BIT


程序中没有调试输出,您是怎么知道中断状态值的?是仿真的么?若是,那么不要单步,全速跑试试


UINT8 SetupReq, SetupLen; unsigned char *pDescr;

要么设置为全局变量,要么设置为静态的,修改后估计会成功.


我用的开发环境是ADS1.2,原先这两个变量都是静态的。跟踪发现似乎程序从未跑到s = Read374Byte( REG_USB_STATUS );这一行,一旦插入USB线,中断程序就会跑到 else { // 意外的中断,不可能发生的情况,除了硬件损坏这一行,会不会是硬件方面的问题呢?


可能与你的硬件有关系,可以做一下读写RAM测试. 你读出来的中断值是多少?


按照红桃六前辈所说的,改成全局变量就好啦!感谢指导。看来ADS里面静态变量和全局变量还不能混用呵呵


还发现一个问题,不仅仅是变量类型,这个中断响应一定要特别的快,正如SMC所说。用11MHz的CPU主频跑WCH的传输测试程序根本跑不动,两个包之后就死掉,后来把CPU速度倍频到55M,最多3000个包就会死掉,后来把SPI时钟速率提高到10M才能稳定的跑。


只有登录才能回复,可以选择微信账号登录