In other words you dont understand how the protocol basically works...I need a example for writing a number in SD memory and reading it and please answer my above questions.
...
I didn't get that should I send these CMDs commands to the memory through SPI.
thx FvMYou'll find a huge amount of ready to use examples and libraries for SD/MMC handling on the internet, dedicated to various processors and compiler tools.
In other words you dont understand how the protocol basically works...
I see two options:
- start with a known working SD code
- study the protocol specification thoroughly and start to implement the code from the scratch. I can assure you, that the posted specification contains all necessary information.
The default command structure/protocol for SPI mode is that CRC checking is disabled. Since the card powers up in SD Bus mode, CMD0 must be followed by a valid CRC byte (even though the command is sent using the SPI structure). Once in SPI mode, CRCs are disabled by default.
CMD0 is a static command and always generates the same 7-bit CRC of 4Ah. Adding the “1,” end bit (bit 0) to the CRC creates a CRC byte of 95h. The following hexadecimal sequence can be used to send CMD0 in all situations for SPI mode, since the CRC byte (although required) is ignored once in SPI mode. The entire CMD0 sequence appears as 40 00 00 00 00 95 (hexadecimal).
CRC field in command uses a CRC7, the algorithm is documented in the specification. Please notice the comment on SPI mode.
Unless you want to use the SD card as raw storage medium, you need to decode the boot sector and file system information and read and write data in files.
A minimal test program must at least perform the above said CMD0 before other operations. As far as I know, a CMD8 is used next in newer SD card drivers to detect SDHC cards. CMD8 uses a (precomputed) CRC as well.
I don't have a simple example for this. I can only repeat my suggestion to refer to an existing SD card driver for your processor/compiler.
I am using PIC16F877 and my compiler is MikroC for PIC and according your guidance I should fill all of the 512 bytes with "110" till have a successful operation ? meanwhile recently I found new problem, and it is related to CRC , the 7 last bites of command , you know, there is a formula in the datasheet for calculating the CRC :Let me refer to your previous post before. It clarifies, that you have little knowledge of SD card operation yet. Access to the memory array is in fact in blocks or "sectors" of 512 bytes, you need to write a full block for a successful operation.
Regarding the AVR book, it's one of many available resources. You still didn't mention your processor and involved compiler tool, so nobody feels invited to suggest a specific source of information.
I wrote this codes according a read program and expected to see on the LCD the written numbers on the SD but I just have 64 !!!! do you have any idea ?maybe this link can help you.
// */ in This program PIC18f452 has comunicated with memory IC 25LC640
// */ and MCU save a 32 numbers (a page) in the 25LC640 through SPI
// */
char* text = "mikroElektronika";
unsigned x=0;
unsigned short take, buffer;
char txt[6];
char write_buf[512];
char read_buf[512];
unsigned int i;
unsigned long sector;
//////////////////////////////////////////6
char mmccommand(char cmd,unsigned long argument){
char r1;
char retry=0;
//send command
spi_write(cmd | 64);
spi_write(argument>>24);
spi_write(argument>>16);
spi_write(argument>>8);
spi_write(argument);
spi_write(149); //crc valid only for mmc_go_idle_state
//wait for response
//if more than 8 retries, card has timeout
//return the received 0xff
while(r1==255)
if(retry++>8) break;
return r1;
}
/////////////////////////////////////////////5
char mmcwrite(unsigned long sector, char* buffer ){
char r1;
unsigned i;
portd.f1=0;
//issue command
r1=mmccommand(24,sector<<9);
if(r1 != 0)
return r1;
spi_write(255); // send dummy
spi_write(254); //send data start token
for (i=0; i<512; i++) spi_write(*buffer++);
spi_write(255); // write 16-bit crc (dummy values)
spi_write(255);
r1 = Spi_Read(buffer); // read data response token
if((r1&35) != 5)
return r1;
while(!r1)
portd.f1=1; //CS
return 0; // return succes
}
/////////////////////////////////////////4
char mmcread(unsigned long sector, char* buffer ){
char r1;
unsigned i;
portd.f1=0;
r1= mmccommand(17,sector<<9);
if (r1!=0) return r1;
while(spi_read(buffer)!= 254)
for (i=0;i<512;i++) *buffer++ = spi_read(buffer);
spi_read(buffer); // read 16-bit CRC
spi_read(buffer);
portd.f1=1;
return 0;
}
/////////////////////////////////////////3
char mmcsendcommand(char cmd, unsigned long argument){
char r1;
portd.f1=0; //assert chip select
r1=mmccommand(cmd,argument); //issue the command
portd.f1=1;
return r1;
}
///////////////////////////////////////////// 2
char mmcreset(){
char i;
char retry;
char r1;
retry=0;
do{
for(i=0;i<10;i++) spi_write(255); // send dummy byte with CS high before accessing
r1= mmcsendcommand(0,0); //resetting card go to spi mode
retry++;
if(retry>10) return-1;
}while(r1 != 0x01);
retry=0;
do
{
r1= mmcsendcommand(1,0); // initializing card for operation
retry++;
if(retry>100)return-1;
}while(r1);
r1= mmcsendcommand(59,0); //turn off CRC checking to simplify communication
r1=mmcsendcommand(16,512);
return 0;
}
/////////////////////////////////////////////0
void main() {
trisd.f1=0;
portd.f1=1;
TRISB = 0; // PORTB is output
Lcd_Init(&PORTB); // Initialize LCD connected to PORTB
Lcd_Cmd(Lcd_CLEAR); // Clear display
Lcd_Cmd(Lcd_CURSOR_OFF); // Turn cursor off
Lcd_Out(1, 1, text); // Print text to LCD, 2nd row, 1st column
Spi_Init_Advanced(MASTER_OSC_DIV4,DATA_SAMPLE_End,CLK_IDLE_HIGH , HIGH_2_LOW) ;
mmcreset();
for (i=0;i<512;i++) write_buf[i]=i;
sector=5;
mmcwrite(sector,write_buf); // write to sector 5
delay_ms(1);
mmcread(sector,read_buf); // read of sector 5
while(1)
{
x=0;
while(x<512){
WordToStr(read_buf[x], txt);
Lcd_Out(2, 1, txt);
delay_ms(200);
Lcd_Cmd(Lcd_CLEAR);
Lcd_Out(1, 1, text);
portd.f1=1;
}
}
}//~!
According to the code, it's a timeout. One of the reset steps doesn't work as intended. This may be a hardware or software problem. Did you notice the requirement to start the initial SD card actions with a lower SPI frequency.I don't know what does mean "return -1
thanks your point for SPI was right and I changed it but still nothing meanwhile could you please have a quick look in the codes maybe find the errors. by the way , in the "mmcread ()" function what does mean ''*" in this line "char mmcread(unsigned long sector, char *buffer )" could you please explain clearly, and why it's using sector<<9 in this line r1= mmccommand(17,sector<<9); and one thing more what is the beneficial of this two line "spi_write(255); " in the "mmcwrite" function ? I mean why i should write 16-bit CRC (dummy values) ?According to the code, it's a timeout. One of the reset steps doesn't work as intended. This may be a hardware or software problem. Did you notice the requirement to start the initial SD card actions with a lower SPI frequency.
Are you using mikro C? I see that mikro C has a ready-to-use SD/MMC library.
Your SPI parameters, particularly SPI_IDLE_HIGH are incorrect for SD card interface.
char* text = "mikroElektronika";
unsigned x=0;
unsigned short take, buffer;
char txt[6];
char write_buf[512];
char read_buf[512];
unsigned int i;
unsigned long sector;
//////////////////////////////////////////6
char mmccommand(char cmd,unsigned long argument){
char r1;
char retry=0;
//send command
spi_write(cmd | 64);
spi_write(argument>>24);
spi_write(argument>>16);
spi_write(argument>>8);
spi_write(argument);
spi_write(149); //crc valid only for mmc_go_idle_state
//wait for response
//if more than 8 retries, card has timeout
//return the received 0xff
//while(r1==255)
//if(retry++>8) break;
//return r1;
while (retry<8) {
r1=spi_read(buffer);
if (r1==255){
retry++;
if ( retry>8) break;
}
if (r1 !=255){
retry=9;
return r1;
}
}
}
/////////////////////////////////////////////5
char mmcwrite(unsigned long sector, char *buffer ){
char r1;
unsigned i;
portd.f1=0;
//issue command
r1=mmccommand(24,sector<<9);
if(r1 != 0)
return r1;
spi_write(255); // send dummy
spi_write(254); //send data start token
for (i=0; i<512; i++)
{ spi_write(*buffer++);
}
spi_write(255); // write 16-bit crc (dummy values)
spi_write(255);
r1 = Spi_Read(buffer); // read data response token
if((r1&31) != 5)
return r1;
while(!r1) portd.f1=1; //CS
return 0; // return succes
}
/////////////////////////////////////////4
char mmcread(unsigned long sector, char *buffer ){
char r1;
unsigned i;
portd.f1=0;
r1= mmccommand(17,sector<<9);
if (r1!=0) return r1;
while(spi_read(buffer)!= 254)
for (i=0;i<512;i++) *buffer++ = spi_read(buffer);
spi_read(buffer); // read 16-bit CRC
spi_read(buffer);
portd.f1=1;
return 0;
}
/////////////////////////////////////////3
char mmcsendcommand(char cmd, unsigned long argument){
char r1;
portd.f1=0; //assert chip select
r1=mmccommand(cmd,argument); //issue the command
portd.f1=1;
return r1;
}
///////////////////////////////////////////// 2
char mmcreset(){
char i;
char retry;
char r1;
retry=0;
do{
for(i=0;i<10;i++) spi_write(255); // send dummy byte with CS high before accessing
r1= mmcsendcommand(0,0); //resetting card go to spi mode
retry++;
if(retry>10) return-1;
}while(r1 != 1);
retry=0;
do
{
r1= mmcsendcommand(1,0); // initializing card for operation
retry++;
if(retry>100) return-1;
}while(r1);
r1= mmcsendcommand(59,0); //turn off CRC checking to simplify communication
r1=mmcsendcommand(16,512);
return 0;
}
/////////////////////////////////////////////0
void main() {
trisd.f1=0;
portd.f1=1;
TRISB = 0; // PORTB is output
Lcd_Init(&PORTB); // Initialize LCD connected to PORTB
Lcd_Cmd(Lcd_CLEAR); // Clear display
Lcd_Cmd(Lcd_CURSOR_OFF); // Turn cursor off
Lcd_Out(1, 1, text); // Print text to LCD, 2nd row, 1st column
Spi_Init_Advanced(MASTER_OSC_DIV16, DATA_SAMPLE_MIDDLE, CLK_IDLE_LOW, LOW_2_HIGH);
mmcreset();
for (i=0;i<512;i++) {
write_buf[i]=i;
sector=5;
mmcwrite(sector,write_buf[i]); // write to sector 5
}
delay_ms(1);
mmcread(sector,read_buf[i]); // read of sector 5
while(1)
{
x=0;
while(x<512){
WordToStr(read_buf[x], txt);
Lcd_Out(2, 1, txt);
delay_ms(200);
Lcd_Cmd(Lcd_CLEAR);
Lcd_Out(1, 1, text);
portd.f1=1;
}
}
}//~!
// */
char* text = "mikroElektronika";
unsigned x=110;
unsigned short take, buffer;
char txt[6];
char r2=1;
void Pins()
{
trisc.f2 =1;
portc.f2 = 0;
trisd.f1 =0;
portd.f1 =1;
trisd.f0 =0;
portd.f0 =0;
TRISB = 0;
}
//////////////////////////////////////////LCD
void lcd(){
Lcd_Cmd(Lcd_CLEAR); // Clear display
Lcd_Cmd(Lcd_CURSOR_OFF); // Turn cursor off
Lcd_Out(1, 1, text); // Print text to LCD, 2nd row, 1st column
WordToStr( x, txt);
Lcd_Out(2, 1, txt);
delay_ms(300);
Lcd_Cmd(Lcd_CLEAR);
Lcd_Out(1, 1, text);
}
//////////////////////////////////////////6
mmccommand(){
char r1=0;
char retry=0;
r2=1;
portd.f1=0;
spi_write(64);
spi_write(0);
spi_write(0);
spi_write(0);
spi_write(0);
spi_write(149); //crc valid only for mmc_go_idle_state
portd.f1=1;
delay_ms(3);
portd.f1=0;
r1=spi_read(buffer);
x=r1;
r1=0;
portd.f1=1;
lcd();
}
/////////////////////////////////////////////0
void main() {
// PORTB is output
Lcd_Init(&PORTB); // Initialize LCD connected to PORTB
Spi_Init_Advanced(MASTER_OSC_DIV16, DATA_SAMPLE_MIDDLE, CLK_IDLE_LOW, LOW_2_HIGH);
lcd();
pins();
mmccommand();
while(1){
}
}
//
Yes, I was able to guess this myself. But you don't have the mikro C SD/MMC library?by the way I am using "mikroc" as compiler
That's a good way to start a project from the scratch. I would do it the same. The point is to check the results of each step exactly. I still think, that you can probably inherit existing code from the internet. But it's also very good to understand, how the stuff is working.I got decision , to simplify this project to just one command CMD0 . and if I could get right response I will expand the project step by step to the hole of the project.
of curse it has but as I said I am trying to do it myself.Yes, I was able to guess this myself. But you don't have the mikro C SD/MMC library?
I tried this solution too, as you saw in my previous topic, but it didn't work !!! didn't see, any mistake in my last codes ? I think the problem refers to SPI but I don't know how should I solved it. by the way I set the SPI protocol as mikroc defaults but still nothings!!! I received these numbers as R1: 255,127,240,7 but I expected to receive 5 or at least 1I still think, that you can probably inherit existing code from the internet
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?