久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2333|回復: 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 共享資料的黑幣獎勵!

查看全部評分

回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 久久久久一区二区 | 亚洲免费视频一区二区 | 亚洲国产黄 | 欧美黄色片 | 精品一区二区三区在线观看 | 欧美a区| www.久| 久草在线青青草 | 国产免费自拍 | 亚洲精品二三区 | 亚洲成人一二三 | 日韩欧美中文在线 | 狠狠干2020 | 欧美成人a | 午夜精品久久久久久久久久久久久 | 日本福利在线 | 爱草在线| 欧美日韩国产一区二区三区 | 欧美成年网站 | 中文字幕国产视频 | www.亚洲免费 | 亚洲 一区 | 日韩成人av在线 | 色花av| 成人网av | 日本又色又爽又黄又高潮 | 久久99深爱久久99精品 | 日韩一区二区三区视频 | 黄色片网站在线观看 | 国产精品日韩一区二区 | 一区二区视频在线 | 精品欧美一区二区三区久久久 | 婷婷久久网 | 欧美日韩视频在线第一区 | 欧美精品综合在线 | 国产精品视频一 | 欧美日韩电影一区二区 | 成人小视频在线免费观看 | 久久一区 | 国产精品一区二 | 日韩有码一区 |