|
楼主 |
发表于 2010-2-18 16:30:56
|
显示全部楼层
address到底是什么?是扇区号吗?
不错,是扇区号。
那为什么要把扇区号左移1位呢?
因为传入参数是扇区号,但是读取SD卡需要的具体地址编号,由于读取SD卡具体地址编号与扇区号是512倍关系(一扇区有512字节)
所以需要将扇区号乘以512就可以获得地址编号了,那么扇区号往左边移动9位也可以实现相同效果。
你可以下面代码中可以看出来,本质是相当于往左边移动9位的,而不是1位。因为unsigned long int address是4个字节的,将address往左边移动义务之后再将其赋予给temp.cluster,由于temp是一个联合体,也就是说temp.cluster和unsigned char dt[4];共用内存的。
在GCC编译器中
联合体中,数组下标大的装数据大端,如:temp.cluster=0xaabbccdd,那么temp.dt[3]=0xaa,temp.dt[2]=0xbb
temp.dt[1]=0xcc,temp.dt[0]=0xdd
我现在假设address=00000000 00000000 10101010 01010101
那么address<<=1;则address=00000000 00000001 01010100 10101010
然后执行temp.cluster=address,那么temp.dt[3]=00000000,temp.dt[2]=00000001,temp.dt[1]=01010100,temp.dt[0]=10101010
在下面程序中将temp.dt[2],temp.dt[1],temp.dt[0],0发送出去,这就是扇区号所对应SD卡存储单元开始地址。
这样做的目的,无非想提高程序执行速度而已。
如果我这样说,你还不能明白,你还需要阅读SD卡读写协议。
void SD_Read_Sector(unsigned long int address) //从指定地址读取扇区
{
unsigned char ret;
unsigned int i;
union
{
unsigned long int cluster;
unsigned char dt[4];
}temp; //定义temp 联合体
address <<=1; //地址左移1 位
temp.cluster=address; //设置簇的地址
//------------------------------------
CLR_SPI_SS(); //选中SD 卡;
SPDR=0x51; //发送CMD17
while(!(SPSR & 0x80)); //等待发送完成
SPDR=temp.dt[2]; //发送开始读取地址,高位字节在前,低位字节在后 ,注意不是temp.dt[3]; 相当于往左边移动8位
while(!(SPSR & 0x80));
SPDR=temp.dt[1];
while(!(SPSR & 0x80));
SPDR=temp.dt[0];
while(!(SPSR & 0x80));
SPDR=0; //你想想,为什么是0
while(!(SPSR & 0x80)); |
|