以下是代码,单片机用的是stc12C5A32AD,带spi接口的,发送CMD0之后的响应总是0xff,而不是0x01,希望各位给我看看,是哪个地方的问题。程序参考了ZLG的SD驱动程序。
#include"stc8051.h"
//#include "sdcmd.h"
#include "serial.h"
#define SD_NO_ERR 0x00 // 函数执行成功
#define SD_ERR_CMD_TIMEOUT 0x11 // 卡命令响应超时
#define SD_IDLE_WAIT_MAX 1000
#define SD_ERR_TIMEOUT_WAITIDLE 0x34 // 初始化SD卡时,等待SD卡进入空闲状态超时错误
#define SD_CMD_TIMEOUT 200
#define CMD0 0
#define CMD1 1
sbit SCLK=P1^7;
sbit MISO=P1^6;
sbit MOSI=P1^5;
sbit CS=P2^7;
void Delay(uchar N){
uint j=0;
while(N--){
for(j=0;j<1000;j++)
;
}
}
//spi传输完成中断处理函数
void SPI_Interrupt_Routine()interrupt 9{
SPSTAT=0XC0;
}
//spi接收一字节数据
uchar SPI_RecByte(){
uchar BYTE;
SPDAT=0x00;
while(!(SPSTAT&0x80));
BYTE=SPDAT;
return BYTE;
}
//spi发送一字节
uchar SPI_SendByte(uchar dat){
SPDAT=dat;
while(!(SPSTAT&0x80));
return SPDAT;
// Prints("send byte end\t\n");
}
//spi从机被选中
void SPI_CS_Assert(){
CS=0;
}
void SPI_CS_Deassert(){
CS=1;
}
//SPCTL位stc单片机SPI总线控制寄存器
//复位 时 时钟<400k
void SPI_Clk400k(){
SPCTL=0xd2;//cpu_clk/64 11.0592M/64 CPOL=0,CPHA=0,MASTER=1
}
void SPI_ClkMax(){
SPCTL=0Xd0;//cpu_clk/4
}
/********************************************************************************************************************
** 函数名称: void SD_SPIDelay() Name: void SD_SPIDelay()
** 功能描述: SPI总线延时 Function: SPI Bus delay
** 输 入: INT8U value: 延时值,不超过255 Input: INT8U value : delay value,do not beyond 255
** 输 出: 无 Output: NULL
*********************************************************************************************************************/
void SD_SPIDelay(uchar value)
{
uchar i;
for (i = 0; i < value; i++)
SPI_SendByte(0xff); /* 发送0xFF clock out 0xFF */
}
/********************************************************************************************************************
** 函数名称: uchar SD_SendCmd()
** 功能描述: 向卡发送命令,并取得响应
** 输 入: uchar cmd : 命令字
uchar *param : 命令参数,长度为5字节
uchar resptype : 响应类型
uchar *resp : 响应,长度为1-5字节
** 输 出: 0: 正确 >0: 错误码
********************************************************************************************************************/
void SD_SendCmd(uchar cmd, uchar *param){
uchar i;
Prints("enter sendcmd \n");
SPI_CS_Assert();
SPI_SendByte((cmd & 0x3F) | 0x40); /* 发送命令头和命令字 send command header and word */
// Prints("header send end\t\n");
for (i = 0; i <=4;i++){
SPI_SendByte(param[i]); /* 发送参数 send parameters */
// Delay(1);
}
Prints("send cmd end\n");
// if(Is_Reset)
// SPI_SendByte(0x95); /* 不用crc ,0x95复位用 */
// else
//
SPI_SendByte(0xff); //命令发送完之后,在发送1*8个时钟
// SPI_SendByte(0xff);
}
/********************************************************************************************************************
** 函数名称: INT8U SD_ResetSD() Name: INT8U SD_ResetSD()
** 功能描述: 复位SD/MMC卡 Function: reset SD/MMC card
** 输 入: 无 Input: NULL
** 输 出: 0: 正确 >0: 错误码 Output: 0: right >0: error code
*********************************************************************************************************************/
uchar SD_ResetSD()
{
uchar param[5] = {0,0,0,0,0x95};
uchar i=0,tmp=0x00;
Prints("enter reset\n");
// for(i=0;i<10;i++){
// SPI_SendByte(0x00);
// }
// SPI_CS_Assert();
// Prints("wait for response\t\n");
SPI_CS_Deassert();
// Delay(100);
SD_SPIDelay(15); //发送74+个时钟
SD_SendCmd(CMD0,param);
do /* 等待响应,CMD0响应为0x01 */
{
tmp = SPI_RecByte();
//tmp=SPI_SendByte(0xff);
i++;
}while ((tmp!=0x01) && (i < SD_CMD_TIMEOUT));
PrintNum(tmp);
Prints("\n");
SPI_CS_Deassert();
if (i >= SD_CMD_TIMEOUT)
{
Prints("error:reset timeout\n");
return SD_ERR_CMD_TIMEOUT; /* 返回命令超时 return response timeout of command */
}
SPI_SendByte(0xff);
return SD_NO_ERR;
}
/*******************************************************************************************************************
** 函数名称: INT8U SD_CalTimeout() Name: INT8U SD_CalTimeout()
** 功能描述: 计算读/写/擦超时时间 Function: get the information of SD card
** 输 入: INT8U *cardtype: 卡类型接收缓冲 Input: INT8U *cardtype: card type receive buff
** 输 出: 0: 正确 >0: 错误码 Output: 0: right >0: error code
** 函数说明: 该命令不断重复发送到SD卡,直到响应R1的Bit0(Idle)位为0,表示SD卡内部初始化处理完成。
当响应的Idle位为0时,SD卡就完全进入SPI模式了。当然重复发送命令CMD1是有次数限制的,
最大次数为宏定义SD_IDLE_WAIT_MAX.
*******************************************************************************************************************/
uchar SD_ActiveInit(void)
{
uchar param[5] = {0,0,0,0,0xff},resp;
unsigned int i = 0;
// SPI_CS_Assert();
do
{ /* 发出CMD1, 查询卡的状态s */
SD_SendCmd(CMD1, param);
resp= SPI_RecByte();
i++;
}
while ((resp!=0x00) && (i < SD_IDLE_WAIT_MAX));
/* CMD1的响应为0x00 */
SPI_CS_Deassert();
if (i >= SD_IDLE_WAIT_MAX){
Prints("error:cmd1 timeout\n");
return SD_ERR_TIMEOUT_WAITIDLE; /* 超时,返回错误 time out,return error */
}
SPI_SendByte(0xff);
return SD_NO_ERR;
}
/*******************************************************************************************************************
** 函数名称: INT8U SD_Initialize() Name: INT8U SD_Initialize()
** 功能描述: 初始化SD卡 Function: initialize sd card
** 输 入: 无 Input: NULL
** 输 出: 0: 正确 >0: 错误码 Output: 0: right >0: error code
********************************************************************************************************************/
uchar SD_Initialize(void)
{
// uchar recbuf[4],ret;
uchar ret=0;
/* 初始化读写SD卡的硬件条件 Initialize the hardware that access SD Card */
Prints("enter ini\n");
ret = SD_ResetSD(); /* 5. 发出CMDO命令复位SD卡 send CMD0 command to reset sd card */
if (ret != SD_NO_ERR)
return ret;
Prints("reset end\n");
ret = SD_ActiveInit(); /* 6. 激活卡进入初始化过程. active card initialize process */
if (ret != SD_NO_ERR)
return ret;
// ret = SD_ReadOCR(4, recbuf); /* 7. 读OCR寄存器,查询卡支持的电压值 read OCR register,get the supported voltage */
// if (ret != SD_NO_ERR)
// return ret;
// if ((recbuf[1] & MSK_OCR_33) != MSK_OCR_33)
// return SD_ERR_VOL_NOTSUSP; /* 不支持3.3V,返回错误码 not support 3.3V,return error code */
SPI_ClkMax(); /* 8. 设置SPI时钟到最大值 set SPI clock to maximum */
// ret = SD_SetBlockLen(SD_BLOCKSIZE); /* 9. 设置块的长度: 512Bytes Set the block length: 512Bytes */
// if (ret != SD_NO_ERR)
// return ret;
// return (SD_GetCardInfo()); /* 10. 读CSD寄存器,获取SD卡信息 read CSD register, get the information of SD card */
return 0;
}
void main()
{
uchar rec_code=0x0;
uchar buffer[128]={0xff};
uchar i=0;
// unsigned long len=128;
// P1M0=0Xff;
// P1M1=0Xff;
ComInit();
// CS=0;
// P1=0XFF;
// while(1);
// PrintNum(0xf0);
// SPCTL=0XD0; //CLK/4
// SPCTL=0XD2; //CLK/64
SPI_Clk400k();
SPSTAT=0XC0; //spi中断标志清零
IE2|=0x02; //使能spi中断
EA=1;
// SPI_SendByte(0xff);
/* PrintNum(0x0f);
PrintNum(SPI_SendByte(0x00));
PrintNum(SPI_SendByte(0xff));
while(1);
*/
rec_code=SD_Initialize();
PrintNum(rec_code);
Prints("\t\n");
// SPI_ClkMax();
/* rec_code=SD_ReadCID(16,buffer);
PrintNum(rec_code);
Prints("\t\n");
if(rec_code==0){
for(i=0;i<16;i++){
PrintNum(buffer[i]);
Prints("\t");
}
}
*/
while(1){
// PrintNum(0xf0);
;
}
} |