1. 如何判断一个卡所属的版本,像V2.0,V1.X,这个信息应该从哪里获得?一开始我对这个问题有疑问,我用的是1GB的kingston和sandisk。其实,只有SDHC才有版本问题,即内存大于2GB的SD卡才涉及这个问题,1GB的sd卡不用关心这个问题。
2. Proteus仿真只能起到辅助作用,但是不可过度迷恋。在SD卡的调试中,我试图用proteus检测单片机端口的发出的数值,很快出了问题,片选信号置高,但在示波器里片选给了高电平后却渐渐的降低,直至为零。而此处找不到任何原因。
但是也有可以借鉴的一面。我从SCK总是为高得出单片机并未发数据,因为在时钟极性中设置空闲状态时钟为高电平。另外,用SPI debuger也检测不到SDO的输出,也可以作为SPI未工作的佐证。
3.有时,在程序执行一段时间以后,我们不确定单片机的端口或寄存器是什么样的状态,而寄存器的状态有反应了程序的执行状态。端口可用电表测得电平,但是某些寄存器的某些位,我们可以用串口USART将寄存器的某些位读回,并返回串口小助手,从而做到对单片机运行的足够了解,因为单片机的所有寄存器几乎都是可读的。我在此次的实验中读了一些端口或寄存器的值,像PORTC中用到的各个位,RC4为输入,读到的值为0,还读了写冲突检测位WCOL,是0,说明没有写冲突,BF=1,说明SSPSR在发送完一个字节后,同时收到一个字节,给了SSPBUF,引起BF置位。
4.另外,我一般写SPI的数据与发送是如下格式
SSPBUF=data;
While(!SSPIF);
SSPIF=0;//与下面比,此句可省
而我在这次试验发现,写成这样亦可
SSPBUF=data;While(!BF);
因为SSPSR输出数据的同时,也在接收数据,并将接收数据给了SSPBUF,引起BF,SSPIF的置位,当读SSPBUF时,BF会清零,而不用管中断标志SSPIF也不会引起写冲突。这样就可没发一个数据就可节省一条指令。
5.在每次CS拉低使能SD卡后,都要有八个时钟信号,且单片机的输出为高,即SD卡的输入为高。
6.在给扇区写完数据后,SD卡将作出回应,回应之后,还有一段忙时间(busy),所以写完数据后要有恰当的延时。不可马上去读。
7.给芯片写数据一定要注意大小端,本次实验sd卡的逻辑块地址发送(共4个字节)写反了。应该先发地址高字节。
以下是程序摘要:
#include<pic.h>
#define uchar unsigned char
#define uint unsigned int
#define _XTAL_FREQ 12000000
#define CS RC2
uchar response=0XFF;
void init_pic_spi();
void init_pic_usart();
void init_sd_spi();
uchar receive_response();
void write_command(uchar command,unsigned long arguement,uchar CRC);
void write_sd(uchar command,unsigned long address,uchar CRC,uint len);
void read_sd(uchar command,unsigned long address,uchar CRC,uint len);
void test();
__CONFIG(0X2f42);
void main()
{
init_pic_usart();
init_pic_spi();
init_sd_spi();
write_sd(0X18,102400,0XFF,512);
read_sd(0X11,102400,0XFF,512);
while(1);
}
void init_pic_spi()
{
TRISC2=0;//CS
TRISC3=0;//SCK
TRISC4=1;//SDI
TRISC5=0;//SDO
SSPSTAT=0X80;
//SMP=1,input data sampled at the end of data output time
//CKE=1;transmit occurs on transition from idle to active clock
SSPCON=0X30;
//SSPM3-SSPM0 0000 SPI master mode ,clock=fosc/64
//CKP=1 idle state for clock high level
//SPEN=1 enable serial port
//WCOL=0 no collision
//falling edge of SCK transmit data
}
void init_pic_usart()
{
TRISC7=1;
TRISC6=1;
RCSTA=0x90;//1001 0000,SPEN=1,serial port enabled.CREN=1,
TXSTA=0X24;//0010 0100,TX9=0,select 8 bits transmission.
//TXEN=1,transmit enabled .
//SYNC=0,Asynchronous mode.
//BRGH=1,High speed.
SPBRG=77;
}
void init_sd_spi()
{
int i=0;
do
{
CS=1;//disable sd card
for(i=0;i<15;i++) //more than 74 clock pules,15*8=120,FOR YU JU CUO LE
{
SSPBUF=0XFF;
while(!BF);
}
CS=0;
SSPBUF=0XFF;
while(!BF);//8 clock
write_command(0x00,0,0x95);
}while(receive_response()!=0x01);
CS=1;
SSPBUF=0XFF;//8 clock pules
while(!BF);//untile now ,reset completed
do
{
CS=0;
__delay_us(10);
write_command(0x01,0,0xff);
}while(receive_response()!=0x00);
CS=1;
__delay_us(10);
SSPBUF=0XFF;//8 clock pules
while(!BF);//untile now ,SD card has came into SPI work mode
}
void write_command(uchar command,unsigned long arguement,uchar CRC)
{
uchar arg[4],i=0;
arg[0]=(uchar)(arguement>>24);
arg[1]=(uchar)(arguement>>16);
arg[2]=(uchar)(arguement>>8);
arg[3]=(uchar)(arguement);//four 0x00
SSPBUF=command|0x40;
while(!BF);
for(i=0;i<4;i++)
{
SSPBUF=arg[i];
while(!BF);
}
SSPBUF=CRC;
while(!BF);
}
void write_sd(uchar command,unsigned long address,uchar CRC,uint len)
{
int i=0;
do
{
CS=1;
CS=0;
SSPBUF=0XFF;//8 clock pules
while(!BF);
write_command(command,address,CRC);
}while(receive_response()!=0x00);
SSPBUF=0XFE;//head data
while(!BF);
for(i=0;i<512;i++)//data block
{
SSPBUF=i;//SSPBUF is 8 bit,the max data is 11111111 ff 256
while(!BF);
}
SSPBUF=0XFF;//CRC
while(!BF);
SSPBUF=0XFF;//CRC
while(!BF);
receive_response();
CS=1;
SSPBUF=0XFF;
while(!BF);
}
void read_sd(uchar command,unsigned long address,uchar CRC,uint len)
{
int i=0;
do
{
CS=1;
CS=0;
SSPBUF=0XFF;//8 clock pules
while(!BF);
write_command(command,address,CRC);//CMD11:the command of read data block,address must be integer multiple of 512
}while(receive_response()!=0x00);
while(receive_response()!=0xfe);
for(i=0;i<len;i++)//read and output data
{
SSPBUF=0XFF;
while(!BF);
TXREG=SSPBUF;
while(!TRMT);
}
SSPBUF=0XFF;
while(!BF);
i=SSPBUF; //abandon two CRC bytes
SSPBUF=0XFF;
while(!BF);
i=SSPBUF;
CS=1;
SSPBUF=0XFF;
while(!BF);
}
uchar receive_response()
{
uchar a=0;
while(a++<100)
{
SSPBUF=0XFF;//if we want to read a data,must send first,we send complete,receive comlete
while(!BF);//receive flag
if(0xff!=SSPBUF)
{
break;
}
if(0xff!=SSPBUF)
{
break;
}
}
return(SSPBUF);
}
void test()
{
int i=0;
for(i=0;i<5;i++)
{
TXREG=SSPBUF;
while(!TRMT);
}
}