全新论坛MCU智学网上线,欢迎访问新论坛!稀缺资源、技术干货、参考设计、原厂资料尽在MCU智学网
更新自动建库工具PCB Footprint Expert 2023.13 Pro / Library Expert 破解版

求助 可不可以帮忙验证这个sd卡读写程序是不是对的!!

[复制链接]
3109 2

本文包含原理图、PCB、源代码、封装库、中英文PDF等资源

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
#include <reg51.h>
#include "huixian.h"

#define uchar unsigned char
#define ulong unsigned long
#define ushort unsigned short

sbit clk = P2^5;          //时钟线
//define master out slave in pin 数据输chu
sbit miso = P2^4;
//define master in slave out pin 数据输ru
sbit mosi = P2^6;
//define chip selection(挑选) pin
sbit cs = P2^7;

sbit led = P3^7;


void Write_Byte_SD(uchar dat)
{
        uchar i;
        for (i = 0; i < 8; i++)
        {       
                clk = 0;
                dat <<= 1;
                mosi = CY;
        //        miso = CY;
                clk = 1;
        }
        mosi = 1;
       
}


uchar Read_Byte_SD()
{
        uchar i, dat;
        for (i = 0; i < 8; i++)
        {
                clk = 0;
                dat <<= 1;                 
                dat |= miso;
        //        *dat |= mosi;
                clk = 1; //循环结束 clk == 1
        }
        return dat;       
}

unsigned char Write_Command_SD(unsigned char *CMD)
{
   unsigned char tmp;
   unsigned char retry=0;
   unsigned char i;
   //禁止SD卡片选
   cs=1;
   //发送8个时钟信号
   Write_Byte_SD(0xFF);
   //使能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<50));
   return(tmp);
}



//           初始化例程:
//--------------------------------------------------------------------------
//    初始化SD卡到SPI模式
//--------------------------------------------------------------------------
unsigned char SD_Init()
{  
   unsigned char retry,temp;
   unsigned char i;
   unsigned char CMD[] = {0x40,0x00,0x00,0x00,0x00,0x95};
        //SD_Port_Init(); //初始化驱动端口//////////////////
   
//  Init_Flag=1; //将初始化标志置1
        uart_puts("init1");
        cs = 1;
   for (i=0;i<0x0f;i++)
   {
      Write_Byte_SD(0xff); //发送至少74个时钟信号
   }

   //向SD卡发送CMD0
   retry=0;
   cs = 0;
   uart_puts("init2");
   do
   { //为了能够成功写入CMD0,在这里写200次
     temp=Write_Command_SD(CMD);
     retry++;
     if(retry==200)
     { //超过200次
                uart_puts("init cmd0 over200");
                if (temp == 0xff)
                {
                        sendone('f');
                }
     //  return(0);//CMD0 Error!
                 break;
     }
//         sendone(retry);
   }
   while(temp!=1);  //回应01h,停止写入
   uart_puts("init3");
   //发送CMD1到SD卡
   CMD[0] = 0x41; //CMD1
   CMD[5] = 0xFF;
   retry=0;                  
   do
   { //为了能成功写入CMD1,写100次
     temp=Write_Command_SD(CMD);
     retry++;
     if(retry==100)
     { //超过100次
    //   return(0);//CMD1 Error!
                uart_puts("init cmd1 over100");
                        if (temp == 0xff)
                {
                        sendone('f');
                }
                break;
     }
   }
   while(temp!=0);//回应00h停止写入
//  Init_Flag=0; //初始化完毕,初始化标志清零
   
   cs=1;  //片选无效
   return(0); //初始化成功
}

void SD_get_data(unsigned int Bytes,unsigned char *buffer)
{
   unsigned int j;
   unsigned char ch;
   for (j=0;j<Bytes;j++)
   {
      *buffer++ = Read_Byte_SD();
        }
        *buffer = '\0';
        for (j; j < 512; j++)
        {
                ch = Read_Byte_SD();
        }
        cs = 1;
}

void delay_spi(uchar a)
{
        uchar b;
        for (b=100; b; b--)
        for (a; a; a--);
}

//      扇区读的程序例程:
unsigned char SD_Read_Sector(unsigned long sector,unsigned char *buffer)
{  
   unsigned char retry;
   //命令16
   unsigned char CMD[] = {0x51,0x00,0x00,0x00,0x00,0xFF};
   unsigned char temp;
   
   //地址变换   由逻辑块地址转为字节地址
   sector = sector << 9; //sector = sector * 512
   CMD[1] = ((sector & 0xFF000000) >>24 );
   CMD[2] = ((sector & 0x00FF0000) >>16 );
   CMD[3] = ((sector & 0x0000FF00) >>8 );
   //将命令16写入SD卡
   retry=0;
        cs = 0;
   do
   {  //为了保证写入命令  一共写100次
      temp=Write_Command_SD(CMD);
      retry++;
//          sendone(temp);
      if(retry==100)
      {
                  uart_puts("read cmd16 over 100");
                if (temp == 0xff)
                {
                        sendone('f');
                }
       // return(0); //block write Error!
           break;
      }
   }
   while(temp!=0);
   cs = 1;
   retry = 0;
   //Read Start Byte form MMC/SD-Card (FEh/Start Byte)
  //Now data is ready,you can read it out.
        uart_puts("waiting....");
        cs = 0;
   while ( temp != 0xfe)
   {
                   temp = Read_Byte_SD();
                retry++;
                delay_spi(200);
                delay_spi(200);
                if (retry == 200)
                {
                        retry = 0;
                        if (temp == 0xff)
                        {
                                sendone('f');       
                        }
                        else
                        {
                                sendone('a');       
                        }
                        delay_spi(200);
                        delay_spi(200);       
                }       
   }
//   readPos=0;
       
        uart_puts("get ");
                if (temp == 0xff)
                {
                        sendone('f');
                }
  SD_get_data(7,buffer);
          //512字节被读出到buffer中
return 0;
}
//其中SD_get_data函数如下:
//----------------------------------------------------------------------------
//    获取数据到buffer中
//----------------------------------------------------------------------------




//扇区写的程序例程:
//--------------------------------------------------------------------------------------------
//   写512个字节到SD卡的某一个扇区中去   返回0说明写入成功
//--------------------------------------------------------------------------------------------
unsigned char SD_write_sector(unsigned long addr,unsigned char *Buffer)
{  
   unsigned char tmp,retry;
   unsigned int i = 0;
   //命令24
   unsigned char CMD[] = {0x58,0x00,0x00,0x00,0x00,0xFF};
   addr = addr << 9; //addr = addr * 512

   CMD[1] = ((addr & 0xFF000000) >>24 );
   CMD[2] = ((addr & 0x00FF0000) >>16 );
   CMD[3] = ((addr & 0x0000FF00) >>8 );
   //写命令24到SD卡中去
   cs = 0;
   retry=0;
   do
   {  //为了可靠写入,写100次
      tmp=Write_Command_SD(CMD);
      retry++;
      if(retry==100)
      {
       // return(tmp); //send commamd Error!
           break;
      }
        //  uart_puts(aa);
   }
   while(tmp!=0);
  
   //在写之前先产生100个时钟信号
   for (i=0;i<100;i++)
   {
      Read_Byte_SD();
   }

   //写入开始字节
   Write_Byte_SD(0xFE);
   Write_Byte_SD(0xFE);
   //现在可以写入512个字节
   while (*Buffer != '\0')
   {
                   Write_Byte_SD(*Buffer++);
                i++;               
   }
   for (i;i<512;i++)
   {
      Write_Byte_SD(0xff);
   }
   //CRC-Byte
   Write_Byte_SD(0xFF); //Dummy CRC
   Write_Byte_SD(0xFF); //CRC Code
   
   
   tmp=Read_Byte_SD();   // read response
   if((tmp & 0x1F)!=0x05) // 写入的512个字节是未被接受
   {
            cs=1;
    // return(0); //Error!
        //        break;
   }
   //等到SD卡不忙为止
//因为数据被接受后,SD卡在向储存阵列中编程数据
   while (Read_Byte_SD()!=0xff){;}

   //禁止SD卡
   cs=1;
   return(0);//写入成功
}


void delay1s(uchar d)   //误差 0us
{
    unsigned char a,b,c;
        while(d--)
        {
    for(c=167;c>0;c--)
        for(b=171;b>0;b--)
            for(a=16;a>0;a--);
        }  //if Keil,require use intrins.h
}




void main()
{
        uchar str[]="0123456";
        uchar str1[]="ABCDEFGHI";
        init_uart();

        delay1s(30);
        SD_Init();
       
       

        SD_write_sector(0x00ffff,str);
        delay_spi(300);
        uart_puts(str);
        SD_Read_Sector(0x00ffff,str1);
        uart_puts("du chu");
        uart_puts(str1);
       
        while (1)
        {
                ;               
        }

}







串口输出



#include <reg52.h>

#define uchar unsigned char
#define uint unsigned int

//void init_uart();
//void sendone(uchar ch);
//void uart_puts(uchar *str);
//void delay_uart(uchar ms);

uchar str[16], con = 0;

//void main()
//{
//        uchar  i = 0; // buf[16],
//        init_uart();       
//        while (1)
//        {
//                if (con != 0)
//                {
//                        for (i = 0; i < con; i++)
//                        {
//                                sendone(str[i]);
//                                str[i] = str[i + 1];
//                        }
//                        con--;               
//                }
//        }
//
//}

void init_uart()
{
        TMOD = 0x20;
        SCON = 0x50;
        TH1 = 0xf3;
        TL1 = 0xf3;
        EA = 1;
        ES = 1;
        TR1 = 1;
}

void ISR_UART() interrupt 4
{
        if (RI)
        {
                RI = 0;
                str[con] = SBUF; //接收   
                con++;
                str[con] = '\0';
        }
}

void sendone(uchar ch)
{
        SBUF = ch;         //发送后 TI = 1, 进入中断
        while (!TI);
        TI = 0;       
}

void uart_puts(uchar *str)
{
        while (*str)
        {
                sendone(*str);
                str++;
//                if (*str == ';')
//                {
//                        break;
//                }       
        }
}


void delay_uart(uchar ms)
{
        uchar x, y;
        for (;ms > 0; ms--)
        for (x = 100; x > 0; x--)
                for (y = 100; y > 0; y--);
}

举报

回复

2 个评论

ad***  管理员  发表于 2012-5-8 15:42:28  | 显示全部楼层
没有你原理图
L***  新手上路  发表于 2012-5-28 08:44:15  | 显示全部楼层
一个注解都没有谁想看?
*滑块验证:
您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

打开支付宝扫一扫,最高立得1212元红包
搜索

图文热点

更多

社区学堂

更多

客服中心

QQ:187196467 服务时间:周一至周日 8:30-20:30

关注我们

关于我们
关于我们
友情链接
联系我们
帮助中心
网友中心
购买须知
支付方式
服务支持
资源下载
售后服务
定制流程
关注我们
官方微博
官方空间
官方微信
快速回复 返回顶部 返回列表