dsp 通过spi控制ch376读写SD卡失败求解

可以初始化

可以CH376DiskMount( ) == USB_INT_SUCCESS

然后新建文件之后看不到,写了数据就更看不到了,不过下次执行CH376FileOpenPath的时候,程序显示找到了那个文件,但PC里看不到(有人说需要用XP系统?),SD卡已经是FAT32格式。

或者根本就没有新建成功。

总之我现在有点崩溃了,跪求大神救我,如果有技术人员愿意帮我就更好了,我可以把整个程序发过去。

下面附main函数和部分函数定义,求大神看一下。


void main(void)

{

   

// 步骤 1. 初始化系统控制:

// 设置PLL, WatchDog, 使能外设时钟

// 下面这个函数可以从DSP280x_SysCtrl.c文件中找到.

   InitSysCtrl();


// 步骤 2. 初始化通用输入输出多路复用器GPIO:

// 这个函数在DSP280x_Gpio.c源文件中被定义了

// 这个函数使GPIO控制类寄存器初始化到默认状态

// InitGpio();  // Skipped for this example


// 次函数在DSP280x_Spi.c文件里面-----------------------------------------(1)

   InitSpiaGpio();  //开发板使用SPIA


//步骤 3. 清除所有中断,初始化中断向量表:

// 禁止CPU全局中断

   DINT;


// 初始化PIE控制寄存器到他们的默认状态.

// 这个默认状态就是禁止PIE中断及清除所有PIE中断标志

// 这个函数放在DSP280x_PieCtrl.c源文件里

   InitPieCtrl();


// 禁止CPU中断,清除CPU中断标志位

   IER = 0x0000;

   IFR = 0x0000;

   

// 初始化PIE中断向量表,并使其指向中断服务子程序(ISR)

// 这些中断服务子程序被放在了DSP280x_DefaultIsr.c源文件中

// 这个函数放在了DSP280x_PieVect.c源文件里面.

   InitPieVectTable();

// 步骤 4.初始化片内外设:--------------------------------------------------(2)

   CH376_PORT_INIT(  );  /* 由于使用SPI读写时序,所以进行初始化SPI,同时初始化GPIO74,初始化FIFO */



   GpioDataRegs.GPCSET.bit.GPIO74 = 1;  /* 防止之前未通过xEndCH376Cmd禁止SPI片选 */



// 步骤 5. 以下是用户编写的指定代码, 使能相关中断:#####################################################

   GpioDataRegs.GPASET.bit.GPIO4 = 1;//置1---共阴极LED14灭


   delay_loop_ms(50);

   statecheck = mInitCH376Host( );  /* 初始化CH376 */

   mStopIfError( statecheck );

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



   GpioDataRegs.GPACLEAR.bit.GPIO4 = 1;//清零---共阴极LED14亮


   delay_loop_ms(500);


   for ( s = 0; s < 10; s ++ ) {  /* 最长等待时间,10*50mS */

  delay_loop_ms(50);

   if ( CH376DiskMount( ) == USB_INT_SUCCESS ) break;  /* 初始化磁盘并测试磁盘是否就绪 */

   }


   /* 如果.TXT文件已经存在则添加数据到尾部,如果不存在则新建文件 */

   s = CH376FileOpenPath( "/161211.TXT" );  /* 打开文件,该文件在根目录下 */


   if ( s == USB_INT_SUCCESS ) {  /* 文件存在并且已经被打开,移动文件指针到尾部以便添加数据 */

    s = CH376ByteLocate( 0xFFFFFFFF );  /* 移到文件的尾部 */

   mStopIfError( s );

   }

   else if ( s == ERR_MISS_FILE ) {  /* 没有找到文件,必须新建文件 */

   s = CH376FileCreatePath( "/161211.TXT"  );  /* 新建文件并打开,如果文件已经存在则先删除后再新建,不必再提供文件名,刚才已经提供给CH376FileOpen */

   mStopIfError( s );

   }

   else mStopIfError( s );  /* 打开文件时出错 */





   strcpy( buf, "ADC" );

   s = CH376ByteWrite( buf, 3, NULL );  /* 以字节为单位向文件写入数据 */

   mStopIfError( s );


   //delay_loop_ms(50);


   s = CH376FileClose( 0x01 );  /* 关闭文件,自动计算文件长度,以字节为单位写文件,建议让程序库关闭文件以便自动更新文件长度 */

   mStopIfError( s );


   LED14flash();



}

//end of main############################################################################





#definexEndCH376Cmd()   GpioDataRegs.GPCSET.bit.GPIO74 = 1; /* SPI片选无效,结束CH376命令,仅用于SPI接口方式 */


//延迟函数

void delay_loop_100ms()//0.1s

{

    long      i;

    for (i = 0; i < 15000000; i++) {} //1ms

}


void delay_loop_ms(int n)//0.001s

{

    long      i;

    for (i = 0; i < 150000*n; i++) {} //1ms

}


void delay_loop_us(int n)//0.000001s

{

    long      i;

    for (i = 0; i < 150*n; i++) {} //1us

}


voidCH376_PORT_INIT(  )  /* 由于使用SPI读写时序,所以进行初始化SPI,同时初始化GPIO74,初始化FIFO */

{

/* 如果是硬件SPI接口,那么可使用mode3(CPOL=1&CPHA=1)或mode0(CPOL=0&CPHA=0),CH376在时钟上升沿采样输入,下降沿输出,数据位是高位在前 */

//CH376_SPI_SCS = 1;  /* 禁止SPI片选 */

/* 对于双向I/O引脚模拟SPI接口,那么必须在此设置SPI_SCS,SPI_SCK,SPI_SDI为输出方向,SPI_SDO为输入方向 */

//SPCR = 0x5C;  /* 设置SPI模式3, DORD=0(MSB first), CPOL=1, CPHA=1, CH376也支持SPI模式0 */



SpiaRegs.SPICCR.all =0x0047;// SPI软件复位, 极性位为1(下降沿发送数据), 每次移         0100 0111

                           //进和移出8位字长度;禁止SPI内部回送(LOOKBACK)功能;

SpiaRegs.SPICTL.all =0x0006; // 使能主机模式,正常相位(0),使能主机发送,禁止接收  0000 0110

                           //溢出中断,禁止SPI中断;

SpiaRegs.SPIBRR =0x0011;//SPI波特率=150M/4/18=2MHZ

SpiaRegs.SPICCR.all =0x00C7;//停止SPI软件复位准备接收或发送;禁止SPI内部回送;  1100 0111

SpiaRegs.SPIPRI.bit.FREE = 1;  // 自由运行



//GpioCtrlRegs.GPCMUX1.bit.GPIO74 = 0;               //GPIO74作为普通IO

//GpioCtrlRegs.GPCDIR.bit.GPIO74 = 1;                   //GPIO74方向为输出

//GpioCtrlRegs.GPCMUX1.bit.GPIO73 = 0;               //GPIO73作为普通IO

//GpioCtrlRegs.GPCDIR.bit.GPIO73 = 0;                   //GPIO73方向为输入


//GpioCtrlRegs.GPAMUX1.bit.GPIO4 = 0;//GPIO4---->LED作为DEGUG的标志,之后要删掉!!!!**********************************

//GpioCtrlRegs.GPADIR.bit.GPIO4 = 1;


SpiaRegs.SPIFFTX.all=0xE040;//使能FIFO;清除发送中断标志位;禁止FIFO发送中断;

                                //发送中断级别定义为0;

SpiaRegs.SPIFFRX.all=0x204F;//清除FF溢出标志位;清除溢出接受中断标志位;禁止

                           //FF接受中断;接受中断级别为16;

SpiaRegs.SPIFFCT.all=0x0;//SPITXBUF到移位寄存器传送不延迟;


}


UINT8Spi376Exchange( UINT8 d )  /* 硬件SPI输出且输入8个位数据 */

{

Uint16 sdata;

Uint16 rdata;

UINT8 tempdata2;


sdata=(d<<8);

SpiaRegs.SPITXBUF=sdata;


while(SpiaRegs.SPIFFRX.bit.RXFFST !=1) { }// wait for the transmission


rdata = SpiaRegs.SPIRXBUF;   //每次都保证发送和接收都进行一次,这样FIFO中才不会滞留数据

tempdata2=(UINT8)rdata;

return( tempdata2 );

}


void   LED14flash()

{

GpioDataRegs.GPACLEAR.bit.GPIO4 = 1;//清零---共阴极LED14亮

delay_loop_100ms();

GpioDataRegs.GPASET.bit.GPIO4 = 1;//置1---共阴极LED14灭

delay_loop_100ms();

GpioDataRegs.GPACLEAR.bit.GPIO4 = 1;//清零---共阴极LED14亮

delay_loop_100ms();

GpioDataRegs.GPASET.bit.GPIO4 = 1;//置1---共阴极LED14灭

}


voidmStopIfError( UINT8 iError )

{

if ( iError == USB_INT_SUCCESS )   /* 操作成功 */

{


//LED14flash();


}


}


voidxWriteCH376Cmd( UINT8 mCmd )  /* 向CH376写命令 */

{

GpioDataRegs.GPCSET.bit.GPIO74 = 1;  /* 防止之前未通过xEndCH376Cmd禁止SPI片选 */

delay_loop_us(2);

/* 对于双向I/O引脚模拟SPI接口,那么必须确保已经设置SPI_SCS,SPI_SCK,SPI_SDI为输出方向,SPI_SDO为输入方向 */

GpioDataRegs.GPCCLEAR.bit.GPIO74 = 1;  /* SPI片选有效 */

delay_loop_us(2);


Spi376Exchange( mCmd );  /* 发出命令码 */

delay_loop_us(2);

/* 延时1.5uS确保读写周期大于1.5uS,或者用上面一行的状态查询代替 */


}


voidxWriteCH376Data( UINT8 mData )  /* 向CH376写数据 */

{

Spi376Exchange( mData );

delay_loop_us(2);

}


UINT8xReadCH376Data( void )  /* 从CH376读数据 */

{

delay_loop_us(2);

return( Spi376Exchange( 0xFF ) );

}


UINT8mInitCH376Host( void )  /* 初始化CH376 */

{

UINT8res;


//CH376_PORT_INIT( );  /* 接口硬件初始化 *///接口可以在硬件初始化之前就完成初始化


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

xWriteCH376Data( 0x56 );

res = xReadCH376Data( );

xEndCH376Cmd( );

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

xWriteCH376Cmd( CMD11_SET_USB_MODE );  /* 设备USB工作模式 */

xWriteCH376Data( 0x03 );//USB 05

delay_loop_ms(20);

res = xReadCH376Data( );

xEndCH376Cmd( );


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

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

}


UINT8Query376Interrupt( void )

{

return( GpioDataRegs.GPCDAT.bit.GPIO73 ? FALSE : TRUE );  /* 如果连接了CH376的中断引脚则直接查询中断引脚 */

}


UINT8Wait376Interrupt( void )  /* 等待CH376中断(INT#低电平),返回中断状态码, 超时则返回ERR_USB_UNKNOWN */

{

UINT32i;

for ( i = 0; i < 30000000; i ++ ) {  /* 计数防止超时,默认的超时时间,与单片机主频有关 */

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

/* 在等待CH376中断的过程中,可以做些需要及时处理的其它事情 */

}

return( ERR_USB_UNKNOWN );  /* 不应该发生的情况 */

}


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

{

UINT8s;

xWriteCH376Cmd( CMD01_GET_STATUS );

s = xReadCH376Data( );

xEndCH376Cmd( );

return( s );

}


UINT8CH376SendCmdWaitInt( UINT8 mCmd )  /* 发出命令码后,等待中断 */

{

xWriteCH376Cmd( mCmd );

xEndCH376Cmd( );

return( Wait376Interrupt( ) );

}


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

{

return( CH376SendCmdWaitInt( CMD0H_DISK_MOUNT ) );

}


UINT8CH376FileOpen( PUINT8 name )  /* 在根目录或者当前目录下打开文件或者目录(文件夹) */

{

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

return( CH376SendCmdWaitInt( CMD0H_FILE_OPEN ) );

}


UINT8CH376FileOpenPath( PUINT8 PathName )  /* 打开多级目录下的文件或者目录(文件夹),支持多级目录路径,支持路径分隔符,路径长度不超过255个字符 */

{

return( CH376FileOpenDir( PathName, 0xFF ) );

}


UINT8CH376FileOpenDir( PUINT8 PathName, UINT8 StopName )  /* 打开多级目录下的文件或者目录的上级目录,支持多级目录路径,支持路径分隔符,路径长度不超过255个字符 */

/* StopName 指向最后一级文件名或者目录名 */

{

UINT8i, s;

s = 0;

i = 1;  /* 跳过有可能的根目录符 */

while ( 1 ) {

while ( PathName[i] != DEF_SEPAR_CHAR1 && PathName[i] != DEF_SEPAR_CHAR2 && PathName[i] != 0 ) ++ i;  /* 搜索下一个路径分隔符或者路径结束符 */

if ( PathName[i] ) i ++;  /* 找到了路径分隔符,修改指向目标文件的最后一级文件名 */

else i = 0;  /* 路径结束 */

s = CH376FileOpen( &PathName[s] );  /* 打开文件或者目录 */

if ( i && i != StopName ) {  /* 路径尚未结束 */

if ( s != ERR_OPEN_DIR ) {  /* 因为是逐级打开,尚未到路径结束,所以,如果不是成功打开了目录,那么说明有问题 */

if ( s == USB_INT_SUCCESS ) return( ERR_FOUND_NAME );  /* 中间路径必须是目录名,如果是文件名则出错 */

else if ( s == ERR_MISS_FILE ) return( ERR_MISS_DIR );  /* 中间路径的某个子目录没有找到,可能是目录名称错误 */

else return( s );  /* 操作出错 */

}

s = i;  /* 从下一级目录开始继续 */

}

else return( s );  /* 路径结束,USB_INT_SUCCESS为成功打开文件,ERR_OPEN_DIR为成功打开目录(文件夹),其它为操作出错 */

}

}


UINT8CH376FileCreatePath( PUINT8 PathName )  /* 新建多级目录下的文件,支持多级目录路径,支持路径分隔符,路径长度不超过255个字符 */

{

UINT8s;

UINT8Name;

Name = CH376SeparatePath( PathName );  /* 从路径中分离出最后一级文件名,返回最后一级文件名的偏移 */

if ( Name ) {  /* 是多级目录 */

s = CH376FileOpenDir( PathName, Name );  /* 打开多级目录下的最后一级目录,即打开新建文件的上级目录 */

if ( s != ERR_OPEN_DIR ) {  /* 因为是打开上级目录,所以,如果不是成功打开了目录,那么说明有问题 */

if ( s == USB_INT_SUCCESS ) return( ERR_FOUND_NAME );  /* 中间路径必须是目录名,如果是文件名则出错 */

else if ( s == ERR_MISS_FILE ) return( ERR_MISS_DIR );  /* 中间路径的某个子目录没有找到,可能是目录名称错误 */

else return( s );  /* 操作出错 */

}

}

return( CH376FileCreate( &PathName[Name] ) );  /* 在根目录或者当前目录下新建文件 */

}


UINT8CH376SeparatePath( PUINT8 path )  /* 从路径中分离出最后一级文件名或者目录(文件夹)名,返回最后一级文件名或者目录名的字节偏移 */

{

PUINT8pName;

for ( pName = path; *pName != 0; ++ pName );  /* 到文件名字符串结束位置 */

while ( *pName != DEF_SEPAR_CHAR1 && *pName != DEF_SEPAR_CHAR2 && pName != path ) pName --;  /*  搜索倒数第一个路径分隔符 */

if ( pName != path ) pName ++;  /* 找到了路径分隔符,则修改指向目标文件的最后一级文件名,跳过前面的多级目录名及路径分隔符 */

return( pName - path );

}



UINT8CH376ByteLocate( UINT32 offset )  /* 以字节为单位移动当前文件指针 */

{

xWriteCH376Cmd( CMD4H_BYTE_LOCATE );

xWriteCH376Data( (UINT8)offset );

xWriteCH376Data( (UINT8)((UINT16)offset>>8) );

xWriteCH376Data( (UINT8)(offset>>16) );

xWriteCH376Data( (UINT8)(offset>>24) );

xEndCH376Cmd( );

return( Wait376Interrupt( ) );

}


UINT8CH376FileCreate( PUINT8 name )  /* 在根目录或者当前目录下新建文件,如果文件已经存在那么先删除 */

{

if ( name ) CH376SetFileName( name );  /* 设置将要操作的文件的文件名 */

return( CH376SendCmdWaitInt( CMD0H_FILE_CREATE ) );

}


UINT8CH376DirCreate( PUINT8 name )  /* 在根目录下新建目录(文件夹)并打开,如果目录已经存在那么直接打开 */

{

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


return( CH376SendCmdWaitInt( CMD0H_DIR_CREATE ) );

}


voidCH376SetFileName( PUINT8 name )  /* 设置将要操作的文件的文件名 */

{

/*UINT8i;*/

UINT8c;


xWriteCH376Cmd( CMD10_SET_FILE_NAME );

/*for ( i = MAX_FILE_NAME_LEN; i != 0; -- i ) {

c = *name;

xWriteCH376Data( c );

if ( c == 0 ) break;

name ++;

}*/

c = *name;

xWriteCH376Data( c );

while ( c ) {

name ++;

c = *name;

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

xWriteCH376Data( c );

}

xEndCH376Cmd( );

}


UINT8CH376ByteWrite( PUINT8 buf, UINT16 ReqCount, PUINT16 RealCount )  /* 以字节为单位向当前位置写入数据块 */

{

//UINT8s;

xWriteCH376Cmd( CMD2H_BYTE_WRITE );

xWriteCH376Data( (UINT8)ReqCount );

xWriteCH376Data( (UINT8)(ReqCount>>8) );

xEndCH376Cmd( );

if ( RealCount ) *RealCount = 0;

while ( 1 ) {

s = Wait376Interrupt( );

if ( s == USB_INT_DISK_WRITE ) {

s = CH376WriteReqBlock( buf );  /* 向内部指定缓冲区写入请求的数据块,返回长度 */

xWriteCH376Cmd( CMD0H_BYTE_WR_GO );

xEndCH376Cmd( );

buf += s;

if ( RealCount ) *RealCount += s;

}

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

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

}

}



UINT8CH376WriteReqBlock( PUINT8 buf )  /* 向内部指定缓冲区写入请求的数据块,返回长度 */

{

UINT8s, l;

xWriteCH376Cmd( CMD01_WR_REQ_DATA );

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

if ( l ) {

do {

xWriteCH376Data( *buf );

buf ++;

} while ( -- l );

}

xEndCH376Cmd( );

return( s );

}



UINT8CH376FileClose( UINT8 UpdateSz )  /* 关闭当前已经打开的文件或者目录(文件夹) */

{

return( CH376SendCmdDatWaitInt( CMD1H_FILE_CLOSE, UpdateSz ) );

}


UINT8CH376SendCmdDatWaitInt( UINT8 mCmd, UINT8 mDat )  /* 发出命令码和一字节数据后,等待中断 */

{

xWriteCH376Cmd( mCmd );

xWriteCH376Data( mDat );

xEndCH376Cmd( );

return( Wait376Interrupt( ) );

}



void CH376SetFileName( PUINT8 name )  /* 设置将要操作的文件的文件名 */
{
/* UINT8 i;*/
 UINT8 c;
#ifndef DEF_IC_V43_U
 UINT8 s;
 xWriteCH376Cmd( CMD01_GET_IC_VER );
 if ( xReadCH376Data( ) < 0x43 ) {
  if ( CH376ReadVar8( VAR_DISK_STATUS ) < DEF_DISK_READY ) {
   xWriteCH376Cmd( CMD10_SET_FILE_NAME );
   xWriteCH376Data( 0 );
   s = CH376SendCmdWaitInt( CMD0H_FILE_OPEN );
   if ( s == USB_INT_SUCCESS ) {
    s = CH376ReadVar8( 0xCF );
    if ( s ) {
     CH376WriteVar32( 0x4C, CH376ReadVar32( 0x4C ) + ( (UINT16)s << 8 ) );
     CH376WriteVar32( 0x50, CH376ReadVar32( 0x50 ) + ( (UINT16)s << 8 ) );
     CH376WriteVar32( 0x70, 0 );
    }
   }
  }
 }
#endif
 xWriteCH376Cmd( CMD10_SET_FILE_NAME );
/* for ( i = MAX_FILE_NAME_LEN; i != 0; -- i ) {
  c = *name;
  xWriteCH376Data( c );
  if ( c == 0 ) break;
  name ++;
 }*/
 c = *name;
 xWriteCH376Data( c );
 while ( c ) {
  name ++;
  c = *name;
  if ( c == DEF_SEPAR_CHAR1 || c == DEF_SEPAR_CHAR2 ) c = 0;  /* 强行将文件名截止 */
  xWriteCH376Data( c );
 }
 xEndCH376Cmd( );
}

不要定义DEF_IC_V43_U,以兼容低版本。你可以把376版本号打印出来看是多少?


感激之情无以言表!!仅有3分全数奉上,无法表达我的感激之情,所以我是跪在屏幕前面回帖的。


反思自己:不知被什么有毒电波侵蚀,自信的认为我的芯片就是新版固件,就把兼容部分全部去掉。

若不是经高人点醒,至今仍活在梦里,苦苦调试!


再拜,再拜!



不客气


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