Forum: Mikrocontroller und Digitale Elektronik SD-Karte, Probleme mit CMD1


von Stefan_h (Gast)


Lesenswert?

Morgen,

Ich habe eine SD-Karte an einen Atmega128 mit Pegelwandler MAX3378 
angeschlossen und kann diese Karte nicht initialisieren(eine 32MB SD und 
eine microSD mit 2GB). Ich schicke via SPI das CMD0 und erhalte 0x01, 
das ist ja auch gut so ;-). Wenn ich nun die Karte Initialisieren möchte 
(CMD1) erhalte ich zuerst ein paar mal 0xff, dann einmal 0xfc und ein 
0x07 ab dann wieder 0xff.

Preudocode:
1
SPI_Init();
2
for i=0 to 15 //sync.
3
  SPI_put_char(0xff);
4
wait(5);//5s waiting
5
SPI_cs_enable(); //set cs low
6
7
SPI_put_char(0x40);
8
SPI_put_char(0x00);
9
SPI_put_char(0x00);
10
SPI_put_char(0x00);
11
SPI_put_char(0x00);
12
SPI_put_char(0x95);
13
do
14
{
15
  answer=SPI_get_char();
16
}while(answer==0xff)
17
18
rs232_send_byte(answer);//PC rec. 0x01
19
20
SPI_put_char(0x41);
21
SPI_put_char(0x00);
22
SPI_put_char(0x00);
23
SPI_put_char(0x00);
24
SPI_put_char(0x00);
25
SPI_put_char(0x01);
26
do
27
{
28
  answer=SPI_get_char();
29
  rs232_send_byte(answer);//PC rec. 0xff 0xff 0xff 0xfc 0x07 0xff 0xff (point of no return)
30
}while(answer!=0x00)

Hat jemand eine Idee? Was mache ich falsch?

glg,

Stefan

von Rex Gildo jr. (Gast)


Lesenswert?

Moin !

Gug mal hier rein ;)

http://www.captain.at/electronic-atmega-mmc.php

Gruß

von Rex Gildo jr. (Gast)


Lesenswert?


von Gast (Gast)


Lesenswert?

Du sendest auch 0xFF (andere Werte führen bein manchen Karten zu 
Fehlern) an die SPI, wenn du ein Byte empfangen willst?

von Stefan_h (Gast)


Lesenswert?

hallo,

@Rex: wo liegt dort der unterschied zu meinem code? Das einzige was ich 
gesehen: Ich sende das CMD1 mit crc=0 und das Beispiel mit crc=0x7F. 
Weiters hole ich nach dem Senden von CMD1 immer nur ein Byte ab, in dem 
beispiel wird solange das CMD1 geschickt bis die richtige antwort kommt, 
habe ich beides bei mir auch verändert, dann kommt prinzipiell immer 
0xff und hinundwieder 0xfc oder oxfe.

@Gast: Ja ich schicke 0xff bei SPI_get_char();

lg,

Stefan

von M. G. (looking)


Lesenswert?

Stefan_h schrieb:
> SPI_put_char(0x41);
> SPI_put_char(0x00);
> SPI_put_char(0x00);
> SPI_put_char(0x00);
> SPI_put_char(0x00);
> SPI_put_char(0x01);

Probier mal bei CMD 0x41 im letzten Byte 0xFF zu senden statt 0x01.

von Stefan_h (Gast)


Lesenswert?

gerade probiert, gleiches ergebnis.

von Rex Gildo jr. (Gast)


Lesenswert?

Command 1 :

Deine Version :

SPI_put_char(0x41);
SPI_put_char(0x00);
SPI_put_char(0x00);
SPI_put_char(0x00);
SPI_put_char(0x00);
SPI_put_char(0x01);


Version Captain.at :

SPI_put_char(0x41);
SPI_put_char(0x00);
SPI_put_char(0x00);
SPI_put_char(0x00);
SPI_put_char(0x00);
SPI_put_char(0xFF);
SPI_put_char(0xFF);

Gruß

von Olaf (Gast)


Lesenswert?

> Wenn ich nun die Karte Initialisieren möchte (CMD1) erhalte
> ich zuerst ein paar mal 0xff, dann einmal 0xfc und ein
> 0x07 ab dann wieder 0xff.

Ich bin jetzt zu faul fuer dich das Datenblatt zu lesen, aber
soll es bei diesem Kommando denn zwei Bytes als Antwort geben?
Wenn nicht dann hast du wohl ein Problem auf niedrigstem Level,
also falscher SPI-Mode, Flankensteilheit, Reflexion auf dem Kabel.

Olaf

von M. G. (looking)


Lesenswert?

Noch ein Vorschlag:


...
rs232_send_byte(answer);//PC rec. 0x01

SPI_cs_disable(); //set cs high

SPI_put_char(0xFF);

SPI_cs_enable(); //set cs low
SPI_put_char(0x41);
SPI_put_char(0x00);
SPI_put_char(0x00);
SPI_put_char(0x00);
SPI_put_char(0x00);
SPI_put_char(0xFF);
do
{
  answer=SPI_get_char();
  rs232_send_byte(answer);//PC rec.
}while(answer!=0x00)

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Hast Du einen Pullup am DO der Karte? Wie schnell ist die Taktfrequenz 
des SPI?

von Stefan_h (Gast)


Lesenswert?

Hi,

Danke vielmals für die vielen antworten, es war eine Kombination aller 
Antworten.

Ich habe den Code so geändert:

do
{

  SPI_cs_disable(); //set cs high
  SPI_put_char(0xFF);
  SPI_cs_enable(); //set cs low

  SPI_put_char(0x41);
  SPI_put_char(0x00);
  SPI_put_char(0x00);
  SPI_put_char(0x00);
  SPI_put_char(0x00);
  SPI_put_char(0xFF);
  do
  {
    answer=SPI_get_char();
  }while(answer==0xff);
  rs232_send_byte(answer);//PC rec.
}while(answer!=0x00)

Anscheinend muss das Commando immerwieder an die Karte geschickt werden 
und davor jedesmahl das CS auf High - ein 0xff schicken - und wieder CS 
wieder auf Low, dann das Commando schicken und auf die Anwort warten, 
die ist bei den ersten 2x 0x01 und beim dritten mal dann 0x00, also 
initialisiert. Warum das so ist, weiß ic nicht, lt. Datenblatt sollte es 
anders gehen, vieleicht hab ichs auch falsch verstanden. Egal.

Ich werd dann mal versuchen Daten zu schreiben und zu lesen, wenns nicht 
geht melde ich mich wieder ;-)

lg,

Stefan

von Rex Gildo jr. (Gast)


Lesenswert?

Schön dass es funktioniert :)

Anbei noch 2 Anmerkungen.


Stefan_h wrote :

>Anscheinend muss das Commando immerwieder an die Karte geschickt werden

Richtig , was der captain.at Code ja auch beinhaltet ?!
1
st: // if there is no MMC, prg. loops here
2
  if (Command(0x41,0,0,0xFF) !=0) goto st;

>und davor jedesmahl das CS auf High - ein 0xff schicken - und wieder CS
>wieder auf Low

Laut code (und eigener zurückliegender Erfahrung) ist es wichtig die 
clock Leitung am Anfang EINMAL high und dann wider low zu ziehen.
Das Timing was im code angegeben ist, muss eingehalten werden..also 80 
Clockzyklen:
1
  PORTB |= (1 << SPICS); // disable MMC
2
  // start MMC in SPI mode
3
  for(i=0; i < 10; i++) SPI(0xFF); // send 10*8=80 clock pulses
4
  PORTB &= ~(1 << SPICS); // enable MMC

Gruß

von Rex Gildo jr. (Gast)


Lesenswert?

Sorry meine natürlich nicht die Clockleitung sonder CS ?!

von Stefan_h (Gast)


Lesenswert?

Hallo,

mein Status ist im Moment folgender:

- Karte in Idle setzen geht
- Karte dann initialisieren geht auch

das wars dann schon :-(

Habe dann versucht 512 Bytes auf die Karte zu schreiben:
1
do
2
{
3
   SPI_put_char(0xFF);
4
   SPI_put_char(0x58);
5
   SPI_put_char(0x00);
6
   SPI_put_char(0x00);
7
   SPI_put_char(0x02);
8
   SPI_put_char(0x00);
9
   SPI_put_char(0xFF);
10
   answer=SPI_get_char();
11
}while(answer==0xFF);//CMD write block
12
13
rs232_send_hex(answer);//PC rec. 0x00
14
SPI_put_char(0xff);
15
SPI_put_char(0xff);
16
SPI_put_char(0xfe);//start block
17
for(i=0;i<512;i++)
18
{
19
  SPI_put_char(0xAA);//block
20
}
21
SPI_put_char(0xff);//dummy
22
SPI_put_char(0xff);//dummy
23
do
24
{
25
  answer=SPI_get_char();
26
  rs232_send_hex(answer);
27
}while(answer==0xFF);
28
29
answer&=0x1f;
30
rs232_send_hex(answer);//should be 0x05
31
do
32
{
33
  answer=SPI_get_char();
34
}while(answer!=0xFF);

Statt den zu erwartenden 0x05 kommt meist was anderes konnte kein Muster 
erkennen. Hatte aber schon einmal 0x05!

habe einmal versucht die Bocklänge zu setzen, erhalte als antwort nie 
0x00, meist 0x03 oder 0x01 ...:
1
SPI_Disable();
2
SPI_PutChar(0xFF);
3
SPI_Enable();
4
do
5
{
6
  SPI_put_char(0x50);
7
  SPI_put_char(0x00);
8
  SPI_put_char(0x00);
9
  SPI_put_char(0x00);
10
  SPI_put_char(0x00);
11
  SPI_put_char(0xFF);
12
  do
13
  {
14
    answer=SPI_get_char();
15
  }while(answer==0xFF);
16
}while(answer!=0x00);

Habe auch schon viele codebeispiele(http://www.captain.at, 
http://www.captain.at, uvm) ausprobiert, CMD1 geht weiter komme ich 
nicht.

Ideen?

glg,

Stefan

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.