12.10更新
已经解决啦,嘿嘿
是SPI读写字节的小函数出了问题,
下面的程序是没问题的哈
还是感谢各位大神帮助~~
如题~~
SD卡用的是金士顿1G大卡,SPI方式发送CMD0可以复位成功,返回0X01,
但初始化时,无论发送CMD8、CMD1还是CMD55+ACMD41都返回0XFF,实在不知道是怎么回事,有人遇到过类似的问题吗?
纠结两天了,求高人指点~~
自己用的源码:
/********************************************************
/********************************************************
sd_f149.c
********************************************************/
********************************************************/
#include"sd_f149.h"
#include"usart.h"
uchar pbuf[512]={0};
//uchar is_init=0;
uchar Init_Flag=0;
/********************************************************
时钟 mclk 8M
********************************************************/
void clk_init() //8M时钟
{
uchar i;
BCSCTL1&=~XT2OFF; //打开XT振荡器
BCSCTL2|=SELM1+SELS; //MCLK 8M and SMCLK 8M
do
{
IFG1 &= ~OFIFG; //清除振荡错误标志
for(i = 0; i < 100; i++)
_NOP(); //延时等待
}
while ((IFG1 & OFIFG) != 0); //如果标志为1继续循环等待
IFG1&=~OFIFG;
}
/****************函数定义**********************/
void delay(unsigned int time) //延时函数
{
while(time--);
}
//--------------------------------------------------------------------------
//初始化SD卡到SPI模式
//--------------------------------------------------------------------------
unsigned char SD_Init()
{
unsigned int retry;
unsigned char temp;
unsigned char i;
unsigned char CMD[] = {0x40,0x00,0x00,0x00,0x00,0x95};
Init_Flag=1; //将初始化标志置1
SD_CS_1;
for (i=0;i<0x0f;i++)
{
Write_Byte_SD(0xff); //发送至少74个时钟信号
}
SD_CS_0; //片选开启
//向SD卡发送CMD0
retry=0;
do
{ //为了能够成功写入CMD0,在这里写200次
temp=Write_Command_SD(CMD);
retry++;
if(retry==500)
{ //超过200次
return(INIT_CMD0_ERROR);//CMD0 Error!
}
}
while(temp!=0x01); //回应01h,停止写入
usart_send_string("Reset finish!
");
//只到这里是完全可以的!!!串口助手上显示了"Reset finish! "说明复位成功~可是接下来的初始化部分就不行,串口助手只显示“” 说明temp读的值为0XFF
//发送CMD1到SD卡
CMD[0] = 0x41; //CMD1
CMD[5] = 0xFF;
retry=0;
do
{
temp=Write_Command_SD(CMD);
retry++;
if(retry==1000)
{ //超过100次
usart_send_onechar(temp+0x30);
return(INIT_CMD1_ERROR);//CMD1 Error!
}
}
while(temp!=0x00);//回应00h停止写入
usart_send_string("CMD1 finish!
");
//根本没到这一步,直接在上面就return了。串口助手只显示“” 说明temp读的值为0XFF
Init_Flag=0; //初始化完毕,初始化标志清零
SD_CS_1; //片选无效
return(0); //初始化成功
}
void Write_Byte_SD(unsigned char x)
{
uchar i;
for(i=0;i<8;i++)
{
P4OUT&=~BIT2; //下降沿
if(x&0x80)
{
P4OUT|=BIT0;
}
else
{
P4OUT&=~BIT0;
}
x=x<<1;
if(Init_Flag) //用于初始化、复位时降速
{
delay_us(2);
}
P4OUT|=BIT2;//时钟上升沿
if(Init_Flag) //用于初始化、复位时降速
{
delay_us(2);
}
}
}
unsigned char Read_Byte_SD()
{
uchar temp=0,i=0;
P4DIR|=BIT0;//MISO切换成输出
P4OUT|=BIT0;//电平置高
P4DIR&=~BIT0;//再换回输入
for(i=0;i<8;i++)
{
P4OUT&=~BIT2;//时钟下降沿
if(Init_Flag)
{
delay_us(2);
}
if(P4IN&BIT1)//1
{
temp|=(0x80>>i);//读出数据
}
P4OUT|=BIT2; //上升沿 1011
if(Init_Flag)
{
delay_us(2);
}
}
return(temp);
}
//-----------------------------------------------------------------------------------------------
//向SD卡中写入命令,并返回回应的第二个字节
//-----------------------------------------------------------------------------------------------
unsigned char Write_Command_SD(unsigned char *CMD)
{
unsigned char tmp;
unsigned char retry=0;
unsigned char i;
//禁止SD卡片选
SD_CS_1;
//发送8个时钟信号
Write_Byte_SD(0xFF);
//使能SD卡片选
SD_CS_0;
//向SD卡发送6字节命令
for (i=0;i<0x06;i++)
{
Write_Byte_SD(*CMD++);
}
//获得16位的回应
Read_Byte_SD(); //read the first byte,ignore it.
do
{ //读取后8位
tmp = Read_Byte_SD();
retry++;
}
while((tmp==0xff)&&(retry<100));
return(tmp);
}
void SD_IO_Init()
{
P4SEL=0X00;
P4DIR=0xfd;//11111101
P4OUT=0xff;
}
unsigned char SD_write_sector(unsigned long int addr,unsigned char *Buffer)
{
unsigned char temp,retry;
unsigned int i;
unsigned char CMD[] = {0x58,0x00,0x00,0x00,0x00,0xFF}; //24号写扇区命令
addr = addr << 9; //将块地址转换成字节地址
CMD[1] = ((addr & 0xFF000000) >>24 );
CMD[2] = ((addr & 0x00FF0000) >>16 );
CMD[3] = ((addr & 0x0000FF00) >>8 ); //将地址装入24号命令
retry=0;
P4OUT&=~BIT3;//打开片选
do
{
temp=Write_Command_SD(CMD); //写入24号命令
retry++;
if(retry==100)
{
return(temp); //返回sd相应值
}
}
while(temp!=0);
for (i=0;i<100;i++)
{
Read_Byte_SD();//插入若干个时钟信号
}
Write_Byte_SD(0xFE);
for (i=0;i<512;i++)
{
Write_Byte_SD(*Buffer++); //向块中写数据
}
Write_Byte_SD(0xFF);
Write_Byte_SD(0xFF); //写入两个校验码,数值不用关心
temp=Read_Byte_SD(); //读取返回值
if((temp & 0x1F)!=0x05) //读回sd相应
{
P4OUT|=BIT3;//关闭片选
return(WRITE_BLOCK_ERROR);
}
while (Read_Byte_SD()!=0xff){};//判断sd是否忙
Write_Byte_SD(0xff);//补偿8个时钟
P4OUT|=BIT3;//关闭片选
return(0);
}
unsigned char SD_Read_Sector(unsigned long sector,unsigned char *buffer)
{
unsigned char retry;
unsigned char CMD[] = {0x51,0x00,0x00,0x00,0x00,0xFF}; //17号读扇区命令
unsigned char temp;
unsigned int j;
sector = sector << 9; //地址转换
CMD[1] = ((sector & 0xFF000000) >>24 );
CMD[2] = ((sector & 0x00FF0000) >>16 );
CMD[3] = ((sector & 0x0000FF00) >>8 );//向命令中装入地址
retry=0;
do
{
temp=Write_Command_SD(CMD); //写入17号命令
retry++;
if(retry==100)
{
return(READ_BLOCK_ERROR);//读块数据失败
}
}
while(temp!=0);
while (Read_Byte_SD() != 0xfe);//等待回应,当读到0xfe时,开始接收数据
for (j=0;j<512;j++)
{
*buffer++ = Read_Byte_SD(); //将数据存在缓冲区
}
P4OUT|=BIT3;//关闭片选
Read_Byte_SD();
Read_Byte_SD(); //读取两位校验码,数值不用关心
Write_Byte_SD(0xff); //按照操作时许补偿8个时钟
return 0;
}
[
本帖最后由 blue_bm 于 2013-12-10 16:49 编辑 ]
此帖出自
小平头技术问答
一周热门 更多>