在网上找的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);
- }
复制代码 |