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;
Previous article:STC15W reads RM3100 data via SPI
Next article:Use 51 single chip microcomputer to write timer (minutes, seconds separated version)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- Developer Case: Design of Smart Agriculture Based on Gizwits IoT and RT-Thread
- Basic Theory of System Timing
- GD32L233C-START evaluation development environment construction and official DEMO download test
- Several technical principles of unlocking shared bicycles with mobile phones,,,
- 【GD32E503 Review】——04.MCU CoreMark Performance Test
- [RTT & Renesas high performance CPK-RA6M4] 3. PWM to achieve breathing light evaluation
- Comparison of IIC data and logic diagram between the reference prototype and your own product
- MicroPython Newsletter Issue 6
- Why is the line so thick? How can I remove the two dots? Reducing the grid size doesn't seem to work, and I can't capture the endpoints of the component.
- Please help me write a program to monitor the status of 2 buttons. Is it really that difficult? I just can't figure it out!