找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2281|回复: 0
打印 上一主题 下一主题
收起左侧

AVR mega128单片机读写sd卡例程分享给大家

[复制链接]
跳转到指定楼层
楼主
ID:361764 发表于 2018-6-29 14:41 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
//**************************************************************************************
//------------------ MMC/SD-Card Reading and Writing implementation -------------------
//FileName     : mmcgcc.c
//Function     : Connect AVR to MMC/SD
//Created by   : Yangxiaoping
//Created date : 05/06/2006
//Version      : V1.0
//Last Modified: //2006
//Filesystem   : Read or Write MMC without any filesystem


//*****  配置端口 *************
//1 CS     ---> PORTB.0
//2 CMD/DI ---> PORTB.2
//3 GND    ---> NC(接相应的3.3V电源地)
//4 Vcc    ---> NC(接3.3V电源正)
//5 CLK    ---> PORTB.1
//6 GND    ---> NC(接相应的3.3V电源地)
//7 DO     ---> PORTB.3
//8 NC     ---- 未连接
//9 NC     ---- 未连接

//****************************************************************************
#include <avr/io.h>
//#include "mmcgcc.h"

//--------------------------------------------------------------
// 硬件 SPI 端口说明  ATmega128
//--------------------------------------------------------------
#define MMC_Write                    PORTB        //SPI port register
#define MMC_Read                    PINB    //Data PIN
#define MMC_Direction_REG        DDRB    //端口方向寄存器端口

#define MMC_Chip_Select         0             //-->MMC_CS_PIN
#define SPI_Clock                 1           //-->MMC_CLK_PIN
#define SPI_DO                         2           //-->MMC_DI_PIN
#define SPI_DI                         3           //<--MMC_DO_PIN

//------------------------------------------------------------
// Error 定义
//-------------------------------------------------------------
#define INIT_CMD0_ERROR     0x01
#define INIT_CMD1_ERROR                0x02
#define WRITE_BLOCK_ERROR        0x03
#define READ_BLOCK_ERROR           0x04

//#define MMC_Disable() MMC_Write|=(1<<MMC_Chip_Select)    //SD卡无效
//#define MMC_Enable() MMC_Write&=~(1<<MMC_Chip_Select)    //SD卡使能

#define MMC_Disable()  asm("sbi 56-0x20,0")       //SD卡无效
#define MMC_Enable()   asm("cbi 56-0x20,0")       //SD卡使能

//****************************************************************************
// 端口初始化
//****************************************************************************
void MMC_Port_Init(void)
{
        //配置端口
        MMC_Direction_REG &= ~(1<<SPI_DI);         //设 PORTB.3 输入
        MMC_Direction_REG |= (1<<SPI_Clock);       //设 PORTB.1 输出
        MMC_Direction_REG |= (1<<SPI_DO);          //设 PORTB.2 输出
        MMC_Direction_REG |= (1<<MMC_Chip_Select); //设 PORTB.0 输出
        MMC_Write |= (1<<MMC_Chip_Select);         //SD卡CS脚置高,SD卡无效.

}
//****************************************************************************
//功能描述: 从 SD 读一个字节 (硬件SPI)
//输   入: 无
//输   出: 读出的一个字节
//****************************************************************************

unsigned char Read_Byte_MMC(void)
{
        unsigned char Byte;
        SPDR = 0xff;
        while(!(SPSR & (1<<SPIF)));
        Byte = SPDR;
        return (Byte);
}

//****************************************************************************
//功能描述: 向 SD 发送一个字节 (硬件SPI)
//输   入: 发送的字节
//输   出: 无
//****************************************************************************

void Write_Byte_MMC(unsigned char Byte)
{
        SPDR = Byte;
        while(!(SPSR & (1<<SPIF)));
}
//****************************************************************************
// 功能描述: 向卡发送命令,并取得响应,返回R1
// 输   入: unsigned char *CMD      命令
// 输   出: 返回1字节的R1
//****************************************************************************
unsigned char Write_Command_MMC(unsigned char *CMD)
{
        unsigned char tmp;
        unsigned char retry=0;
        unsigned char i;
        MMC_Disable();                           //SD卡无效
        Write_Byte_MMC(0xFF);                    //送 8 Clock
        MMC_Enable();                            //SD卡使能
        for (i=0;i<0x06;i++)                     //送 6 Byte 命令去SD卡
        {
                Write_Byte_MMC(*CMD++);
        }
   //get 16 bit response
        Read_Byte_MMC();                         //第1个字节不要.
        do
        {                                        //Only last 8 bit is used here.Read it out.
                tmp = Read_Byte_MMC();               //读出8位有效回应R1
                retry++;
        }
        while((tmp==0xff)&&(retry<100));
        return(tmp);
}
//****************************************************************************
// 功能描述: 向卡发送命令,并取得响应,返回2字节的R2
// 输   入: unsigned char *CMD      命令
//           unsigned char *resp     返回缓冲区2字节
// 输   出: 0:   正确    >0:    错误码
//****************************************************************************
unsigned char Write_Command_MMCr2(unsigned char *CMD,unsigned char *resp)
{
        unsigned char tmp;
        unsigned char retry=0;
        unsigned char i;
        MMC_Disable();                           //set MMC_Chip_Select to high (MMC/SD-Card disable)
        Write_Byte_MMC(0xFF);                    //send 8 Clock Impulse
        MMC_Enable();                            //set MMC_Chip_Select to low (MMC/SD-Card active)
        for (i=0;i<6;i++)                        //send 6 Byte Command to MMC/SD-Card
        {
                Write_Byte_MMC(*CMD++);
        }
        Read_Byte_MMC();                         //read the first byte,ignore it.
        do
        {
                tmp = Read_Byte_MMC();
                retry++;
        }
        while((tmp==0xff)&&(retry<100));
        if(retry>=100)
        {
                MMC_Disable();
                return(tmp);
        }
        resp[0] = tmp;                           //读出2字节有效回应R2
        resp[1] = Read_Byte_MMC();

        return(0);
}

//****************************************************************************
//功能描述: SD卡初始化 (SPI-MODE) 硬件SPI
//输   入: 无
//输   出: 0:   正确    >0:    错误码
//****************************************************************************
unsigned char MMC_Init(void)
{
        unsigned char temp;
        unsigned int retry;
        unsigned char i;
        unsigned char CMD[] = {0x40,0x00,0x00,0x00,0x00,0x95};
        unsigned char out[2];
        
        
        MMC_Port_Init();                      //Init SPI port
        for(i=0;i<200;i++)                    //Wait MMC/SD ready...
        {
                asm("nop");
        }
        //Enable SPI in Master Mode with IDLE low and clock at 16E6/128
        //初始化SPI 为主模式,时钟速率为128分频
        SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1);
        SPSR = (0<<SPI2X);
        for (i=0;i<0x0f;i++)
        {
                Write_Byte_MMC(0xff);             //最少发送74个clock
        }

        retry=0;                              //发送命令 CMD0 to MMC/SD Card
        do
        {                                     //延时200次发送命令 CMD0 直到R1正确
                temp=Write_Command_MMC(CMD);
                retry++;
                if(retry==200)
                {                                 //超时
                        MMC_Disable();
                        return(INIT_CMD0_ERROR);      //CMD0 Error! (0x01)
                }
        }
        while(temp!=1);                       //初始化时R1第0位为1


              CMD[0] = 0x48;                        //Command CMD8
              CMD[5] = 0xFF;
              retry=0;
              do
              {                                      //延时200次发送命令 CMD8 直到R1正确
                     temp=Write_Command_MMC(CMD);
                    temp=(temp&0xF7);
                retry++;
                    if(retry==1000)                    //128M时为200
                    {                                  //超时
                          MMC_Disable();
                         return(temp);       //CMD1 Error! (0x02)
                     }
              }
            while((temp!=5)&&(temp!=1));

                if (temp == 5)                              //v1.0卡
                {
             SD_Card = 1;
              retry=0;
              do
              {
           CMD[0] = 0x40+55;                        //Command CMD55
                   CMD[5] = 0xFF;
               temp=Write_Command_MMC(CMD);
        
               CMD[0] = 0x40+41;                     
               CMD[1] = 0x40;
                   CMD[5] = 0xFF;                                 
                   temp=Write_Command_MMC(CMD);
                   retry++;
                   if(retry==1000)                    //128M时为200
                   {                                  //超时
                         MMC_Disable();
                         return(temp);       //CMD1 Error! (0x02)
                   }
               
              }
              while(temp!=0);                        //R1为0正常
         
         }
                 
            if (temp == 1)                               //v2.0卡
            {
                    SD_Card = 2;
                    
              retry=0;
              do
              {
           CMD[0] = 0x40+55;                        //Command CMD55
                   CMD[5] = 0xFF;
               temp=Write_Command_MMC(CMD);
        
               CMD[0] = 0x40+41;                     
               CMD[1] = 0x40;
                   CMD[5] = 0xFF;                                 
                   temp=Write_Command_MMC(CMD);
                   retry++;
                   if(retry==1000)                    //128M时为200
                   {                                  //超时
                         MMC_Disable();
                         return(temp);       //CMD1 Error! (0x02)
                   }
               
              }
              while(temp!=0);                        //R1为0正常
               
                   CMD[0] = 0x40+58;                        //Command CMD58
                   CMD[5] = 0xFF;
                                      
                   Write_Command_MMCr2(CMD,out);
                           if((out[1]&0x40)==0)                  //  如果返回CCS不等于1则为标准卡,若等于1则为高速卡   
                        {
                                   SD_Card = 1;
                           }

         }

                                           // 设置 SPI 为全速
        SPCR = SPCR|(0<<SPR0)|(0<<SPR1);
        SPSR = SPSR|(1<<SPI2X);                //fosc/2
//        SPSR &= ~(1<<SPI2X);                   //fosc/4

        MMC_Disable();                        //SD卡无效
        return(0);                            //All commands have been taken.
}



//****************************************************************************
//功能描述: 从SD卡中读多个字节
//输   入: unsigned char *CMD      命令
//          unsigned char *Buffer   接收缓冲区
//          unsigned int Bytes      接收的字节数
//输   出: 0:   正确    >0:    错误码
//****************************************************************************
unsigned char MMC_Read_Block(unsigned char *CMD,unsigned char *Buffer,unsigned int Bytes)
{
        unsigned char retry,temp;
        unsigned int i;
    //Send Command CMD to MMC/SD-Card
        retry=0;
        do
        {                                   //Retry 100 times to send command.
                temp=Write_Command_MMC(CMD);
                retry++;
                if(retry==100)
                {
                        MMC_Disable();
                        return(READ_BLOCK_ERROR);    //block write Error!
                }
        }
        while(temp!=0);
        //Read Start Byte form MMC/SD-Card (FEh/Start Byte)
        while (Read_Byte_MMC() != 0xfe){};   //读数据开始令牌

        for (i=0;i<Bytes;i++)
        {
                *Buffer++ = Read_Byte_MMC();
        }
        Read_Byte_MMC();                      //CRC - Byte
        Read_Byte_MMC();                      //CRC - Byte

        MMC_Disable();             //set MMC_Chip_Select to high (MMC/SD-Card invalid)
        return(0);
}

//***************************************************************************
//功能描述: 从SD卡中读CID
//输   入: unsigned char *Buffer   接收缓冲区16字节
//输   出: 0:   正确    >0:    错误码
//***************************************************************************
unsigned char Read_CID_MMC(unsigned char *Buffer)
{
   unsigned char CMD[] = {0x4A,0x00,0x00,0x00,0x00,0xFF};
   unsigned char temp;
   temp=MMC_Read_Block(CMD,Buffer,16); //read 16 bytes
   return(temp);
}

//***************************************************************************
//功能描述: 从SD卡中读CSD
//输   入: unsigned char *Buffer   接收缓冲区16字节
//输   出: 0:   正确    >0:    错误码
//***************************************************************************
unsigned char Read_CSD_MMC(unsigned char *Buffer)
{
        unsigned char CMD[] = {0x49,0x00,0x00,0x00,0x00,0xFF};
        unsigned char temp;
        temp=MMC_Read_Block(CMD,Buffer,16); //read 16 bytes
        return(temp);
}
//****************************************************************************
//功能描述: 从SD卡中读1个块
//输   入: unsigned long addr:       块地址
//          unsigned char *Buffer   : 接收缓冲区,每块512字节
//输   出: 0:   正确    >0:    错误码
//****************************************************************************
unsigned char MMC_read_sector(unsigned long addr,unsigned char *Buffer)
{
   unsigned char CMD[] = {0x51,0x00,0x00,0x00,0x00,0xFF};
   unsigned char temp;

   //Address conversation(logic block address-->byte address)
        if (SD_Card==1)
        {
                addr = addr << 9;                        //addr = addr * 512
         CMD[1] = ((addr & 0xFF000000) >>24 );
         CMD[2] = ((addr & 0x00FF0000) >>16 );
         CMD[3] = ((addr & 0x0000FF00) >>8 );
    }
        if (SD_Card==2)
        {
         CMD[1] = ((addr & 0xFF000000) >>24 );
         CMD[2] = ((addr & 0x00FF0000) >>16 );
         CMD[3] = ((addr & 0x0000FF00) >>8 );
         CMD[4] = (addr & 0x000000FF) ;
        }

   temp=MMC_Read_Block(CMD,Buffer,512);
   return(temp);
}
//********************************************************************************************************************
// 函数名称: unsigned char MMC_ReadMultiBlock()
// 功能描述: 从SD卡中读多个块
// 输   入: unsigned long addr:       块地址
//                         unsigned long blocknum :  块数量
//                         unsigned char *Buffer   : 接收缓冲区
// 输   出: 0:   正确    >0:   错误码
//*********************************************************************************************************************

unsigned char MMC_ReadMultiBlock(unsigned long addr, unsigned long blocknum, unsigned char *Buffer)
{
        unsigned char CMD[] = {0x52,0x00,0x00,0x00,0x00,0xFF};
        unsigned char temp,retry;
        unsigned int  j;
        unsigned long i;
//         asm("cli");
                if (SD_Card==1)
        {
                addr = addr << 9;                        //addr = addr * 512
         CMD[1] = ((addr & 0xFF000000) >>24 );
         CMD[2] = ((addr & 0x00FF0000) >>16 );
         CMD[3] = ((addr & 0x0000FF00) >>8 );
    }
        if (SD_Card==2)
        {
         CMD[1] = ((addr & 0xFF000000) >>24 );
         CMD[2] = ((addr & 0x00FF0000) >>16 );
         CMD[3] = ((addr & 0x0000FF00) >>8 );
         CMD[4] = (addr & 0x000000FF) ;
        }

        retry=0;
        do
        {                                               //Retry 100 times to send command.
                temp=Write_Command_MMC(CMD);
                retry++;
                if(retry==100)
                {
                        MMC_Disable();
                        return(temp);                        //send commamd Error!
                }
        }
        while(temp!=0);


        for(i=0; i<blocknum; i++)
        {
                while (Read_Byte_MMC() != 0xfe){};

                for (j=0;j<512;j++)
                {
                        *Buffer++ = Read_Byte_MMC();
                }

                Read_Byte_MMC();                             //CRC - Byte
                Read_Byte_MMC();                             //CRC - Byte


        }
        CMD[0]=0x4c;
        CMD[1]=0x00;
        CMD[2]=0x00;
        CMD[3]=0x00;
        do
        {                                                //Retry 100 times to send command.
                temp=Write_Command_MMC(CMD);
                retry++;
                if(retry==100)
                {
                        MMC_Disable();
                        return(temp);                           //send commamd Error!
                }
        }
        while(temp!=0);
        MMC_Disable();
//        asm("sei");
        return(temp);

}

//********************************************************************************************************************
// 函数名称: MMC_GetNumWRBlcoks()
// 功能描述: 得到正确写入的块数
// 输   入:  *blocknum: 返回的块数
// 输   出: 0:   正确    >0:   错误码
//*******************************************************************************************************************
unsigned char MMC_GetNumWRBlcoks(unsigned long *blocknum)
{
        unsigned char tmp,retry;
        unsigned char CMD[] = {0x77,0x00,0x00,0x00,0x00,0xFF};
        unsigned char Buffer[4];

        retry=0;
        do
        {                                         //Retry 100 times to send command.
                tmp=Write_Command_MMC(CMD);           // CMD55 ; R1 后续命令为一个应用命令
                retry++;
                if(retry==100)
                {
                        return(tmp);                      //send commamd Error!
                }
        }
        while(tmp!=0);

        CMD[0] = 0x56;                            // ACMD22 ; R1
        tmp=MMC_Read_Block(CMD,Buffer,4);
        if(tmp!=0)
        {
                return(tmp);                           //send commamd Error!
        }
        *blocknum = ((unsigned long)Buffer[0] << 24) + ((unsigned long)Buffer[1] << 16) + ((unsigned long)Buffer[2] << 8) + Buffer[3];
        return(0);
}

//****************************************************************************
//功能描述: 向SD卡中写入一个块
//输   入: unsigned long addr:    块地址
//          unsigned char *Buffer: 发送缓冲区每块512字节
//输   出: 0:   正确    >0:   错误码
//****************************************************************************
unsigned char MMC_write_sector(unsigned long addr,unsigned char *Buffer)
{
        unsigned char tmp,retry;
        unsigned int i;
        unsigned char CMD[] = {0x58,0x00,0x00,0x00,0x00,0xFF};
        unsigned char R2[2];
                if (SD_Card==1)
        {
                addr = addr << 9;                        //addr = addr * 512
         CMD[1] = ((addr & 0xFF000000) >>24 );
         CMD[2] = ((addr & 0x00FF0000) >>16 );
         CMD[3] = ((addr & 0x0000FF00) >>8 );
    }
        if (SD_Card==2)
        {
         CMD[1] = ((addr & 0xFF000000) >>24 );
         CMD[2] = ((addr & 0x00FF0000) >>16 );
         CMD[3] = ((addr & 0x0000FF00) >>8 );
         CMD[4] = (addr & 0x000000FF) ;
        }
                                                     //Send Command CMD24 to MMC/SD-Card
        retry=0;
        do
        {                                            //Retry 100 times to send command.
                tmp=Write_Command_MMC(CMD);
                retry++;
                if(retry==100)
                {
                        MMC_Disable();
                        return(tmp);                         //send commamd Error!
                }
        }
        while(tmp!=0);

        for (i=0;i<100;i++)                //Before writing,send 100 clock to MMC/SD-Card
        {
                Read_Byte_MMC();
        }
        Write_Byte_MMC(0xFE);                  //Send Start Byte to MMC/SD-Card
        for (i=0;i<512;i++)               //Now send real data Bolck (512Bytes) to MMC/SD-Card
        {
                Write_Byte_MMC(*Buffer++);              //send 512 bytes to Card
        }
        //CRC-Byte
        Write_Byte_MMC(0xFF);                       //Dummy CRC
        Write_Byte_MMC(0xFF);                       //CRC Code

        tmp=Read_Byte_MMC();                        // read response
        if((tmp & 0x1F)!=0x05)                      // data block accepted ?
        {
                MMC_Disable();
                return(WRITE_BLOCK_ERROR);              //Error!
        }

        while (Read_Byte_MMC()!=0xff){};            //Wait till MMC/SD-Card is not busy
        CMD[0]= 0x4d;                               //CMD13 ; R2
        CMD[1]= 0x00;
        CMD[2]= 0x00;
        CMD[3]= 0x00;
        do
        {
                tmp=Write_Command_MMC(CMD);
                retry++;
                if(retry==100)
                {
                      MMC_Disable();
                        return(tmp);                         //send commamd Error!
                }
        }
        while(tmp!=0);

        if((R2[0] != 0) || (R2[1] != 0))             //返回R1,R2都不为0
        {
                MMC_Disable();
                return(WRITE_BLOCK_ERROR);                 //Error!
        }

   MMC_Disable();
   return(0);
}

//****************************************************************************
//功能描述: 向SD卡中写入多个块
//输   入: unsigned long addr:        块地址
//          unsigned long blocknum:    块数
//                unsigned char *Buffer:    发送缓冲区
//输   出: 0:   正确    >0:   错误码
//****************************************************************************
unsigned char MMC_WriteMultiBlock(unsigned long addr, unsigned long blocknum, unsigned char *Buffer)
{
        unsigned char CMD[] = {0x59,0x00,0x00,0x00,0x00,0xFF};
        unsigned char tmp,retry;
        unsigned int  j;
        unsigned long i;

if (SD_Card==1)
        {
                addr = addr << 9;                        //addr = addr * 512
         CMD[1] = ((addr & 0xFF000000) >>24 );
         CMD[2] = ((addr & 0x00FF0000) >>16 );
         CMD[3] = ((addr & 0x0000FF00) >>8 );
    }
        if (SD_Card==2)
        {
         CMD[1] = ((addr & 0xFF000000) >>24 );
         CMD[2] = ((addr & 0x00FF0000) >>16 );
         CMD[3] = ((addr & 0x0000FF00) >>8 );
         CMD[4] = (addr & 0x000000FF) ;
        }
   retry=0;
   do
   {                                         //Retry 100 times to send command.
      tmp=Write_Command_MMC(CMD);
      retry++;
      if(retry==100)
      {
              MMC_Disable();
        return(tmp);                         //send commamd Error!
      }
   }
   while(tmp!=0);

   for (i=0;i<100;i++)                       //Before writing,send 100 clock to MMC/SD-Card
   {
      Read_Byte_MMC();
   }

        for(i=0; i<blocknum; i++)
        {


                Write_Byte_MMC(0xFC);                //Send Start Byte to MMC/SD-Card

                for (j=0;j<512;j++)                  //Now send real data Bolck (512Bytes)
                {
                        Write_Byte_MMC(*Buffer++);       //send 512 bytes to Card
                }
                Write_Byte_MMC(0xFF);                //CRC
                Write_Byte_MMC(0xFF);                //CRC

                tmp=Read_Byte_MMC();                 // read response
                if((tmp & 0x1F)!=0x05)               // data block accepted
                {
                        MMC_Disable();
                        return(WRITE_BLOCK_ERROR);       //Error!
                }

                while (Read_Byte_MMC()!=0xff){};     //Wait till MMC/SD-Card is not busy
        }
        Write_Byte_MMC(0xff);                    //
        Write_Byte_MMC(0xfd);                    //发送数据停止令牌
        while (Read_Byte_MMC()!=0xff){};         //Wait till MMC/SD-Card is not busy

        tmp = MMC_GetNumWRBlcoks(&i);            //读正确写入的块数
        if(tmp != 0)
        {
                MMC_Disable();
                return(tmp);                         //Error!
        }
        if(i != blocknum)
        {
                MMC_Disable();
                return(WRITE_BLOCK_ERROR);           //正确写入块数错误
        }
        MMC_Disable();
        return(0);

}




评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表