看了很多资料,例程,但还是没有成功,可能哪里出了问题没发现,请大家帮我看看。以下是关键的3个函数,CMD0和CMD55返回的响应是0x01,但ACMD41返回的响应还是0x01,应该是0才对,但是怎么调试都不行,大侠帮看一下吧,先在此谢过了!
BYTE SD_SendCmd(BYTE cmd, BYTE *param, BYTE resptype, BYTE *resp) { WORD i; //所有SD卡命令都是6字节长 BYTE xdata tmp,rlen,Cmd_Buf[6]; char j;
if(cmd == CMD0) Cmd_Buf[0] = 0x95; // 发送CRC校验码,只用于第1个命令(command0=40 00 00 00 00 95) else //起始位为0(bit47),传输位为1(bit46) Cmd_Buf[0] = 0xFF; for(j = 3;j >=0;j --) { Cmd_Buf[j+1] = param[j]; //param[j] } Cmd_Buf[5] = (cmd & 0x3F) | 0x40; if(cmd == CMD0) //先发送74个以上的时钟,为了使SD卡同步 { SET_Slave_select(0); // EZUSB_Delay(1); for(i=0;i<10;i++) SPI_Send_Byte(0xFF); } else { SET_Slave_select(0); SPI_Send_Byte(0xFF); } SET_Slave_select(2); //片选SPI从机 SPI_Send_Byte(Cmd_Buf[5]); SPI_Send_Byte(Cmd_Buf[4]); SPI_Send_Byte(Cmd_Buf[3]); SPI_Send_Byte(Cmd_Buf[2]); SPI_Send_Byte(Cmd_Buf[1]); SPI_Send_Byte(Cmd_Buf[0]);
i = 0; do // 等待响应,响应的最高位为0 { //Wait for a response,a response is a start bit(zero) tmp = 0xFF; tmp = SPI_Rec_Byte(); //在没收到响应令牌之前,tmp=0xFF,因此tmp & 0x80==1, i++; } while (((tmp & 0x80) != 0) && (i < SD_CMD_TIMEOUT)); //收到响应以后由于响应最高位是0,因此tmp & 0x80==0 if (i >= SD_CMD_TIMEOUT) //超时 { // SPI_CS_Deassert(); //释放总线 TD_Poll(0x15); EZUSB_Delay(2000); TD_Poll(tmp); EZUSB_Delay(2000); SET_Slave_select(0); return SD_ERR_CMD_TIMEOUT; // 返回命令超时 return response timeout of command }
rlen = 0; switch (resptype) //根据不同的命令,得到不同的响应长度 { //according various command,get the various response length case R1: case R1B: rlen = 1; break; case R2: rlen = 2; break; case R3: rlen = 5; break; default: rlen = 1; // SPI_Send_Byte(0xFF); SPI_CS_Deassert(); return SD_ERR_CMD_RESPTYPE; // 返回命令响应类型错误 return error of command response type break; } // EZUSB_Delay(1); *resp = tmp; for (j = rlen - 1; j >= 0; j--) { SPI_Send_Byte(0xFF); //resp的最高字节保存响应令牌Rx,其他字节装入0xFF // SPI_Send_Byte(0xFF); // 发送周期的最后发送8clock at the last recycle,clock out 8 clock } SET_Slave_select(0); return SD_NO_ERR; // 返回执行成功 return perform sucessfully }
//////////复位///////////// BYTE SD_ResetSD(void) ///// { BYTE xdata param[4] = {0,0,0,0},ret,resp; ret = SD_SendCmd(CMD0, param, CMD0_R, &resp); /* 复位命令 command that reset sd card */ if(ret != SD_NO_ERR) { return 1; } if(resp != 0x01) { TD_Poll(0x11); EZUSB_Delay(2000); TD_Poll(resp); EZUSB_Delay(2000); return 1; } return SD_NO_ERR; } ///////////激活///////////////// BYTE SD_Active(void) { BYTE xdata param[4] = {0,0,0,0},*resp1,*resp2,ret; BYTE xdata i;
ret = SD_SendCmd(CMD55, param, CMD55_R, resp1); // 后续命令为一个应用命令 if (ret != SD_NO_ERR) { TD_Poll(0x21); EZUSB_Delay(2000); return ret; // command that the followed commnad is a specific application } if (*resp1 & 0x01 != 1 ) //CMD55响应值是0x01 { TD_Poll(0x22); EZUSB_Delay(2000); // TD_Poll(*resp); // EZUSB_Delay(2000); return SD_ERR_CMD_RESP; // 响应错误 response is error } i = 0; do // 循环发出CMD55+ACMD41, 查询卡的状态 { ret = SD_SendCmd(ACMD41, param, ACMD41_R, resp2); if (ret != SD_NO_ERR) { TD_Poll(0x23); EZUSB_Delay(2000); return ret; } i++; }while ((i < 200)&& (*resp2 != 0));/* 如果响应R1的最低位Idle位为1,则继续循环 */
if (i >= 200) { TD_Poll(0x24); EZUSB_Delay(2000); TD_Poll(*resp2); EZUSB_Delay(2000); return SD_ERR_TIMEOUT_WAITIDLE; // 超时,返回错误 time out,return error } if (*resp2 != 0) return SD_ERR_CMD_RESP; //响应错误 response is error return SD_NO_ERR; // 读出寄存器内容 read the content of the register } |