avr m16 ch376 中断响应 问题求助

移植的51的库。

初始化,连接u盘,打开目录,打开文件都正常,

但是在使用CH376ByteRead函数时,发送CMD_BYTE_READ和数据长度后,中断一直不发生。

代码如下:请指点一下,谢谢

/* */ #define F_CPU 16000000UL

#include "ch376.h" #include #include #include

#define CH376_DATA_PORT PORTA #define CH376_DATA_PIN PINA #define CH376_DATA_DDR DDRA

#define CH376_CMD_PORT PORTC #define CH376_CMD_PIN PINC #define CH376_CMD_DDR DDRC

#define CH376_A0 PC7 #define CH376_RD PC6 #define CH376_WR PC5 #define CH376_RSTI PC4 #define CH376_INT PC3 #define CH376_CS PC2

////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////// Hardware Access Function //////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////

void CH376PortInit( ) /* 由于使用通用I/O模块并口读写时序,所以进行初始化 */

{ uint8_t i; /* 设置8位并口为输入 */

CH376_DATA_DDR = 0x00; /* 设置CS,WR,RD,A0,RSTI为输出,设置INT#为输入 */

CH376_CMD_DDR |= _BV(CH376_CS)|_BV(CH376_WR)|_BV(CH376_RD)|_BV(CH376_A0)|_BV(CH376_RSTI); CH376_CMD_DDR &= ~_BV(CH376_INT); /* 设置CS,WR,RD默认为高电平 */ CH376_CMD_PORT |= _BV(CH376_CS)|_BV(CH376_WR)|_BV(CH376_RD); /* 复位系统 */ CH376_CMD_PORT |= _BV(CH376_RSTI); _delay_ms(1); CH376_CMD_PORT &= ~_BV(CH376_RSTI); //延时100ms 等待 CH376 复位进入工作状态 for(i=0;i<10;i++) _delay_ms(10);

}

void CH376WriteCmd( uint8_t cmd ) /* 外部定义的被CH376程序库调用的子程序,向CH376写命令 */

{ //_delay_us(5); /* 至少延时2uS */

CH376_CMD_PORT |= _BV(CH376_A0); /* 输出A0=1 打开命令端口 */

CH376_DATA_PORT = cmd; /* 向CH376的并口输出数据 */

CH376_DATA_DDR = 0xFF; /* 并口D0-D7输出 */

/* 输出有效写控制信号, 写CH376芯片的命令端口, CS=0; WR=0; RD=1; */

CH376_CMD_PORT &= ~_BV(CH376_CS)&~_BV(CH376_WR); CH376_CMD_PORT |= _BV(CH376_RD); //_delay_us(0.2); //CH376_DATA_DDR = 0xFF; /* 该操作无意义,仅作延时,CH376要求读写脉冲宽度大于100nS */

/* 输出无效的控制信号, 完成操作CH376芯片, CS=1; WR=1; RD=1; */

CH376_CMD_PORT |= _BV(CH376_CS)|_BV(CH376_WR)|_BV(CH376_RD);

CH376_DATA_DDR = 0x00; /* 禁止数据输出 */

_delay_us(2); /* 至少延时2uS */

}

void CH376WriteData( uint8_t data ) /* 外部定义的被CH376程序库调用的子程序,向CH376写数据 */

{ //_delay_us(5); /* 至少延时2uS */ CH376_CMD_PORT &= ~_BV(CH376_A0); /* 输出A0=0; 打开数据端口 */

CH376_DATA_PORT = data; /* 向CH376的并口输出数据 */

CH376_DATA_DDR = 0xFF; /* 并口D0-D7输出 */ /* 输出有效写控制信号, 写CH376芯片的数据端口, CS=0; WR=0; RD=1; */

CH376_CMD_PORT &= ~_BV(CH376_CS)&~_BV(CH376_WR); CH376_CMD_PORT |= _BV(CH376_RD); //_delay_us(0.2);

//CH376_DATA_DDR = 0xFF; /* 该操作无意义,仅作延时,CH376要求读写脉冲宽度大于100nS */

/* 输出无效的控制信号, 完成操作CH376芯片, CS=1; WR=1; RD=1; */

CH376_CMD_PORT |= _BV(CH376_CS)|_BV(CH376_WR)|_BV(CH376_RD);

CH376_DATA_DDR = 0x00; /* 禁止数据输出 */

_delay_us(2); /* 至少延时1.2uS */

}

uint8_t CH376ReadData( void ) /* 外部定义的被CH376程序库调用的子程序,从CH376读数据 */

{

uint8_t data;

_delay_us(1.5); /* 至少延时1.2uS */ CH376_CMD_PORT &= ~_BV(CH376_A0); /* 输出A0=0; 打开数据端口 */

CH376_DATA_DDR = 0x00; /* 数据输入 */ /* 输出有效读控制信号, 读CH376芯片的数据端口, CS=0; WR=1; RD=0; */ CH376_CMD_PORT &= ~_BV(CH376_CS)&~_BV(CH376_RD); CH376_CMD_PORT |= _BV(CH376_WR);

CH376_DATA_DDR = 0x00; /* 该操作无意义,仅作延时,CH376要求读写脉冲宽度大于100nS */

data = CH376_DATA_PIN; /* 从CH376的并口PA输入数据 */

/* 输出无效的控制信号, 完成操作CH376芯片, CS=1; WR=1; RD=1; */ CH376_CMD_PORT |= _BV(CH376_CS)|_BV(CH376_WR)|_BV(CH376_RD);

return( data );

}

/* 查询CH376中断(INT#低电平) */

uint8_t CH376QueryInterrupt( void )

{ //uint8_t i; //PORTB ^= _BV(PB0); //for(i=0;i<200;i++) // _delay_ms(10);

return( CH376_CMD_PIN & _BV(CH376_INT) ); /* 如果连接了CH376的中断引脚则直接查询中断引脚 */

}

////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////// File Access API //////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////

uint8_t CH376InitHost( void ) /* 初始化CH376 */

{

uint8_t res;

//CH376PortInit( ); /* 接口硬件初始化 */

CH376WriteCmd( CMD_CHECK_EXIST ); /* 测试单片机与CH376之间的通讯接口 */

CH376WriteData( 0x65 );

res = CH376ReadData( );

if ( res != 0x9A ) return( ERR_USB_UNKNOWN ); /* 通讯接口不正常,可能原因有:接口连接异常,其它设备影响(片选不唯一),串口波特率,一直在复位,晶振不工作 */

CH376WriteCmd( CMD_SET_USB_MODE ); /* 设备USB工作模式 */

CH376WriteData( 0x06 );

_delay_us(20);

res = CH376ReadData( );

if ( res == CMD_RET_SUCCESS ) return( USB_INT_SUCCESS );

else return( ERR_USB_UNKNOWN ); /* 设置模式错误 */

}

uint8_t CH376WaitInterrupt( void ) { while ( CH376QueryInterrupt() ); /* 一直等中断 */ return( CH376GetIntStatus( ) ); /* 检测到中断 */ }

uint8_t CH376GetIntStatus( void ) /* 获取中断状态并取消中断请求 */

{

uint8_t s;

CH376WriteCmd( CMD_GET_STATUS );

s = CH376ReadData( );

return( s );

}

uint8_t CH376SendCmdWaitInt( uint8_t cmd ) /* 发出命令码后,等待中断 */

{

CH376WriteCmd( cmd );

return( CH376WaitInterrupt( ) );

}

uint8_t CH376DiskConnect( void ) /* 检查U盘是否连接,不支持SD卡 */

{

if ( CH376QueryInterrupt( ) ) CH376GetIntStatus( ); /* 检测到中断 */

return( CH376SendCmdWaitInt( CMD_DISK_CONNECT ) );

}

uint8_t CH376DiskMount( void ) /* 初始化磁盘并测试磁盘是否就绪 */

{

return( CH376SendCmdWaitInt( CMD_DISK_MOUNT ) );

}

void CH376SetFileName( const char *name ) /* 设置将要操作的文件的文件名 */

{ uint8_t c;

CH376WriteCmd( CMD_SET_FILE_NAME );

c = *name;

CH376WriteData( c );

while ( c ) {

name ++;

c = *name;

if ( c == DEF_SEPAR_CHAR1 || c == DEF_SEPAR_CHAR2 ) c = 0; /* 强行将文件名截止 */

CH376WriteData( c );

}

}

uint8_t CH376FileOpen( void ) /* 在根目录或者当前目录下打开文件或者目录(文件夹) */

{

return( CH376SendCmdWaitInt( CMD_FILE_OPEN ) );

}

uint8_t CH376ReadBlock( uint8_t *buf ) /* 从当前主机端点的接收缓冲区读取数据块,返回长度 */

{

uint8_t s, l;

CH376WriteCmd( CMD_RD_USB_DATA0 );

s = l = CH376ReadData( ); /* 长度 */

if ( l ) {

do {

*buf = CH376ReadData( );

buf ++;

} while ( -- l );

}

return( s );

}

uint8_t CH376ByteLocate( uint32_t offset ) /* 以字节为单位移动当前文件指针 */

{

CH376WriteCmd( CMD_BYTE_LOCATE );

CH376WriteData( (uint8_t)offset );

CH376WriteData( (uint8_t)((uint16_t)offset>>8) );

CH376WriteData( (uint8_t)(offset>>16) );

CH376WriteData( (uint8_t)(offset>>24) );

return( CH376WaitInterrupt() );

}

uint8_t CH376ByteRead( uint8_t *buf, uint16_t reqcount, uint16_t *realcount ) /* 以字节为单位从当前位置读取数据块 */

{

uint8_t s;

if ( realcount ) *realcount = 0; CH376WriteCmd( CMD_BYTE_READ );

//CH376WriteData( (uint8_t)reqcount );

//CH376WriteData( (uint8_t)(reqcount>>8) ); CH376WriteData( 0x00 ); CH376WriteData( 0x02 );

while ( 1 ) { //PORTB |= _BV(PB0);

s = CH376WaitInterrupt(); //s = CH376GetIntStatus(); PORTB |= _BV(PB0);

if ( s == USB_INT_DISK_READ ) {

s = CH376ReadBlock( buf ); /* 从当前主机端点的接收缓冲区读取数据块,返回长度 */

CH376WriteCmd( CMD_BYTE_RD_GO );

buf += s;

if ( realcount ) *realcount += s;

}

/* else if ( s == USB_INT_SUCCESS ) return( s );*/ /* 结束 */

else return( s ); /* 错误 */

}

}

int main (void) { ioinit(); if(VS1053B_Init()) return(1); if(CH376InitHost() != USB_INT_SUCCESS) return(1); buffer = malloc(32); while(1)

{ while(ch376_status == DISK_UNCONNECTED) { if(CH376DiskConnect() == USB_INT_SUCCESS) /* 检查U盘是否连接,等待U盘插入,对于SD卡,可以由单片机直接查询SD卡座的插拔状态引脚 */ { ch376_status = DISK_CONNECTED; /* 对于检测到USB设备的,最多等待10*50mS */

for(i=0;i<50;i++) _delay_ms( 10 ); if ( CH376DiskMount( ) != USB_INT_SUCCESS ) /* 初始化磁盘并测试磁盘是否就绪 */ return (1); ch376_status = DISK_MOUNTED; break; } _delay_ms(10); } while(ch376_status == DISK_MOUNTED) { CH376SetFileName( "/CDC" ); if ( CH376FileOpen() != ERR_OPEN_DIR ) return (1); CH376SetFileName( "CD1" ); if ( CH376FileOpen() != ERR_OPEN_DIR ) return (1); CH376SetFileName( "TRACK01.MP3" ); if ( CH376FileOpen() != USB_INT_SUCCESS ) return (1);

//PORTB |= _BV(PB0); //VS1053B_SoftReset(); CH376ByteRead(buffer,32,&realdatasize); /* //PORTB |= _BV(PB0); while(realdatasize == 32) { for(i=0;i { //PORTB |= _BV(PB0);

VS1053B_WriteDAT(buffer[i]); //PORTB &= ~_BV(PB0);

} CH376ByteRead(buffer,32,&realdatasize); } for(i=0;i {

VS1053B_WriteDAT(buffer[i]);

} CH376ByteLocate(0); */ //VS1053B_Test(1500); PORTB |= _BV(PB0); }

} return (0); }


移植CH376的源程序,只要修改与硬件相关的接口程序就可以了,如:XXX_HW.C,XXX_SW.C,HAL_BASE.C,而不是修该FILE_SYS.C,这样出现问题,也便于我们分析,建议重新移植


现在是这样一个情况,查询CH376ReadStatus s = CH376ReadStatus(); if((s & 0x40) == 0x00) { PORTB |= _BV(PB0); for(s=0;s<10;s++) _delay_ms(1000); PORTB &= ~_BV(PB0); } 在指示灯亮的期间,测试INT#脚,电平为3.3伏。 搞不懂啦。按道理status的位7就是INT#的状态。这个应该从那方面来查找错误?

有AVR的各函数测试的程序没?麻烦再指导一下。


下面几个核心函数能不能帮我看看。CH376 编译通过的,没有警告和错误。 一个时钟周期62.5ns avr atmega16 16M

先谢谢了

void CH376WriteCmd( uint8_t cmd ) /* 外部定义的被CH376程序库调用的子程序,向CH376写命令 */

{ CH376_DATA_PORT = cmd; /* 向CH376的并口输出数据 */

CH376_DATA_DDR = 0xFF; /* 并口D0-D7输出 */

/* 输出有效写控制信号, 写CH376芯片的命令端口, CS=0; WR=0; A0=1; RD=1; */

CH376_CMD_PORT &= ~_BV(CH376_CS)&~_BV(CH376_WR); CH376_CMD_PORT |= _BV(CH376_RD)|_BV(CH376_A0);

asm volatile("nop\n\t"::); /* 延时,CH376要求读写脉冲宽度大于40nS */

/* 输出无效的控制信号, 完成操作CH376芯片, CS=1; WR=1; RD=1; */

CH376_CMD_PORT |= _BV(CH376_CS)|_BV(CH376_WR)|_BV(CH376_RD); CH376_DATA_DDR = 0x00; /* 禁止数据输出 */

_delay_us(1.5);

}

void CH376WriteData( uint8_t data ) /* 外部定义的被CH376程序库调用的子程序,向CH376写数据 */

{ CH376_DATA_PORT = data; /* 向CH376的并口输出数据 */

CH376_DATA_DDR = 0xFF; /* 并口D0-D7输出 */ /* 输出有效写控制信号, 写CH376芯片的数据端口, CS=0; WR=0; A0=0; RD=1; */

CH376_CMD_PORT &= ~_BV(CH376_CS)&~_BV(CH376_WR)&~_BV(CH376_A0); CH376_CMD_PORT |= _BV(CH376_RD); asm volatile("nop\n\t"::); /* 延时,CH376要求读写脉冲宽度大于40nS */

/* 输出无效的控制信号, 完成操作CH376芯片, CS=1; WR=1; RD=1; */

CH376_CMD_PORT |= _BV(CH376_CS)|_BV(CH376_WR)|_BV(CH376_RD); CH376_DATA_DDR = 0x00; /* 禁止数据输出 */

_delay_us(0.6);

}

/* 位 7 是中断标志,低有效,等效于 INT#引脚, 位 4 是忙标志,高有效,等效于 SPI 接口的 BZ 引脚 */ uint8_t CH376ReadStatus( void ) /* 外部定义的被CH376程序库调用的子程序,从CH376读数据 */

{

uint8_t data;

CH376_DATA_DDR = 0x00; /* 数据输入 */ /* 输出有效读控制信号, 读CH376芯片的状态端口, CS=0; RD=0; WR=1; A0 =1; */ CH376_CMD_PORT &= ~_BV(CH376_CS)&~_BV(CH376_RD); CH376_CMD_PORT |= _BV(CH376_A0)|_BV(CH376_WR);

asm volatile("nop\n\t"::); /* 延时,CH376要求读写脉冲宽度大于40nS */

data = CH376_DATA_PIN; /* 从CH376的并口PA输入数据 */

/* 输出无效的控制信号, 完成操作CH376芯片, CS=1; WR=1; RD=1; */ CH376_CMD_PORT |= _BV(CH376_CS)|_BV(CH376_WR)|_BV(CH376_RD); return( data );

}

uint8_t CH376ReadData( void ) /* 外部定义的被CH376程序库调用的子程序,从CH376读数据 */

{

uint8_t data;

_delay_us(0.5); /* 确保读写周期大于0.6uS */ CH376_DATA_DDR = 0x00; /* 数据输入 */ /* 输出有效读控制信号, 读CH376芯片的数据端口, CS=0; RD=0; A0=0; WR=1; */ CH376_CMD_PORT &= ~_BV(CH376_CS)&~_BV(CH376_RD)&~_BV(CH376_A0);

CH376_CMD_PORT |= _BV(CH376_WR); asm volatile("nop\n\t"::); /* 延时,CH376要求读写脉冲宽度大于40nS */

data = CH376_DATA_PIN; /* 从CH376的并口PA输入数据 */

/* 输出无效的控制信号, 完成操作CH376芯片, CS=1; WR=1; RD=1; */ CH376_CMD_PORT |= _BV(CH376_CS)|_BV(CH376_WR)|_BV(CH376_RD);

return( data );

}

/* 查询CH376中断(INT#低电平) */

uint8_t CH376QueryInterrupt( void )

{

return( CH376_CMD_PIN & _BV(CH376_INT) ); /* 如果连接了CH376的中断引脚则直接查询中断引脚 */

}


单片机在IO口初始化的时候 A0 = 0;WR = 1;RD =1;CS =1; 读写命令之后A0为0

void CH376WriteCmd( uint8_t cmd ) /* 外部定义的被CH376程序库调用的子程序,向CH376写命令 */

{ CH376_DATA_PORT = cmd; /* 向CH376的并口输出数据 */

CH376_DATA_DDR = 0xFF; /* 并口D0-D7输出 */

/* 输出有效写控制信号, 写CH376芯片的命令端口, CS=0; WR=0; A0=1; RD=1; */

CH376_CMD_PORT &= ~_BV(CH376_CS)&~_BV(CH376_WR); CH376_CMD_PORT |= _BV(CH376_RD)|_BV(CH376_A0);

asm volatile("nop\n\t"::); /* 延时,CH376要求读写脉冲宽度大于40nS */

/* 输出无效的控制信号, 完成操作CH376芯片, CS=1; WR=1; RD=1; */

CH376_CMD_PORT |= _BV(CH376_CS)|_BV(CH376_WR)|_BV(CH376_RD);

CH376_CMD_PORT &= ~_BV(CH376_A0); /* 输出A0=0; 打开数据端口 */

CH376_DATA_DDR = 0x00; /* 禁止数据输出 */

_delay_us(1.5);

}

/* 位 7 是中断标志,低有效,等效于 INT#引脚, 位 4 是忙标志,高有效,等效于 SPI 接口的 BZ 引脚 */ uint8_t CH376ReadStatus( void ) /* 外部定义的被CH376程序库调用的子程序,从CH376读数据 */

{

uint8_t data;

CH376_DATA_DDR = 0x00; /* 数据输入 */ /* 输出有效读控制信号, 读CH376芯片的状态端口, CS=0; RD=0; WR=1; A0 =1; */ CH376_CMD_PORT &= ~_BV(CH376_CS)&~_BV(CH376_RD); CH376_CMD_PORT |= _BV(CH376_A0)|_BV(CH376_WR);

asm volatile("nop\n\t"::); /* 延时,CH376要求读写脉冲宽度大于40nS */

data = CH376_DATA_PIN; /* 从CH376的并口PA输入数据 */

/* 输出无效的控制信号, 完成操作CH376芯片, CS=1; WR=1; RD=1; */ CH376_CMD_PORT |= _BV(CH376_CS)|_BV(CH376_WR)|_BV(CH376_RD);

CH376_CMD_PORT &= ~_BV(CH376_A0); /* 输出A0=0; 打开数据端口 */

return( data );

}

s = CH376ReadStatus(); if((s & 0x40) == 0x00) { PORTB |= _BV(PB0); for(s=0;s<10;s++) _delay_ms(1000); PORTB &= ~_BV(PB0); } 判断第6位有什么用? 程序中没有用到吗


仔细看了下时序,命令结束是要把A0拉底,没注意,直接按照命令和数据口选择的要求设置了A0 .拉低A0在硬件设计上是怎么回事?一般按照地址的概念没这个必要。

还有把位7误解为了8位里的第7位。

建议手册里面强调一下,或者图示,呵呵。

谢谢指导。

上班了我再确认一下。


CH376在并口模式下占用2个地址:命令口地址和数据口地址,前者要求A0 = 1,后者要求A0 = 0


我还想请教一下,命令端口地址是A=1 写命令结束设置A=0 的目的是什么?为什么是必须的操作?


你可以不设置,但是A=0是默认的,如果你不设置的话,写数据的时候要切换为0.每次都不会到初始状态。也就是说切换回0不是必须的,建议这样切换


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