ch376初始化+中断

大师们,你们好,我使用ch376s模块与U盘通信,遇到一些问题,始终找不到解决办法,请求帮助。 我按照例程上边,用atmega16的模拟spi使单片机与u盘通信,遇到了一些个问题,灰常难解。 首先,xWriteCH376Cmd( CMD11_CHECK_EXIST )命令和xWriteCH376Cmd( CMD11_SET_USB_MODE )命令不能同时使用,当第一条命令执行时,第二条就出错,把第一条屏蔽了,第二条就好用了。我跟踪程序,总是如此。 然后,执行xWriteCH376Cmd( CMD11_SET_USB_MODE )命令后,发送0x06工作方式,正常结束以后。int#被拉低,利用Query376Interrupt()函数和CH376GetIntStatus()始终不能取消中断,INT#引脚一直为低。 问题很奇怪,想了一些办法一直没能解决,请求帮助,非常感谢。

把你的程序贴出来看看。


程序大都调用例程,在一个文件下,非常繁琐,上传不知能不能看到,我把主要的粘贴出来

/* 查询CH376中断(INT#低电平) */ UINT8 Query376Interrupt( void ) { #ifdef CH376_INT_WIRE return( CH376_INT_WIRE ? FALSE : TRUE ); /* 如果连接了CH376的中断引脚则直接查询中断引脚 */ #else return( CH376_SPI_SDO ? FALSE : TRUE ); /* 如果未连接CH376的中断引脚则查询兼做中断输出的SDO引脚状态 */ #endif }

UINT8 mInitCH376Host( void ) /* 初始化CH376 */ { UINT8 res; CH376_PORT_INIT( ); /* 接口硬件初始化 */ xWriteCH376Cmd( CMD11_CHECK_EXIST ); /* 测试单片机与CH376之间的通讯接口 */ xWriteCH376Data( 0x55 ); res = xReadCH376Data( ); xEndCH376Cmd( ); if ( res != 0xaA ) {PORTA=0XFB;return(ERR_USB_UNKNOWN ); } /* 通讯接口不正常,可能原因有:接口连接异常,其它设备影响(片选不唯一),串口波特率,一直在复位,晶振不工作 */ //while(!(Query376Interrupt())); CH376GetIntStatus(); xWriteCH376Cmd( CMD11_SET_USB_MODE ); /* 设备USB工作模式 */ xWriteCH376Data( 0x06 ); mDelayuS( 20 ); res = xReadCH376Data( ); xEndCH376Cmd( ); #ifndef CH376_INT_WIRE #ifdef CH376_SPI_SDO xWriteCH376Cmd( CMD20_SET_SDO_INT ); /* 设置SPI的SDO引脚的中断方式 */ xWriteCH376Data( 0x16 ); xWriteCH376Data( 0x90 ); /* SDO引脚在SCS片选无效时兼做中断请求输出 */ xEndCH376Cmd( ); #endif #endif if ( res == CMD_RET_SUCCESS ) {PORTA&=0XFD;return( USB_INT_SUCCESS );} else return( ERR_USB_UNKNOWN ); /* 设置模式错误 */ }

/* 检查操作状态,如果错误则显示错误代码并停机,应该替换为实际的处理措施,例如显示错误信息,等待用户确认后重试等 */ void mStopIfError( UINT8 iError ) { if ( iError == USB_INT_SUCCESS ) return; /* 操作成功 */ //printf( "Error: %02X\n", (UINT16)iError ); /* 显示错误 */ while ( 1 ) { /* LED_OUT_ACT( );*/ /* LED闪烁 */ PORTA&=0XFE; mDelaymS( 200 ); /* LED_OUT_INACT( );*/ mDelaymS( 200 ); } }

UINT8 CH376GetIntStatus( void ) /* 获取中断状态并取消中断请求 */ { UINT8 s; xWriteCH376Cmd( CMD01_GET_STATUS ); s = xReadCH376Data( ); xEndCH376Cmd( ); return( s ); }

#ifndef NO_DEFAULT_CH376_INT UINT8 Wait376Interrupt( void ) /* 等待CH376中断(INT#低电平),返回中断状态码, 超时则返回ERR_USB_UNKNOWN */ { #ifdef DEF_INT_TIMEOUT #if DEF_INT_TIMEOUT < 1 while ( Query376Interrupt( ) == FALSE ); /* 一直等中断 */ return( CH376GetIntStatus( ) ); /* 检测到中断 */ #else UINT32 i; for ( i = 0; i < DEF_INT_TIMEOUT; i ++ ) { /* 计数防止超时 */ if ( Query376Interrupt( ) ) return( CH376GetIntStatus( ) ); /* 检测到中断 */ /* 在等待CH376中断的过程中,可以做些需要及时处理的其它事情 */ } return( ERR_USB_UNKNOWN ); /* 不应该发生的情况 */ #endif #else UINT32 i; for ( i = 0; i < 5000000; i ++ ) { /* 计数防止超时,默认的超时时间,与单片机主频有关 */ if ( Query376Interrupt( ) ) return( CH376GetIntStatus( ) ); /* 检测到中断 */ /* 在等待CH376中断的过程中,可以做些需要及时处理的其它事情 */ } return( ERR_USB_UNKNOWN ); /* 不应该发生的情况 */ #endif } #endif

UINT8 CH376SendCmdWaitInt( UINT8 mCmd ) /* 发出命令码后,等待中断 */ { xWriteCH376Cmd( mCmd ); xEndCH376Cmd( ); return( Wait376Interrupt( ) ); }

UINT8 CH376SendCmdDatWaitInt( UINT8 mCmd, UINT8 mDat ) /* 发出命令码和一字节数据后,等待中断 */ { xWriteCH376Cmd( mCmd ); xWriteCH376Data( mDat ); xEndCH376Cmd( ); return( Wait376Interrupt( ) ); }

UINT8 CH376DiskReqSense( void ) /* 检查USB存储器错误 */ { UINT8 s; mDelaymS( 5 ); s = CH376SendCmdWaitInt( CMD0H_DISK_R_SENSE ); mDelaymS( 5 ); return( s ); }

UINT8 CH376DiskConnect( void ) /* 检查U盘是否连接,不支持SD卡 */ { if ( Query376Interrupt( ) ) CH376GetIntStatus( ); /* 检测到中断 */ return( CH376SendCmdWaitInt( CMD0H_DISK_CONNECT ) ); }

void main(void) { unsigned char s,i; DDRA=0XFF;PORTA=0XFF; delay_ms(200); s = mInitCH376Host( ); /* 初始化CH376 */ mStopIfError( s ); //while(!(Query376Interrupt())); //CH376GetIntStatus(); while ( 1 ) { while ( CH376DiskConnect( ) !=USB_INT_SUCCESS ) { /* 检查U盘是否连接,等待U盘插入,对于SD卡,可以由单片机直接查询SD卡座的插拔状态引脚 */ // delay_ms(200); // delay_ms(200); // delay_ms(200); // delay_ms(200); mDelaymS( 100 ); /* 没必要频繁查询 */ } PORTA&=0XFB; mDelaymS( 200 ); /* 延时,可选操作,有的USB存储器需要几十毫秒的延时 */

for ( i = 0; i < 100; i ++ ) { /* 最长等待时间,100*50mS */ mDelaymS( 50 ); //printf( "Ready ?\n\r" ); s = CH376DiskMount( ); /* 初始化磁盘并测试磁盘是否就绪 */ if ( s == USB_INT_SUCCESS ) {PORTA&=0XF7;break; } /* 准备好 */ else if ( s == ERR_DISK_DISCON ) break; /* 检测到断开,重新检测并计时 */ //if ( CH376GetDiskStatus( ) >= DEF_DISK_MOUNTED && i >= 5 ) break; /* 有的U盘总是返回未准备好,不过可以忽略,只要其建立连接MOUNTED且尝试5*50mS */ } } }


SPI的片选是如何变化的?你仔细看一下CH376的SPI时序部分 发送命令前CS拉低。 CS片选为0表示取消命令,所以一次完整的命令CS是不可以变化的


程序差不多全用的资料包里边的,大约是没问题,一会在自信检查检查,先谢谢啦


我检查片选时序了,都没有错,可还是那样子,费解啊


你给我发个邮件,我给你发一份AVR模拟SPI时序的程序。


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