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
On my terminal, I just saw this: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
I already shared volt value: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
Please check post #6Seeing 4.1V at SD card pins suggests you are not using a suitable level shifter. Please clarify about the used hardware.
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.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¨\
That's what you shared:I already shared volt value:
SCK: 0.1V
MOSI: 2.7V
CLK: 0.01 - 0.9V
MISO: 2.7V
SCK: 0.1V
MOSI: 3.9-4.1V
CLK: 0.09 - 0.1V
MISO: 3.9V - 4.1V
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.That's what I'm saying. The terminal shows ASCII codes. But what does it show when you send non ASCII code like 0x01?
Hence, you mean, I have to write a code which convert ascii to hex not hex to ascii. Right? I am bit confuse.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
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?The terminal shows ASCII codes. But what does it show when you send non ASCII code like 0x01?
Klaus
Where did i say that?Hence, you mean, I have to write a code which convert ascii to hex not hex to ascii. Right? I am bit confuse.
Okay, Understood. I found one code on internet https://www.microchip.com/forums/m1132376.aspxThen you need to tranform it. As said: SPRINTF can do this.
Klaus
SPI initialized at 250kHz using 16MHz crystal.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.
Can you explain me, why its failed to initialize?--- Updated ---
Failing CMD0 initialisation is clear so far.
At MISO (SD CARD side MISO which is connected to RC5 of controller),
#define TRIS_SDO TRISCbits.TRISC5 /**< Serial data out */
Hello,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)
#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--);
}
#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");
}
}
You wonder why it is not working... but ignoring my posts.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;
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. ThanksYou 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
unsigned char buff[32];"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
#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
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?