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

}

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

//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

4G and above: CMD0+CMD8+CMD55+CMD41


#include "HAL.H"


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

//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);


   USB2.0

  trials=0;

   do{


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

  

  response=SdResponse();

  

  trials++;

if(trials>=200){

  return 0xfd;

}



  }while(response!=0x01);

   

  SD_CS=1;

    SdWrite(0xff);

    SD_CS=0;

trials =0;

 

do

   {

   SdRead();SdRead();SdRead();SdRead();

   SdCommand(55, 0, 0);

   response=SdResponse();

       

if(response!=0x01)

         {

            return 0xfb;

  

         }


     SdCommand(41, 0x40000000, 0);

response=SdResponse();

trials++;

if(trials>=200){

  return 0xf7;

}

      

    }while(response!=0x00);


  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;

}


main.c

Slightly modified to confirm that the data read out is indeed the data written previously.


#include

#include "HAL.H"


char buf[16];

char buf2[16]={0xAA,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0};


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

//Delay subroutine

void delay()

{

 unsigned int i;

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

}

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

//Main program

char code SST516[3] _at_ 0x003b;

main()

{

unsigned char rsp;

  CLK_DIV=0x03;


  P0M0=0xff; //    00000000   11111111 high impedance, same as below

P0M1=0xff;//   

    

P1M0=0xff;//           11111111  11111111 

P1M1=0xff;//

P2M0=0xff;// 11111111   111111111

P2M1=0xff; //General       

    

P3M0=0xff; 

P3M1=0xff; //TXD push-pull RXD normal 11111111 11111111

P4M0=0xff; 

P4M1=0xff;//11111111   11111111

P5M0=0xff; 

P5M1=0xff;// 00000000   00000010


  P1M0=0xef;//           11111111  11110001 

    P1M1=0xe1; // P11 push-pull P12 push-pull P13 push-pull P14 normal


 /*

sbit SD_CS =P1^1; //SD/MMC interface definition qinyg@163.net

sbit SD_DI =P1^2;

sbit SD_CLK =P1^3;

sbit SD_DO =P1^4;

  */


  delay(); //Power-on delay

  delay();

  delay();

  delay();

   delay(); //Power-on delay

  delay();

  delay();

  delay();

  SdInit();

   


  while(1) 

  {

    rsp=SdInit();

   //P0=rsp;

  if(rsp==1) //Initialize SD card

    {

 

     SdReadBlock(buf2,1024,16); //Read 16 bytes of data from the SD card address 1024 to BUFFER. A maximum of 512 bytes can be read at a time.

//buf2[0]+=2;

P0 = buf2[0]; //Only use the first byte and send to port P0

buf[0]++; // add 1

delay();


//rewrapBlock();


    //delay(); //delay


     SdWriteBlock(buf,1024,sizeof(buf));

     //Write back to SD card  

    }

   delay();

   

    //Delay

  }


}


The test was successful and it was concluded that all cards support 2.0. Among them, 1G cards are most likely SD SC cards, the type of 2G cards is still uncertain, and 4G and above are SD HC cards.


Unfortunately, there is another class 6 4G card that can't read or write data even though it initializes correctly (the one that succeeded is class 4). Trying different read and write speeds didn't help. I'll leave it for later.


Unlike 51 which must use IO port to simulate timing, STC15 has its own SPI mechanism. So next I plan to use the SPI function of the chip to rewrite the read and write logic, and learn to use znFTP or CH375/376 to implement file access.


[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号