在網上找的SD卡程序和賣家給的程序,測試了一下都不能正常工作,不知道是不是因為卡是8G的原因?
單片機源程序如下:
- #include<reg52.h>
- #include<intrins.h>
- #define uint unsigned int
- #define uchar unsigned char
- //錯誤碼定義//
- #define cmd0_error 0x01
- #define cmd1_error 0x02
- #define write_error 0x03
- #define read_error 0x04
- /*位定義*/
- sbit cs=P1^0; //定義片選位
- sbit clk=P1^1; //定義時鐘位
- sbit si=P1^2; //定義主機發送數據位
- sbit so=P1^3; //定義主機接收位
- uchar xdata shuju[512]={0}; //定義數據緩沖數組
- uchar flag_time;
- //定義標志時間,因為當sd卡進行初始化時需要降低
- //通信速度,所以通過該標志來寫1來降低速度
- void delay(uint x) //通信延時函數
- {
- while(x--)
- _nop_();
- }
- void delay1(uint a)
- {
- uint i,j;
- for(i=0;i<a;i++)
- for(j=0;j<120;j++);
- }
- //寫一字節數據//
- void write_sd(uchar date)
- {
- uchar i;
- CY=0;
- clk=1;
- for(i=0;i<8;i++)
- {
- clk=0;
- date=date<<1;
- si=CY;
- if(flag_time==1) //用來判斷是否處于初始化,如果是降低通信速度
- delay(10);
- _nop_(); //用來讓io口數據更穩定,也可以省略
- clk=1;
- _nop_();
- if(flag_time==1)
- delay(10);
- }
- }
- //讀取sd卡一個字節數據//
- uchar read_sd()
- {
- uchar i,temp=0;
- so=1; //一定要先將其置1否則會出現錯誤
- //因為如果先置0單片機io口寄存器相應位電平為低當
- //當接收到高電平后可能sd卡電平不足使其io變為高電平
- clk=1;
- for(i=0;i<8;i++)
- {
- clk=0;
- if(flag_time==1)
- delay(10);
- temp<<=1;
- temp=temp|so;
- _nop_();
- clk=1;
- _nop_();
- if(flag_time==1)
- delay(10);
- }
- return temp;
- }
- //向sd卡寫命令//
- uchar write_cmd(uchar *cmd)
- {
- uchar i,time,temp;
- si=1;
- for(i=0;i<6;i++) //發送六字節命令
- {
- write_sd(cmd[ i]);
- }
- time=0;
- do
- {
- temp=read_sd();
- time++;
- }
- while((temp==0xff)&&(time<100));
- //判斷命令是否寫入成功,當讀取到so不為0xff時命令寫入成功
- //當temp==0xff時為真且沒發送100次為真繼續執行
- //但是又不能無限制等待所以讓命令寫入100次結束
- return temp; //返回讀取的數據
- }
- //復位函數//
- uchar sd_reset()
- {
- uchar i,temp=0xff,time;
- uchar table[]={0x40,0x00,0x00,0x00,0x00,0x95};
- flag_time=1;
- cs=1;
- for(i=0;i<0x0f;i++) //復位時最少寫入74個時鐘周期
- {
- write_sd(0xff);
- }
- cs=0;
- time=0;//打開片選
- do
- {
- temp=write_cmd(table); //寫入cmd0
- time++;
- if(time==100)
- return(cmd0_error);
- }
- while(temp!=0x01); //等待命令CMD0的響應
- cs=1; //關閉片選
- write_sd(0xff); //補償8個時鐘
- return 0;
- }
- //初始化函數此函數決定SD卡的工作模式 選擇SPI還是SD模式//
- uchar sd_init()
- {
- uchar time=0,temp=0xff;
- uchar table[]={0x41,0x00,0x00,0x00,0x00,0xff}; //命令碼
- flag_time=1;
- cs=0;
- time=0;
- do
- {
- temp=write_cmd(table);
- time++;
- if(time==100)
- return 0x02;
- }
- while(temp!=0x00); //等待命令CMD1響應
- flag_time=0;
- cs=1;
- write_sd(0xff); //補償8個時鐘
- return 0;
- }
- //寫sd卡扇區//
- uchar xie_sd_shanqu(unsigned long int add,uchar *buffer)
- {
- uchar temp,time;
- uint i;
- uchar table[]={0x58,0x00,0x00,0x00,0x00,0xff};
- add=add<<9; //add=add*512
- //由于sd卡操作一次性只能寫一個扇區也就是512個字節
- //所以這里通過將長整型地址左移九位來將地址乘上512
- //用于地址操作
- table[1]=((add&0xff000000)>>24);
- table[2]=((add&0x00ff0000)>>16);
- table[3]=((add&0x0000ff00)>>8);
- cs=0;
- time=0;
- do
- {
- temp=write_cmd(table); //寫入寫扇區命令
- time++;
- if(time==100)
- {
- return(write_error);
- }
- }
- while(temp!=0x00); //判斷命令是否寫入成功成功時返回0x00
- for(i=0;i<20;i++) //補充若干時鐘
- {
- write_sd(0xff);
- }
- write_sd(0xfe); //寫入開始字節0xfe,后面要寫入512字節數據
- for(i=0;i<512;i++)
- {
- write_sd(buffer[ i]);
- }
- write_sd(0xff);
- write_sd(0xff); //兩字節奇偶校驗
- temp=read_sd(); //讀取返回值
- if((temp&0x1f)!=0x05) //如果返回值是 xxx00101 說明數據已經被寫入
- {
- cs=1;
- return(write_error);
- }
- while(read_sd()!=0xff); //等待sd卡不忙 數據寫入成功
- cs=1; //關閉片選
- write_sd(0xff); //補償8 個時鐘
- return 0;
- }
- //讀取sd卡扇區//
- uchar duqushanqu(unsigned long add,uchar *buffer)
- {
- uchar temp,time=0;
- uint i;
- uchar table[]={0x51,0x00,0x00,0x00,0x00,0xff};
- add=add<<9;
- table[1]=((add&0xff000000)>>24);
- table[2]=((add&0x00ff0000)>>16);
- table[3]=((add&0x0000ff00)>>8);
- cs=0; //打開片選
- do
- {
- temp=write_cmd(table); //寫命令
- time++;
- if(time==100)
- {
- return read_error;
- }
- }
- while(temp!=0);
- write_sd(0xff); //補償8個時鐘
- while(read_sd()!=0xfe); //一直讀取等待0xfe
- for(i=0;i<512;i++)
- {
- buffer[ i]=read_sd();
- }
- write_sd(0xff); //兩字節奇偶校驗位
- write_sd(0xff);
- cs=1;
- write_sd(0xff); //補償8個時鐘
- return 0;
- }
- /*在P0上接八個發光二極管用來顯示讀取到的數據
- 首先在數組(shuju)里面放入i用于顯示,再將其
- 寫入SD卡扇區,然后在讀取出SD卡里的數據*/
- void main()
- {
- uint i=0;
- uint a=0xaa;
- P1=0x00;
- P0=0xff;
- sd_reset();
- sd_init(); ///初始化sd卡
- for(i=0;i<512;i++)
- {
- shuju[ i]=a; //向數據數組里面寫入數據
- }
- for(i=0;i<512;i++)
- {
- xie_sd_shanqu(1,shuju); //將數據數組里面的數據寫入sd卡
- }
- for(i=0;i<512;i++)
- {
- shuju[ i]=0; //清零數據數組用來存儲從sd卡讀取到的數據
- }
- duqushanqu(1,shuju); //讀取扇區數據
- while(1)
- {
- for(i=0;i<512;i++)
- {
- P0=shuju[ i]; //顯示扇區數據
- delay1(200);
- }
- }
- }
- /*
- * SD模塊測試程序
- *
- * 用途:SD模塊測試程序
- *
- * 作者 日期 備注
- * Huafeng Lin 20010/10/03 新增
- * Huafeng Lin 20010/10/03 修改
- *
- */
- #include "REG52.H"
- ////////////////////////****************/
- unsigned char *SDInfo1="SD Init Success.";
- unsigned char *SDInfo2="SD Init Fail.";
- unsigned int xdata ReadBuffer[128] ;
- unsigned int xdata WriteBuffer[128] ;
- unsigned int BlockSize;
- unsigned long int BlockNR;
- //sbit sd_clk=P3^2;
- //sbit sd_cse=P3^0;
- //sbit sd_dai=P3^3; //Do
- //sbit sd_dao=P3^1; //DI
- sbit sd_cse=P1^0;
- sbit sd_dao=P1^2;//DI
- sbit sd_clk=P1^1;
- sbit sd_dai=P1^3;//Do
- void Delay5us()
- {
- unsigned char a=0;
- for(a=0;a<40;a++)
- ;
- }
- //********************************************
- void SD_2Byte_Write(unsigned int IOData)
- {
- unsigned char BitCounter;
-
- for (BitCounter=0;BitCounter<16;BitCounter++)
- {
- sd_clk=0;//CLK Low
-
- if(IOData&0x8000)//If the MSB of IOData is 1, then Do=1, else Do=0.
- sd_dao=1;//Do High
- else
- sd_dao=0;//Do Low
-
- sd_clk=1;//CLK High
- Delay5us();
-
- IOData=IOData<<1;//Because the MSB is transmitted firstly, shift to next lower bit.
- }
- }
- //********************************************
- void SD_Write(unsigned int IOData)
- {
- unsigned char BitCounter;
- IOData=IOData<<8;
-
- for (BitCounter=0;BitCounter<8;BitCounter++)
- {
- sd_clk=0;//CLK Low
-
- if(IOData&0x8000)//If the MSB of IOData is 1, then Do=1, else Do=0.
- sd_dao=1;//Do High
- else
- sd_dao=0;//Do Low
-
- sd_clk=1;//CLK High
- Delay5us();
-
- IOData=IOData<<1;//Because the MSB is transmitted firstly, shift to next lower bit.
- }
- }
- //********************************************
- unsigned int SD_2Byte_Read()
- {
- unsigned int Buffer;
- unsigned char BitCounter;
- Buffer=0;
-
- for (BitCounter=0;BitCounter<16;BitCounter++)
- {
- sd_clk=0;//CLK Low
- Delay5us();
- sd_clk=1;//CLK High
- Buffer=Buffer<<1;//Because the MSB is transmitted firstly, shift to next lower bit.
- //Because the LSB will be damaged, we can not put this line under next line.
- if(sd_dai)
- Buffer++;//If SPI_Din=1 then the LSB_of_Buffer=1.
- }
-
- return Buffer;
- }
- //********************************************
- unsigned int SD_Read()
- {
- unsigned int Buffer;
- unsigned char BitCounter;
- Buffer=0xffff;
-
- for (BitCounter=0;BitCounter<8;BitCounter++)
- {
- sd_clk=0;//CLK Low
- Delay5us();
- sd_clk=1;//CLK High
- Buffer=Buffer<<1;//Because the MSB is transmitted firstly, shift to next lower bit.
- //Because the LSB will be damaged, we can not put this line under next line.
- if(sd_dai)
- Buffer++;//If SPI_Din=1 then the LSB_of_Buffer=1.
- }
-
- return Buffer;
- }
- //********************************************
- unsigned int SD_CMD_Write(unsigned int CMDIndex,unsigned long CMDArg,unsigned int ResType,unsigned int CSLowRSV)//ResType:Response Type, send 1 for R1; send 2 for R1b; send 3 for R2.
- { //There are 7 steps need to do.(marked by [1]-[7])
- unsigned int temp,Response,Response2,CRC,MaximumTimes;
- Response2=0;
- MaximumTimes=10;
- CRC=0x0095;//0x0095 is only valid for CMD0
- if (CMDIndex!=0) CRC=0x00ff;
-
- sd_cse=0;//[1] CS Low
-
- SD_2Byte_Write(((CMDIndex|0x0040)<<8)+(CMDArg>>24));//[2] Transmit Command_Index & 1st Byte of Command_Argument.
- SD_2Byte_Write((CMDArg&0x00ffff00)>>8); //[2] 2nd & 3rd Byte of Command_Argument
- SD_2Byte_Write(((CMDArg&0x000000ff)<<8)+CRC); //[2] 4th Byte of Command_Argument & CRC only for CMD0
-
- sd_dao=1;//[3] Do High
- //[3] Restore Do to High Level
-
- for (temp=0;temp<8;temp++)//[4] Provide 8 extra clock after CMD
- {
- sd_clk=0;//CLK Low
- Delay5us();
- sd_clk=1;//CLK High
- Delay5us();
- }
-
- switch (ResType)//[5] wait response
- {
- case 1://R1
- {
- do
- Response=SD_Read();
- while (Response==0xffff);
- break;
- }
- case 2://R1b
- {
- do
- Response=SD_Read();
- while (Response==0xffff);//Read R1 firstly
-
- do
- Response2=SD_Read()-0xff00;
- while (Response2!=0);//Wait until the Busy_Signal_Token is non-zero
- break;
- }
- case 3: Response=SD_2Byte_Read();break;//R2
- }
-
- if (CSLowRSV==0) sd_cse=1;//[6] CS High (if the CMD has data block response CS should be kept low)
-
- for (temp=0;temp<8;temp++)//[7] Provide 8 extra clock after card response
- {
- sd_clk=0;//CLK Low
- Delay5us();
- sd_clk=1;//CLK High
- Delay5us();
- }
- return Response;
- }
- //********************************************
- unsigned int SD_Reset_Card()
- {
- unsigned int temp,MaximumTimes;
- MaximumTimes=10;
-
- for (temp=0;temp<80;temp++)//Send 74+ Clocks
- {
- sd_clk=0;//CLK Low
- Delay5us();
- sd_clk=1;//CLK High
- Delay5us();
- }
-
- return SD_CMD_Write(0x0000,0x00000000,1,0);//Send CMD0
- }
- //********************************************
- unsigned int SD_Initiate_Card()//Polling the card after reset
- {
- unsigned int temp,Response,MaximumTimes;
- MaximumTimes=50;
-
- for(temp=0;temp<MaximumTimes;temp++)
- {
- Response=SD_CMD_Write(0x0037,0x00000000,1,0);//Send CMD55
- Response=SD_CMD_Write(0x0029,0x00000000,1,0);//Send ACMD41
- if (Response==0xff00)
- temp=MaximumTimes;
- }
- return Response;
- }
- //********************************************
- unsigned int SD_Get_CardInfo()//Read CSD register
- {
- unsigned int temp,Response,MaximumTimes;
- MaximumTimes=50;
-
- for(temp=0;temp<MaximumTimes;temp++)
- {
- Response=SD_CMD_Write(9,0x00000000,1,1);//Send CMD9
- if (Response==0xff00)
- temp=MaximumTimes;
- }
-
- for (temp=0;temp<8;temp++)//Provide 8 clock to romove the first byte of data response (0x00fe)
- {
- sd_clk=0;//CLK Low
- Delay5us();
- sd_clk=1;//CLK High
- Delay5us();
- }
-
- for (temp=0;temp<8;temp++) ReadBuffer[temp]=SD_2Byte_Read();//Get the CSD data
-
- for (temp=0;temp<16;temp++)//Provide 16 clock to remove the last 2 bytes of data response (CRC)
- {
- sd_clk=0;//CLK Low
- Delay5us();
- sd_clk=1;//CLK High
- Delay5us();
- }
-
- sd_cse=1;//CS_High()
-
- for (temp=0;temp<8;temp++)//Provide 8 extra clock after data response
- {
- sd_clk=0;//CLK Low
- Delay5us();
- sd_clk=1;//CLK High
- Delay5us();
- }
-
- BlockNR=((ReadBuffer[3]<<2)&0x0fff)+((ReadBuffer[4]>>14)&0x0003)+1;//Calcuate MULT
- BlockNR=BlockNR*(0x0002<<(((ReadBuffer[4]<<1)&0x0007)+((ReadBuffer[5]>>15)&0x0001)+1));//Calcuate Block_Number
- return Response;
- }
- //********************************************
- unsigned int SD_Overall_Initiation()
- {
- unsigned int Response,Response_2;
- Response=0x0000;
- Response_2=0xff00;
-
- sd_dao=1;//[1] Do High
- //[1] Do must be High when there is no transmition
- do
- Response=SD_Reset_Card();//[2] Send CMD0
- while (Response!=0xff01);
-
- if (Response!=0xff01) Response_2+=8;
-
- //Response=SD_CMD_Write(8,0x00000000,1,0);//Send CMD8
-
- Response=SD_Initiate_Card();//[3] Send CMD55+ACMD41
- if (Response==0xff00)
- ;
- else
- {
- Response_2+=4;
- ;
- }
-
- do
- Response=SD_Get_CardInfo();//[4] Read CSD
- while (Response!=0xff00);
- if (Response==0xff01) Response_2+=2;
-
- return Response_2;
- // 0000|0000||0000|0000 Response_2
- // |||_CSD Fail
- // ||__CMD55+ACMD41 Fail
- // |___CMD0 Fail
- }
- //********************************************
- unsigned int SD_Get_CardID()//Read CID register
- {
- unsigned int temp,Response,MaximumTimes;
- MaximumTimes=10;
-
- for(temp=0;temp<MaximumTimes;temp++)
- {
- Response=SD_CMD_Write(10,0x00000000,1,1);//Send CMD9
- if (Response==0xff00)
- temp=MaximumTimes;
- }
-
- for (temp=0;temp<8;temp++)//Provide 8 clock to romove the first byte of data response (0x00fe)
- {
- sd_clk=0;//CLK Low
- Delay5us();
- sd_clk=1;//CLK High
- Delay5us();
- }
-
- for (temp=0;temp<8;temp++) ReadBuffer[temp]=SD_2Byte_Read();//Get the CID data
-
- for (temp=0;temp<16;temp++)//Provide 16 clock to remove the last 2 bytes of data response (CRC)
- {
- sd_clk=0;//CLK Low
- Delay5us();
- sd_clk=1;//CLK High
- Delay5us();
- }
-
- sd_cse=1;//CS_High()
-
- for (temp=0;temp<8;temp++)//Provide 8 extra clock after data response
- {
- sd_clk=0;//CLK Low
- Delay5us();
- sd_clk=1;//CLK High
- Delay5us();
- }
-
- return Response;
- }
- //********************************************
- unsigned int Read_Single_Block(unsigned long int BlockAddress)
- {
- unsigned int temp,Response,MaximumTimes;
- MaximumTimes=10;
-
- if (BlockAddress>BlockNR) return 0xff20;//whether BlockAddress out of range?
-
- for(temp=0;temp<MaximumTimes;temp++)
- {
- Response=SD_CMD_Write(17,BlockAddress,1,1);//Send CMD17
- if (Response==0xff00)
- temp=MaximumTimes;
- }
-
- while (SD_Read()!=0xfffe) {;}
- //這里為了使只有512byte的單片機能夠讀寫SD卡,特意節省了RAM的使用量,每次讀寫只有兩個重復的128byte
- //如果您使用的單片機擁有1K以上的RAM請將"%128"去掉
- for (temp=0;temp<256;temp++) ReadBuffer[temp%128]=SD_2Byte_Read();//Get the readed data
-
- for (temp=0;temp<16;temp++)//Provide 16 clock to remove the last 2 bytes of data response (CRC)
- {
- sd_clk=0;//CLK Low
- Delay5us();
- sd_clk=1;//CLK High
- Delay5us();
- }
-
- sd_cse=1;//CS_High()
-
- for (temp=0;temp<8;temp++)//Provide 8 extra clock after data response
- {
- sd_clk=0;//CLK Low
- Delay5us();
- sd_clk=1;//CLK High
- Delay5us();
- }
-
- return Response;
- }
- //********************************************
- unsigned int Write_Single_Block(unsigned long int BlockAddress)
- {
- unsigned int temp,Response,MaximumTimes;
- MaximumTimes=10;
-
- if (BlockAddress>BlockNR) return 0xff20;//whether BlockAddress out of range?
-
- for(temp=0;temp<MaximumTimes;temp++)
- {
- Response=SD_CMD_Write(24,BlockAddress,1,1);//Send CMD24
- if (Response==0xff00)
- temp=MaximumTimes;
- }
-
- for (temp=0;temp<8;temp++)//Provide 8 extra clock after CMD response
- {
- sd_clk=0;//CLK Low
- Delay5us();
- sd_clk=1;//CLK High
- Delay5us();
- }
-
- SD_Write(0x00fe);//Send Start Block Token
- //這里為了使只有512byte的單片機能夠讀寫SD卡,特意節省了RAM的使用量,每次讀寫只有兩個重復的128byte
- //如果您使用的單片機擁有1K以上的RAM請將"%128"去掉
- for (temp=0;temp<256;temp++) SD_2Byte_Write(WriteBuffer[temp%128]);//Data Block
- SD_2Byte_Write(0xffff);//Send 2 Bytes CRC
-
- Response=SD_Read();
- while (SD_Read()!=0xffff) {;}
-
- sd_cse=1;//CS_High()
-
- for (temp=0;temp<8;temp++)//Provide 8 extra clock after data response
- {
- sd_clk=0;//CLK Low
- Delay5us();
- sd_clk=1;//CLK High
- Delay5us();
- }
-
- return Response;
- }
- /* 串行通信初始化*/
- void UartInit()
- {
- SCON = 0x50; // uart 模式1 (8 bit), REN=1;
- TMOD = TMOD | 0x20 ; // 定時器1 模式2;
- // TH1 = 0xF7; // 9600 Bds at 32MHz
- // TL1 = 0xF7;
- TH1 = 0xFD; // 9600 Bds at 11.059MHz
- TL1 = 0xFD;
- // TH1 = 0xFA; // 9600 Bds at 22.1184MHz
- // TL1 = 0xFA;
- ES = 1; //允許uart中斷;
- EA = 1; //允許CPU中斷;
- TR1 = 1; //運行定時器1:
- }
-
- void send_char_com(unsigned char ch)
- {
- SBUF=ch;
- while(TI==0);
- TI=0;
- }
- //向串口發送一個字符串
- void send_string_com(unsigned char *str,unsigned int len)
- {
- unsigned char k=0;
- do
- {
- send_char_com(*(str + k));
- k++;
- } while(k <len);
- }
- main()
- {
- unsigned int Data,M_Response;
- unsigned char i;
- //初始化要寫入的數據
- for(i=0;i<128;i++)
- {
- if (i < 64)
- {
- WriteBuffer[ i]=0x4141;
- }
- else
- {
- WriteBuffer[ i]=0x4242;
- }
- }
- UartInit();
- TI = 0;
- M_Response=0x0000;
- M_Response=SD_Overall_Initiation();
- M_Response=SD_CMD_Write(16,512,1,0);
- Data=SD_Get_CardID();
- Write_Single_Block(0x0000);
- Read_Single_Block(0x0000);
- for(i=0; i<128; i++)
- {
- send_char_com(ReadBuffer[ i]>>8) ; //向串口發送高8位數據
- send_char_com(ReadBuffer[ i] ) ;
- }
-
- while(1);
- }
復制代碼 |