STC15 microcontroller reads and writes large capacity SD card (IO port simulates SPI mode)

Publisher:SparklingBeautyLatest update time:2022-08-09 Source: csdn Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

The chip used is IAP15F2K61S2 of STC15 series, and the development board is 51's xl2000. Unplug the 51 chip on the chip holder and replace it with STC, mixed mode. (The configuration is low enough)

The source code is modified from experiment 26 of the 51 development board routine.

After browsing the online tutorials, I found that there are basically the following types of SD cards, corresponding to different initialization and reading and writing methods:


Generally speaking, when the power is turned on,

SD card does not support CMD1 but supports CMD55.

MMC cards do not support CMD55 but support CMD1.

Use CMD8 to distinguish between SD1.1 and SD2.0 cards.

Use ACMD41 to distinguish SD2.0 SDSC or SDHC.


I have six SD cards with different capacities ranging from 1 to 16GB, one each of 1G/2G/8G/16G, and two 4G cards. After testing, I have been able to successfully read and write data blocks to 5 of the SD cards, but not to a class6 4G card. In this process, the initialization process is different from the results mentioned above by the masters. For example, the cards with protocols 1.0 and 2.0 both return 0x01 under the CMD8 command, and the SD2.0 SDSC card can return normal values ​​after initialization but cannot read or write, etc. Here are the different initialization codes and test codes for 1G, 2G, 4G and above SD cards.


Only the SdInit function in HAL.c is different, and the other codes are shared.


SD card module

HAL.h


#include "config.h"


sbit SD_CS =P1^1;

sbit SD_DI =P1^2;

sbit SD_CLK =P1^3;

sbit SD_DO =P1^4;


unsigned char SdInit(void);

unsigned char SdReadBlock(unsigned char *Block, unsigned long address,int len);

unsigned char SdWriteBlock(unsigned char *Block, unsigned long address,int len);

unsigned char SdWriteBlock2(unsigned char *Block, unsigned long address,int len);


void ComSendByte(unsigned char c);


HAL.c

1G card: CMD0+CMD8+CMD1


#include "HAL.H"


char csd[16];


//============================================================

//Write one byte to the SD card, simulating the SPI bus mode

void SdWrite(unsigned char  n)

{

    

  unsigned char i;


  for(i=8;i;i--)

   {

    SD_CLK=0;

    SD_DI=(n&0x80);

    n<<=1;

    SD_CLK=1;

   }

  SD_DI=1;      

}   

//================================================================

//Read one byte from the SD card, simulating the SPI bus mode

unsigned char SdRead()

{

 unsigned char n,i;

 for(i=8;i;i--)

  {

   SD_CLK=0;

   SD_CLK=1;

   n<<=1;

   if(SD_DO) n|=1;


  }

 return n;

}

//================================================================

//Detect the response of SD card

unsigned char SdResponse()

{

  unsigned char i=0,response;

  

  while(i<=8)

  {

    response = SdRead();

    if(response==0x00)

      break;

    if(response==0x01)

      break;

    i++;

  }

  return response;

}  

//================================================================

//Send command to SD card

void SdCommand(unsigned char command, unsigned long argument, unsigned char CRC)

{

  

  SdWrite(command|0x40);

  SdWrite(((unsigned char *)&argument)[0]);

  SdWrite(((unsigned char *)&argument)[1]);

  SdWrite(((unsigned char *)&argument)[2]);

  SdWrite(((unsigned char *)&argument)[3]);

  SdWrite(CRC);

}

//================================================================

// Initialize SD card

unsigned char SdInit(void)

{

  int delay=0, trials=0;

  unsigned char i;

  unsigned char response=0x01;


  SD_CS=1;

  for (i=0;i<0x0f;i++)    

   {

    SdWrite(0xff);

}

  SD_CS=0;

  

  //Send Command 0 to put MMC in SPI mode


  do{


  SdCommand(0x00,0,0x95);


  

  response=SdResponse();

  trials++;

if(trials>=200){

  return 0xfe;

}



  }while(response!=0x01);


   

  

   

  trials=0;

   do{

  



  SdCommand(0x08,0x1AA,0x87);

  

  response=SdResponse();

  

  trials++;

if(trials>=200){

  return 0xfd;

}



  }while(response!=0x01);

   

       


trials = 0;

  

  do{

     SD_CS=1;

    SdWrite(0xff);

    SD_CS=0;

    SdCommand(0x01,0x00ffc000,0xff);

    response=SdResponse();

trials++;

if(trials>=200){

  return 0xfa;

}

  } while(response==0x01);

   


     


  SD_CS=1;

  SdWrite(0xff);

 return 1; 

}

//================================================================

//Write data to the specified address of the SD card, up to 512 bytes at a time

unsigned char SdWriteBlock(unsigned char *Block, unsigned long address,int len)

{

  unsigned int  count;

  unsigned char dataResp;

  //Block size is 512 bytes exactly

  //First Lower SS


  SD_CS=0;

  //Then send write command

  SdCommand(0x18,address,0xff);

 

  if(SdResponse()==0x00)

  {


    SdWrite(0xff);

SdWrite(0xff);

SdWrite(0xff);

    //command was a success - now send data

    //start with DATA TOKEN = 0xFE

    SdWrite(0xfe);

    //now send data

    for(count=0;count    

for(;count<512;count++) SdWrite(0);

    //data block sent - now send checksum

    SdWrite(0xff); //Two-byte CRC check, 0XFFFF means CRC is not considered

    SdWrite(0xff);

    //Now read in the DATA RESPONSE token

    dataResp=SdRead();

    //Following the DATA RESPONSE token

    //are a number of BUSY bytes

    //a zero byte indicates the MMC is busy

    while(SdRead()==0);


    dataResp=dataResp&0x0f; //mask the high byte of the DATA RESPONSE token

    SD_CS=1;

    SdWrite(0xff);

    if(dataResp==0x0b)

      {

  //P0=0x0b;

      //printf("DATA WAS NOT ACCEPTED BY CARD -- CRC ERRORn");

      return 0;

      }

    if(dataResp==0x05){

//P0=0x05;

      return 1;

   }

    //printf("Invalid data Response token.n");

//P0=0x02;

    return 0;

 }

 //P0=0x01;

  //printf("Command 0x18 (Write) was not received by the MMC.n");

  return 0;

}

//=======================================================================

//Read data from the specified address of the SD card, up to 512 bytes at a time

unsigned char SdReadBlock(unsigned char *Block, unsigned long address,int len)

{

   unsigned int count;

   int trials=0;

  //Block size is 512 bytes exactly

  //First Lower SS

  

//  printf("MMC_read_blockn");

 

  SD_CS=0;

  //Then send write command


  SdCommand(0x11,address,0xff);

  

  if(SdResponse()==0x00)

  {

    //command was a success - now send data

    //start with DATA TOKEN = 0xFE

    while(SdRead()!=0xfe);

    for(count=0;count

for(;count<512;count++)  SdRead();

 

    //data block sent - now send checksum

    SdRead();

    SdRead();

    //Now read in the DATA RESPONSE token

    SD_CS=1;

    SdRead();

    return 1;

 }

//  printf("Command 0x11 (Read) was not received by the MMC.n");

  return 0;

}


HAL.c

2G card: CMD0+CMD8+CMD55+CMD1


#include "HAL.H"


char csd[16];


//============================================================

//Write one byte to the SD card, simulating the SPI bus mode

void SdWrite(unsigned char  n)

{

    

  unsigned char i;


  for(i=8;i;i--)

   {

    SD_CLK=0;

    SD_DI=(n&0x80);

    n<<=1;

    SD_CLK=1;

   }

  SD_DI=1;      

}   

//================================================================

//Read one byte from the SD card, simulating the SPI bus mode

unsigned char SdRead()

{

 unsigned char n,i;

 for(i=8;i;i--)

  {

   SD_CLK=0;

   SD_CLK=1;

   n<<=1;

   if(SD_DO) n|=1;


  }

 return n;

}

//================================================================

//Detect the response of SD card

unsigned char SdResponse()

{

  unsigned char i=0,response;

  

  while(i<=8)

  {

    response = SdRead();

    if(response==0x00)

      break;

    if(response==0x01)

      break;

    i++;

  }

  return response;

}  

//================================================================

//Send command to SD card

void SdCommand(unsigned char command, unsigned long argument, unsigned char CRC)

{

  

  SdWrite(command|0x40);

  SdWrite(((unsigned char *)&argument)[0]);

  SdWrite(((unsigned char *)&argument)[1]);

  SdWrite(((unsigned char *)&argument)[2]);

  SdWrite(((unsigned char *)&argument)[3]);

  SdWrite(CRC);

}

//================================================================

// Initialize SD card

unsigned char SdInit(void)

{

  int delay=0, trials=0;

  unsigned char i;

  unsigned char response=0x01;


  SD_CS=1;

  for (i=0;i<0x0f;i++)    

   {

    SdWrite(0xff);

}

  SD_CS=0;

  

  //Send Command 0 to put MMC in SPI mode


  do{


  SdCommand(0x00,0,0x95);


  

  response=SdResponse();

  trials++;

if(trials>=200){

  return 0xfe;

}



  }while(response!=0x01);


   trials=0;

   do{


   SdCommand(0x08,0x1AA,0x87);

  

   response=SdResponse();

  

   trials++;

   if(trials>=200){

     return 0xfd;

      }


  }while(response!=0x01);


    SdCommand(55, 0, 0);

response=SdResponse();

       


   trials = 0;

  

  do{

     SD_CS=1;

    SdWrite(0xff);

    SD_CS=0;

    SdCommand(0x01,0x00ffc000,0xff);

    response=SdResponse();

trials++;

if(trials>=200){

  return 0xfa;

}

  } while(response==0x01);

   


     


SD_CS=1;

  SdWrite(0xff);

 return 1; 

}

//================================================================

//Write data to the specified address of the SD card, up to 512 bytes at a time

unsigned char SdWriteBlock(unsigned char *Block, unsigned long address,int len)

{

  unsigned int  count;

  unsigned char dataResp;

  //Block size is 512 bytes exactly

  //First Lower SS


  SD_CS=0;

  //Then send write command

  SdCommand(0x18,address,0xff);

 

  if(SdResponse()==0x00)

  {


    SdWrite(0xff);

SdWrite(0xff);

SdWrite(0xff);

    //command was a success - now send data

    //start with DATA TOKEN = 0xFE

    SdWrite(0xfe);

    //now send data

    for(count=0;count    

for(;count<512;count++) SdWrite(0);

    //data block sent - now send checksum

    SdWrite(0xff); //Two-byte CRC check, 0XFFFF means CRC is not considered

    SdWrite(0xff);

    //Now read in the DATA RESPONSE token

    dataResp=SdRead();

    //Following the DATA RESPONSE token

    //are a number of BUSY bytes

    //a zero byte indicates the MMC is busy

    while(SdRead()==0);


    dataResp=dataResp&0x0f; //mask the high byte of the DATA RESPONSE token

    SD_CS=1;

    SdWrite(0xff);

    if(dataResp==0x0b)

      {

  //P0=0x0b;

      //printf("DATA WAS NOT ACCEPTED BY CARD -- CRC ERRORn");

      return 0;

      }

    if(dataResp==0x05){

//P0=0x05;

      return 1;

   }

    //printf("Invalid data Response token.n");

//P0=0x02;

    return 0;

 }

 //P0=0x01;

  //printf("Command 0x18 (Write) was not received by the MMC.n");

  return 0;

[1] [2]
Reference address:STC15 microcontroller reads and writes large capacity SD card (IO port simulates SPI mode)

Previous article:STC15W reads RM3100 data via SPI
Next article:Use 51 single chip microcomputer to write timer (minutes, seconds separated version)

Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号