Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

SD Card Initialization failed. Help.

Status
Not open for further replies.

Rickooo

Member level 3
Member level 3
Joined
Aug 28, 2018
Messages
67
Helped
0
Reputation
0
Reaction score
0
Trophy points
6
Activity points
507
Hi, I want to use SD Card. I am using MPLAB X IDE and XC8 compiler. I am using PIC18F4520 and 16MHz crystal. I am following https://openlabpro.com/guide/raw-sd-readwrite-using-pic-18f4550/ article to initialize the SD Card.
Code:
Code:
void dummy_clock(int n){
    LATCbits.LATC2 = 1; // set CS high

    // send 80 clocks (10 bytes) to wake up SD card
    // load dummy values into buffer
    for(int i = 0; i < n; i++){
    SDdata[i] = 0xFF;
    }
    spi_send(SDdata, n);

    // set CS low
    LATCbits.LATC2 = 0;
}

//send bus clocks at instances where the buffer of the microcontroller is empty during the execution time.
void proceed(){
    LATCbits.LATC2 = 1; // set CS high
    spi_single_send(0xFF);
    LATCbits.LATC2 = 0;
}
unsigned char response()
{
    
    LATCbits.LATC2 = 0;          //CS low   
    buff = spi_single_receive();   
    return buff;
}
void SDcard_init(void){
    // send debug message
    LATCbits.LATC5 = 1;
    UART_Write_Text("Starting SD card initialization...\n");
    // dummy clock
    do{
    dummy_clock(10);
    UART_Write_Text("Sending CMD0");
    // transmit command 0
    SDcommand[0] = 0x40; // start bit | host bit | command
    SDcommand[1] = 0x00; // no arguments
    SDcommand[2] = 0x00;
    SDcommand[3] = 0x00;
    SDcommand[4] = 0x00;
    SDcommand[5] = 0x95; // pre-calculated CRC
    spi_send(SDcommand, 6);
    UART_Write_Text("Sent CMD0 Command");
    proceed();
    do{   
            buff = response();
            count++;
        }while((buff!=0X01) && (count<10) );
        count = 0;
    }while(buff!=0X01);
    
    UART_Write_Text("CMD0 success!\n");  //Now Card enter in SPI mode

When I run this code and look on terminal, I observed that I didnt receive the 0x01 reponse and hence SD is not initialize. I am usind SD module. 4GB Sd card. Volt level:
SCK: 0.1V
MOSI: 3.9-4.1V
CLK: 0.09 - 0.1V
MISO: 3.9V - 4.1V
What do you think, whats the problem? Thanks
 

Hi,

same old story, explained many times here in the forum before:

Example:
"CMD0 success!\n" are human readable ASCII characters. (except the \n which is 0x0A)
0x01 is no valid ASCII character.

So it´s very likely that the microcontroller sends 0x01, but the terminal does not show it.

Klaus
 

Hi,

same old story, explained many times here in the forum before:

Example:
"CMD0 success!\n" are human readable ASCII characters. (except the \n which is 0x0A)
0x01 is no valid ASCII character.

So it´s very likely that the microcontroller sends 0x01, but the terminal does not show it.

Klaus
On my terminal, I just saw this:
1604720998174.png


This means that, code rotate in do-while(buff!=0X01) loop continously and never comes out for a long time, and hence, it didnt move forward. Which also mean that, it didnt respond 0x01 to the controller. What do you think? What am I suppose to do now?
--- Updated ---

Getting this:
Íõ§´l¤ã ok]W㎜..ýK¨\ as a value of buff.
 
Last edited:

Hi,

The "non ASCII" is one (maybe of several) problem. Please rectify it first.
When sending variable values you need to transform them in ASCII strings. SPRINTF and other functions can do this.

Please check:
* do you have a scope?
* microcontroller supply voltage, signal voltages, SD card supply voltage.
* did you care about the 1 second after power up?
* did you care about CS polarity? Usually the SPI partner is activated with CS =0. I assume you doing it opposite to the example.

Klaus
 

Seeing 4.1V at SD card pins suggests you are not using a suitable level shifter. Please clarify about the used hardware.
 

Hi,

The "non ASCII" is one (maybe of several) problem. Please rectify it first.
When sending variable values you need to transform them in ASCII strings. SPRINTF and other functions can do this.

Please check:
* do you have a scope?
* microcontroller supply voltage, signal voltages, SD card supply voltage.
* did you care about the 1 second after power up?
* did you care about CS polarity? Usually the SPI partner is activated with CS =0. I assume you doing it opposite to the example.

Klaus
I already shared volt value:
SCK: 0.1V
MOSI: 2.7V
CLK: 0.01 - 0.9V
MISO: 2.7V

I am getting 0V at CS pin. I am unsure abut CLK pin.. I want to understand, why I need to convert hex to ascii? As terminal already displaying ascii value Íõ§´l¤ã ok]W㎜..ýK¨\
--- Updated ---

Ple
Seeing 4.1V at SD card pins suggests you are not using a suitable level shifter. Please clarify about the used hardware.
Please check post #6
I am using MMC slot, and giving 3.3V input. I am using 3.3k ohm and 2.2 k ohm resitor while connection to the controller
 

Hi,

I am getting 0V at CS pin. I am unsure abut CLK pin.. I want to understand, why I need to convert hex to ascii? As terminal already displaying ascii value Íõ§´l¤ã ok]W㎜..ýK¨\
0V at CS pin is not much informative when you measure it with a DMM. Maybe you set it HIGH for 1ms when you want to access the SD and set it LOW during a 1s wait. The result on a DMM will be close to 0V. But still it's wrong CS polarity. And can't work . And your code seem to work this way.
(you didn't answer my qestion about a scope)

That's what I'm saying. The terminal shows ASCII codes. But what does it show when you send non ASCII code like 0x01?

Klaus
 

I already shared volt value:
SCK: 0.1V
MOSI: 2.7V
CLK: 0.01 - 0.9V
MISO: 2.7V
That's what you shared:
SCK: 0.1V
MOSI: 3.9-4.1V
CLK: 0.09 - 0.1V
MISO: 3.9V - 4.1V
--- Updated ---

That's what I'm saying. The terminal shows ASCII codes. But what does it show when you send non ASCII code like 0x01?
As far as I see, the code prints only ASCII literals, no response value. The print statement has no specific functions, except for indicating that the expected response to CMD0 isn't received.

Failing CMD0 initialisation is clear so far, but we don't hear anything beyond this simple fact, e.g. does the card respond at all with non FF data?
 
Last edited:

Hi,


0V at CS pin is not much informative when you measure it with a DMM. Maybe you set it HIGH for 1ms when you want to access the SD and set it LOW during a 1s wait. The result on a DMM will be close to 0V. But still it's wrong CS polarity. And can't work . And your code seem to work this way.
(you didn't answer my qestion about a scope)

That's what I'm saying. The terminal shows ASCII codes. But what does it show when you send non ASCII code like 0x01?

Klaus
Hence, you mean, I have to write a code which convert ascii to hex not hex to ascii. Right? I am bit confuse.

In scope, at CS pin, when I start the controller, I got high signal for microsecond and than their is dc signal.
At CLK signal, there is some 10 pulse signal and later it is dc line. And it repeat after few seconds., volt is: 22.3mV
At MISO (SD CARD side MISO which is connected to RC5 of controller), I am getting some signal there, but volt is: 11.9mV - 0.3mV
At MOSI (SD card side MOSI which is connected to RC4 of controller), I am getting DC wave and volt is, 2.7V
--- Updated ---

The terminal shows ASCII codes. But what does it show when you send non ASCII code like 0x01?

Klaus
When we send non-Ascii code, like a "Text", than it display the text. But, when we try to print some response value, it shows ascii code. Now, according to the previous discussion, I have to convert ascii to hex. Right?
 
Last edited:

Hence, you mean, I have to write a code which convert ascii to hex not hex to ascii. Right? I am bit confuse.
Where did i say that?
You need to understand: an 8 bit variable can be:
A binary value of 0b01000001
A hex value of 0x41
A decimal value of 65
An octal value of 101
Or an ASCII value of "A".
All five values are "presented" differently ... while all share the same value in a byte.

So if your terminal reperesents the given values as ASCII characters... one byte = one character. But not all possible 256 values of a byte are valid ASCII characters.
0x01 is no valid ASCII value.
But if you want the terminal to show this binary value 0X01as "0X01" ... which is a string of four bytes = four valid ASCII values.
In hex they are: 0X30, 0X58, 0X30, 0X31
Then you need to tranform it. As said: SPRINTF can do this.

Your CS description is unclear. You say it is DC. But what value of DC? In either case it needs to be sometimes HIGH and sometimes LOW. So it must not be DC.
You referd to an internet document. Did you read it?

Klaus
 

Then you need to tranform it. As said: SPRINTF can do this.

Klaus
Okay, Understood. I found one code on internet https://www.microchip.com/forums/m1132376.aspx
Is it the right code to convert ascii to hex?
uint16_t data;
char buff[10];
sprintf(buff, "%x", data);

In CS pin, when I start the controller, it shows pulse for high and then it turn low (I assume it is the 80 clock pulse which is given in the code) and than their is one pulse which turn it high and low (I feel like it is "proceed()" function which is given to set the SCK) and than it is low pulse. Volt is 0V or lower in mV
 

Before the SD card is initialized the maximum data rate is between 100-400Khz, between sending commands you should have 8 dummy clocks after the response byte.
 

Before the SD card is initialized the maximum data rate is between 100-400Khz, between sending commands you should have 8 dummy clocks after the response byte.
SPI initialized at 250kHz using 16MHz crystal.
--- Updated ---

--- Updated ---


Failing CMD0 initialisation is clear so far.
Can you explain me, why its failed to initialize?
 

Hi,

You don't need ASCII to hex.

You need to form a byte (see your code) into an ASCII string.

Now you declared "data" to be a (signed) integer with 16 bits, which means two bytes.
I'm not sure if you want this.

But the code is correct for transforming a uint16 into an ASCII string.
"Data" contains your binary/hex/octal/devimal value,
"Buff" is an array of bytes, where each byte should be seen as ASCII = displayed as a human readable character

I'm still unsure about CS...

Klaus
 

hello,



could you post all your project with 18F4550
to see the hardware configuration
what pins are dedicated to SPI ?

on threads/sd-card-initialization-failed-help.395564/
Post #9
At MISO (SD CARD side MISO which is connected to RC5 of controller),


threads/fat32-library-using-xc8-compiler.395404/
post #2
in your file cartao.X.rar
use of a 18F4620 .. no USB
Code:
#define TRIS_SDO TRISCbits.TRISC5 /**< Serial data out */


but with 18F4550 with USB ...
RC4 & RC5 are input only with USB disabled ( USBEN=0 by default on POR)
 

hello,



could you post all your project with 18F4550
to see the hardware configuration
what pins are dedicated to SPI ?

on threads/sd-card-initialization-failed-help.395564/
Post #9



threads/fat32-library-using-xc8-compiler.395404/
post #2
in your file cartao.X.rar
use of a 18F4620 .. no USB
Code:
#define TRIS_SDO TRISCbits.TRISC5 /**< Serial data out */


but with 18F4550 with USB ...
RC4 & RC5 are input only with USB disabled ( USBEN=0 by default on POR)
Hello,
Thanks for the response. I am using PIC18F4520.
Here is the SPI Code:
Code:
#include <xc.h>
#include "spi.h"
#include "uart.h"

#define SCK RC3 //Serial Clock
#define SDI RC4 //Serial Data In
#define SD0 RC5 //Serial Data Out
#define CS RC2 //Slave Select: Not used in this application
#define SCK_dir TRISC3
#define SDI_dir TRISC4
#define SDO_dir TRISC5
#define CS_dir TRISC2
#define TRIS_SDO TRISCbits.TRISC5 /**< Serial data out */
#define TRIS_SDI TRISCbits.TRISC4 /**< Serial data in  */
#define TRIS_SCK TRISCbits.TRISC3 /**< Serial clock    */

void spi_init()
{
    SSPCON1bits.SSPEN = 1; // Enables serial port and configures SCK, SDO, SDI and SS as serial port pins
    // SPI mode 0
    SSPCON1bits.CKP = 0; // Idle state for clock is a low level
    SSPSTATbits.CKE = 0; // Transmit occurs on transition from active to Idle clock state
    SSPSTATbits.SMP = 1; // Input data sampled at end of data output time (took me 5 friggin' hours)
    // SPI Master mode, clock = FOSC/64
    SSPCON1bits.SSPM0 = 0;
    SSPCON1bits.SSPM1 = 1;
    SSPCON1bits.SSPM2 = 0;
    SSPCON1bits.SSPM3 = 0;   
    CS_dir = 1; //Diselect chip initially
    SCK_dir = 0;
    SDI_dir = 1;
    SDO_dir = 0;
    CS_dir = 0;
    //SS_dir = 0; //Disable: Because operating in master mode
}

void spi_send(unsigned char* data, unsigned int length){
    unsigned char tmp;
    while(length != 0){
    SSPBUF = *data;
    while( !PIR1bits.SSPIF ); // wait for buffer full
        PIR1bits.SSPIF = 0; // clear SSP1IF
        tmp = SSPBUF; // read out data
        length--;
    data++;
    }
}

void spi_receive(unsigned char* data, unsigned int length){
    while(length != 0){
    SSPBUF = 0xFF;
    while( !PIR1bits.SSPIF ); // wait for transmission complete
        while( !SSPSTATbits.BF ); // wait for buffer full
        PIR1bits.SSPIF = 0; // clear SSP1IF
        *data = SSPBUF;
    length--;
    data++;
    }
}

void spi_single_send(unsigned char data){
    unsigned char tmp;
    SSPBUF = data;
    while( !PIR1bits.SSPIF ); // wait for buffer full
    PIR1bits.SSPIF = 0; // clear SSP1IF
    tmp = SSPBUF;
}

unsigned char spi_single_receive(void){
    unsigned char TempVar;
    TempVar = SSPBUF;        // Clear BF
    //SSPBUF = 0xFF;
    PIR1bits.SSPIF = 0;      // Clear interrupt flag
    SSPBUF = 0x00;           // initiate bus cycle
    while( !PIR1bits.SSPIF ); // wait for transmission complete
    while( !SSPSTATbits.BF ); // wait for buffer full
    return SSPBUF;
}

void delay(unsigned int nMilliseconds)
{
#define CYCLES_PER_MS 100 /* Number of decrement-and-test cycles. */
unsigned long nCycles = nMilliseconds * CYCLES_PER_MS;
while (nCycles--);
}
Here is SDCard code:
Code:
#include <xc.h>
#include <stdio.h>
#include "sdcard.h"
#include "spi.h"
#include "uart.h"

unsigned char SDdata[512];
unsigned char buff;
unsigned char y;
unsigned int init, data,  i=0, count = 0;
unsigned char SDcommand[6];
unsigned char no_response = 0;
unsigned char card_response = 0;
unsigned int timeout = SD_TIMEOUT;


//dummy_clock
void dummy_clock(int n){
    LATCbits.LATC2 = 1; // set CS high

    // send 80 clocks (10 bytes) to wake up SD card
    // load dummy values into buffer
    for(int i = 0; i < n; i++){
    SDdata[i] = 0xFF;
    }
    spi_send(SDdata, n);

    // set CS low
    LATCbits.LATC2 = 0;
}

//send bus clocks at instances where the buffer of the microcontroller is empty during the execution time.
void proceed(){
    LATCbits.LATC2 = 1; // set CS high
    spi_single_send(0xFF);
    LATCbits.LATC2 = 0;
}
unsigned char response()
{
    
    LATCbits.LATC2 = 0;          //CS low   
    buff = spi_single_receive();   
    return buff;
}
void SDcard_init(void){
    
    //LATCbits.LATC5 = 1;
    UART_Write_Text("Starting SD card initialization...\n");
    // dummy clock
    do{
    dummy_clock(10);
    //UART_Write_Text("Sending CMD0");
    // transmit command 0
    SDcommand[0] = 0x40; // start bit | host bit | command
    SDcommand[1] = 0x00; // no arguments
    SDcommand[2] = 0x00;
    SDcommand[3] = 0x00;
    SDcommand[4] = 0x00;
    SDcommand[5] = 0x95; // pre-calculated CRC
    spi_send(SDcommand, 6);
    //UART_Write_Text("Sent CMD0 Command");
    proceed();
    do{   
            buff = response();
            UART_Write_Text("Buff!\n");
            UART_Write_Text(buff);
            count++;
        }while((buff!=0X01) && (count<10) );
        count = 0;
    }while(buff!=0X01);
    
    //UART_Write_Text("CMD0 success!\n");  //Now Card enter in SPI mode
    
    UART_Write_Text("Sending CMD1, awaiting response...");
    LATCbits.LATC2 = 1;
    spi_single_receive();
    LATCbits.LATC2 = 0;
    // load command 1
    SDcommand[0] = 0x41; // start bit | host bit | command
    SDcommand[1] = 0x00; // no arguments
    SDcommand[2] = 0x00;
    SDcommand[3] = 0x00;
    SDcommand[4] = 0x00;
    SDcommand[5] = 0x95; // CRC not needed, dummy byte
    spi_send(SDcommand, 6);
    for (unsigned int i = 0; i<=7; ++i){
        SDdata[i] = 0xFF;
        data = SDdata[i];
    if (SDdata[i] == 0x01){i = 8;}
    }
    
    if (data != 1){data = 1; goto fin;}
    
    UART_Write_Text("success!\n");
    // set SD card CS high
    
    LATCbits.LATC2 = 1;
    for(unsigned char i = 0; i < 1; i++){
    SDdata[i] = 0x00;
    }
    spi_receive(0x00, 1);
    LATCbits.LATC2 = 0;
    
    UART_Write_Text("Sending CMD8, awaiting response...");
    // load command 1
    SDcommand[0] = 0x48; // start bit | host bit | command
    SDcommand[1] = 0x00; // no arguments
    SDcommand[2] = 0x00;
    SDcommand[3] = 0x01;
    SDcommand[4] = 0xAA;
    SDcommand[5] = 0x87; // CRC calculated
    spi_send(SDcommand, 6);
    for (unsigned int i = 0; i<=7; ++i){
        SDdata[i] = 0xFF;
        data = SDdata[i];
    if (SDdata[i] == 0x01){i = 8;}
    }
    if (data != 1){data = 1; goto fin;}
  
    UART_Write_Text("success!\n");
    UART_Write_Text("CMD 55 Init..\n");
    for (unsigned int f = 0; f<=7 ;++f)
    {
        SDdata[f] = 0xFF;
    }   
    spi_send(SDdata, 8);
    for(unsigned int f = 0 ; f<= 128;++f){
    SDcommand[0] = 0x77; // start bit | host bit | command
    SDcommand[1] = 0x00; // no arguments
    SDcommand[2] = 0x00;
    SDcommand[3] = 0x00;
    SDcommand[4] = 0x00;
    SDcommand[5] = 0xFF; // CRC calculated
    spi_send(SDcommand, 6);
    for (unsigned int i = 0; i<=7; ++i){
        SDdata[i] = 0xFF;
    if (SDdata[i] == 0x01){i = 8;}
    }
    
    spi_send(SDdata, 8);
    SDcommand[0] = 0x69; // start bit | host bit | command
    SDcommand[1] = 0x40; // no arguments
    SDcommand[2] = 0x00;
    SDcommand[3] = 0x00;
    SDcommand[4] = 0x00;
    SDcommand[5] = 0xFF; // CRC calculated
    spi_send(SDcommand, 6);
    for(unsigned int g = 0; g<=128; ++g){
        SDdata[g] = 0xFF;
        if(SDdata == 0x00){g = 129; f= 129;}
    }
    }
    fin: ;
    LATCbits.LATC2 = 1;
    if(data = 0)
    {
        init = 0; //Successful Start
        UART_Write_Text("SD card initialized successfully!\n");
    }
    else {
        init = 1;
        UART_Write_Text("Error!\n");
    }
    
}
Still I cant resolve the problem of initializing card.
 

Code:
 // set SD card CS high
    
    LATCbits.LATC2 = 1;
    for(unsigned char i = 0; i < 1; i++){
    SDdata[i] = 0x00;
    }
    spi_receive(0x00, 1);
    LATCbits.LATC2 = 0;
You wonder why it is not working... but ignoring my posts.
If I'm not mistaken: CS = HIGH during above communication.

Can you tell me why? Maybe refer to documents that tell you to do so.
Maybe I'm wrong with my idea to set CS= LOW

Klaus
 

Is it the right way to test spi_receive and write?
spi_single_send(0x01); buff = spi_single_receive(); UART_Write_Text("Go");UART_Write_Char(buff);
UART_Write_Text("Starting SD card initialization...\n");

Where buff is unsigned char and spi_single_send and spi_single_receive is same code as added before.
--- Updated ---

You wonder why it is not working... but ignoring my posts.
If I'm not mistaken: CS = HIGH during above communication.

Can you tell me why? Maybe refer to documents that tell you to do so.
Maybe I'm wrong with my idea to set CS= LOW

Klaus
CS is initially high, and than set to low. I have browsed it on net. Please find the code here: https://openlabpro.com/guide/raw-sd-readwrite-using-pic-18f4550/ Guide me if I am wrong. Thanks
--- Updated ---

"Data" contains your binary/hex/octal/devimal value,
"Buff" is an array of bytes, where each byte should be seen as ASCII = displayed as a human readable character
Klaus
unsigned char buff[32];
char ascii[10];
sprintf(ascii, "%x", buff);
sprintf(ascii, "%x", buff);
UART_Write_Text("ASCii");
UART_Write_Char(ascii);

I tried this, nothing happened. I like to know, if this conversion right or wrong? Ascii[10] is right? why it is 10? Thanks
 
Last edited:

Hi,

I´ve tried but failed to explain.
Sadly I´m not patient enough to go on.

I really hope that others can explain more clearly and have more patience.

Klaus
 

hello,


Bit config is misplaced in SPI init
Normaly , hardware init must be done first ...

Code:
#define CS    LATCbits.LATC2    // chip Select



void spi_init()
{
    SDI_dir = 1;
    SDO_dir = 0;
    CS_dir = 0;
    CS=0;         // if  /CS  mean Chip select with Low level  (0) else you have  CS  (without bar on the top)
    SSPCON1bits.SSPEN = 1; // Enables serial port and configures SCK, SDO, SDI and SS as serial port pins
    // SPI mode 0
    SSPCON1bits.CKP = 0; // Idle state for clock is a low level
    SSPSTATbits.CKE = 0; // Transmit occurs on transition from active to Idle clock state
    SSPSTATbits.SMP = 1; // Input data sampled at end of data output time (took me 5 friggin' hours)
    // SPI Master mode, clock = FOSC/64
    SSPCON1bits.SSPM0 = 0;
    SSPCON1bits.SSPM1 = 1;
    SSPCON1bits.SSPM2 = 0;
    SSPCON1bits.SSPM3 = 0;
CS=1;  // deselect

i did some test with FAT32 from MikroC (Successfully) ( also with MPLB IDE and C18 compiler any years ago with Petite Fat)
and i use a board wich support the SDCARD , resistors and 3,3V regulator

With my hardware
CS chip select must be put Low to select the device
if CS==1 => No card selection
 

Attachments

  • Sdcard_Pinout_PIC18.jpg
    Sdcard_Pinout_PIC18.jpg
    49 KB · Views: 107

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top