Forum: Mikrocontroller und Digitale Elektronik SD Karte Initialisieren


von Gast (Gast)


Lesenswert?

Hallo

Habe ein Problem mit der Initialisierung einer SD-Karte(FAT16, 64MB, 
Panasonic). Ich benutze den Code von Ulrich Radig und einen AT90USB1287. 
Wenn ich die Karte nicht im Slot habe bleibt die Initialisierung stehen 
(Richtig so!) Wenn ich die Karte nun in den Slot schiebe funktioniert 
die Initialisierung bis zur While-Schleife, wo der Command 0 gesendet 
wird. Leider 'hängt' er sich dort auf und bricht wegen dem Timeout ab. 
Wenn ich nun die gesendeten Werte der SD Karte ausgebe, dann sieht es 
wie folgt aus:

Initialisiere SD Karte in SPI-Mode
SENDE Command CMD0
Byte: 63
While schleife verlassen: tmp = 63
Byte: 255
Byte: 5
While schleife verlassen: tmp = 5
Byte: 191
While schleife verlassen: tmp = 191
Byte: 255
Byte: 5
While schleife verlassen: tmp = 5
...
...
...
Byte: 255
Byte: 5
While schleife verlassen: tmp = 5
Timeout CMD0


Habe mal gelesen, dass eine 5 (MMC_ERR_OPEN_RD) ein Öffnungsfehler beim 
Lesen ist. Ist die SD-Karte schon defekt oder liegt der Fehler an einem 
anderen Ort?

Vielen Dank für die Hilfe

Gruss


Hier der Ausschnitt aus dem Code:
-------------------------------------
1
USART_Sende_String("Initialisiere SD Karte in SPI-Mode\n\r");
2
uint8_t b;
3
for (b = 0;b<0x0f;b++) //Sendet min 74+ Clocks an die MMC/SD-Karte
4
{
5
     mmc_write_byte(0xff);
6
}  
7
8
USART_Sende_String("SENDE Command CMD0\n\r");
9
10
uint8_t CMD[] = {0x40,0x00,0x00,0x00,0x00,0x95};
11
while(mmc_write_command (CMD) !=1)
12
{
13
   if (Timeout++ > 200)
14
   {
15
  MMC_Disable();
16
USART_Sende_String("Timeout CMD0\n\r");
17
  return(1); //Abbruch bei Commando1 (Return Code1)
18
   }
19
}
20
-----------------------------
21
unsigned char mmc_write_command (unsigned char *cmd){
22
  unsigned char tmp = 0xff;
23
  unsigned int Timeout = 0;
24
25
  //set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv) 
26
  MMC_Disable();
27
28
  //sendet 8 Clock Impulse
29
  mmc_write_byte(0xFF);
30
31
  //set MMC_Chip_Select to low (MMC/SD-Karte Aktiv)
32
  MMC_Enable();
33
34
  //sendet 6 Byte Commando
35
  unsigned char a;
36
  for (a = 0;a<0x06;a++) //sendet 6 Byte Commando zur MMC/SD-Karte
37
  {
38
    mmc_write_byte(*cmd++);
39
  }
40
41
  //Wartet auf ein gültige Antwort von der MMC/SD-Karte
42
  while (tmp == 0xff)  
43
    {
44
    tmp = mmc_read_byte();
45
46
    if (Timeout++ > 500)
47
      {
48
      break; 
49
      }
50
    }
51
  usart_write("While schleife verlassen: tmp = %i\n\r",tmp);
52
  return(tmp);
53
}
54
55
inline unsigned char mmc_read_byte (void){
56
  unsigned char Byte = 0;
57
58
  SPDR = 0xff;
59
  while(!(SPSR & (1<<SPIF))){};
60
  Byte = SPDR;
61
usart_write("Byte: %i\n\r",Byte);
62
  return (Byte);
63
}

von Gast (Gast)


Lesenswert?

Die Karte ist nicht Defekt, kann sie unter Ubuntu ohne Probleme lesen 
und beschreiben. Das Problem muss an einer anderen Stelle sein...

Gruss

von Christoph (Gast)


Lesenswert?

Wie wird die Karte angesprochen? Sehr wahrscheinlich über Hardware-SPI? 
Ich hatte das Problem, dass ich meine Karte nicht ansprechen konnte, 
solange ich den ISP-Programmer angeschlossen hatte. Evtl. hilft Dir das 
weiter.

Gruss
Christoph

von roboterheld (Gast)


Lesenswert?

wahrscheinlich stimmen deine grundeinstellungswerte für den chip nicht. 
prüfe die nach.

von roboterheld (Gast)


Lesenswert?

ich habe mein kartenprogramm mit bascom geschrieben für eine sd-karte.

alles von hand reingebracht , mit shift right und links und so zu fuss 
erstellt. die zeiten sind stoppuhrzeiten und läuft. also es ist keine 
zauberei so eine billige karte zum laufen zu bringen.

von Gast (Gast)


Lesenswert?

Hallo Christoph

Die Karte wird mit der Hardware SPI angesprochen. Über ISP programmiere 
ich den uP.

Gute Idee mit dem Ausstecken des ISP. Leider geht es damit aber 
immernoch nicht. Bekomme noch die gleichen Ausgaben...

Der uP läuft mit 16Mhz, kann es sein, dass die SPI Initialisierung 
fehlerhaft ist?

Gruss


Hier noch die SPI Initialisierung:
1
DDRB &= ~(1<<PINB3);  // PortB Pin 3 (SPI MISO) -> Eingang
2
DDRB |=  (1<<PINB2);  // PortB Pin 2 (SPI MOSI) -> Ausgang
3
DDRB |=  (1<<PINB1);  // PortB Pin 1 (SPI SCK) -> Ausgang
4
DDRB |=  (1<<PINB0);  // PortB Pin 0 (SPI CS) -> Ausgang
5
6
USART_Sende_String("Aktiviere SPI\n\r");
7
8
// Aktiviere SPI als Master mit OSC/128 
9
SPCR = (1<<SPE) | (1<<MSTR) | (1<<SPR1) | (1<<SPR0);
10
// Aktiviere doppelte Geschwindigkeit
11
SPSR = (1<<SPI2X);

von Gast (Gast)


Lesenswert?

Hallo roboterheld

Mit welchem Datenblatt hast Du gearbeitet? Habe drum noch kein wirklich 
gutes gefunden...

Gruss

von Peter (Gast)


Lesenswert?

Bei manchen Karten muss der SPI-Modus erst aktiviert werden.
Steht hier unter "Initialization Procedure for SPI Mode"
http://elm-chan.org/docs/mmc/mmc_e.html

von Gast (Gast)


Lesenswert?

Hallo Peter

Das habe ich auch schon versucht, ergibt aber keinen Unterschied. Ich 
bekomme immer das gleiche Resultat.

Gruss

von Gast (Gast)


Angehängte Dateien:

Lesenswert?

Kann irgend Jemand die Zahlen deuten?

Habe noch den Schaltplan der SD-Karte und der Code SD.c angehängt. 
Vielleicht nützt es etwas...

DANKE!
1
// AT90USB1287 (16MHz)
2
//SD.c
3
4
#include "mmc.h"
5
#include "usart.h"
6
7
uint8_t mmc_init (void){
8
uint16_t Timeout = 0;
9
10
DDRB &= ~(1<<PINB3);    // PortB Pin 3 (SPI MISO) -> Eingang
11
DDRB |=  (1<<PINB1);    // PortB Pin 1 (SPI SCK) -> Ausgang
12
DDRB |=  (1<<PINB2);    // PortB Pin 2 (SPI MOSI) -> Ausgang
13
DDRB |=  (1<<PINB0);    // PortB Pin 0 (SPI CS) -> Ausgang
14
15
USART_Sende_String("Aktiviere SPI\n\r");
16
17
// Aktiviere SPI als Master mit OSC/128
18
SPCR = (1<<SPE) | (1<<MSTR) | (1<<SPR1) | (1<<SPR0);
19
20
// Aktiviere doppelte Geschwindigkeit
21
SPSR = (1<<SPI2X);
22
  
23
int ii;
24
for (ii = 0;ii<0xff;ii++){};
25
// Setze MOSI und CS auf 1
26
PORTB |= (1<<PINB2);
27
PORTB |= (1<<PINB0);
28
29
//Initialisiert MMC/SD-Karte in den SPI-Mode
30
USART_Sende_String("Initialisiere SD Karte in SPI-Mode\n\r");
31
uint8_t b;
32
for (b = 0;b<0x0f;b++) //Sendet min 74+ Clocks an die MMC/SD-Karte
33
{
34
  mmc_write_byte(0xff);
35
}
36
// CS auf 0
37
PORTB &=~ (1<<PINB0);
38
39
//Sendet Commando CMD0 an MMC/SD-Karte (Go_Idle_State)
40
USART_Sende_String("SENDE Command CMD0\n\r");
41
42
uint8_t CMD[] = {0x40,0x00,0x00,0x00,0x00,0x95};
43
44
while(mmc_write_command (CMD) !=1)
45
{
46
   if (Timeout++ > 200)
47
   {
48
   MMC_Disable();
49
   USART_Sende_String("Timeout CMD0\n\r");
50
   return(1); //Abbruch bei Commando1 (Return Code1)
51
   }
52
}
53
USART_Sende_String("Sende Command CMD1\n\r");
54
55
//Sendet Commando CMD1 an MMC/SD-Karte
56
Timeout = 0;
57
CMD[0] = 0x41;//Commando 1
58
CMD[5] = 0xFF;
59
while( mmc_write_command (CMD) !=0)
60
{
61
   if (Timeout++ > 400)
62
   { 
63
   MMC_Disable();
64
   return(2); //Abbruch bei Commando2 (Return Code2)
65
   }
66
}
67
USART_Sende_String("SPI-MODe\n\r");
68
#if SPI_Mode
69
//SPI Bus auf max Geschwindigkeit
70
SPCR &= ~((1<<SPR0) | (1<<SPR1));
71
SPSR = SPSR|(1<<SPI2X);
72
#endif
73
  
74
USART_Sende_String("Disable MCC\n\r");
75
//set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
76
MMC_Disable();
77
return(0);
78
}
79
//############################################################################
80
//Sendet ein Commando an die MMC/SD-Karte
81
unsigned char mmc_write_command (unsigned char *cmd)
82
//############################################################################
83
{
84
  unsigned char tmp = 0xff;
85
  unsigned int Timeout = 0;
86
87
  //set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv) 
88
  MMC_Disable();
89
90
  //sendet 8 Clock Impulse
91
  mmc_write_byte(0xFF);
92
93
  //set MMC_Chip_Select to low (MMC/SD-Karte Aktiv)
94
  MMC_Enable();
95
96
  //sendet 6 Byte Commando
97
  unsigned char a;
98
  for (a = 0;a<0x06;a++) //sendet 6 Byte Commando zur MMC/SD-Karte
99
    {
100
    mmc_write_byte(*cmd++);
101
    }
102
103
  //Wartet auf ein gültige Antwort von der MMC/SD-Karte
104
  while (tmp == 0xff)  
105
    {
106
    tmp = mmc_read_byte();
107
108
    if (Timeout++ > 500)
109
      {
110
USART_Sende_String("Timeout Read Byte in (write command)\n\r");
111
      break; //Abbruch da die MMC/SD-Karte nicht Antwortet
112
      }
113
    }
114
usart_write("While schleife verlassen: tmp = %i\n\r",tmp);
115
  return(tmp);
116
}
117
//############################################################################
118
//Routine zum Empfangen eines Bytes von der MMC-Karte 
119
inline unsigned char mmc_read_byte (void)
120
//############################################################################
121
{
122
  unsigned char Byte = 0;
123
124
  SPDR = 0xff;
125
  while(!(SPSR & (1<<SPIF))){};
126
  Byte = SPDR;
127
usart_write("Byte: %i\n\r",Byte);
128
  return (Byte);
129
}
130
//############################################################################
131
//Routine zum Senden eines Bytes zur MMC-Karte
132
inline void mmc_write_byte (unsigned char Byte)
133
//############################################################################
134
{
135
  SPDR = Byte;   //Sendet ein Byte
136
  while(!(SPSR & (1<<SPIF))) //Wartet bis Byte gesendet wurde
137
  {
138
  }
139
}

von holger (Gast)


Lesenswert?

Was soll denn der Spannungsteiler an MISO ?
Das ist der Ausgang der SD Karte. Den musst
du direkt an den AVR anschließen. Und wie sind
deine 3V stabilisiert ?

von Gast (Gast)


Lesenswert?

Shit!!! Der MISO muss direkt mit dem uP verbunden sein!

Habe es korrigiert. Nun findet er die Karte und ich kann weitermachen.

VIELEN DANK FÜR DIE HILFE!!!

Gruss

von Rudolph (Gast)


Angehängte Dateien:

Lesenswert?

Also am MISO Spannungsteiler kann es ja wohl nicht gelegen haben?
Nun ja, vielleicht ist der ein wenig nieder-ohmig.
Aber von der SD-Karte zum Controller ist das kein Spannungs-Teiler 
sondern ein Pulldown und ein Reihen-Widerstand.

Ein Problem bekommt man ohne Spannungsteiler dann, wenn der Pin vom 
Controller aus irgendeinem Grund aktiv gegen +5V geht.

Genauso wie mit dem Spannungs-Teiler an CS der Karte diese immer dann 
aktiv geschaltet wird, wenn der Controller im Reset ist.


Die angehängte Schaltung funktioniert auf meiner Platine mit 2 MHz SPI 
ohne Probleme, schützt MISO und lässt CS nicht auf GND hängen.
Wobei meine Widerstände in 0805 sind und keine Leitung länger als 1,5 
cm...

Im Controller müssen an den Eingängen die Pullup-Widerstände aktiviert 
sein.

von Peter (Gast)


Lesenswert?

das ist doch völlig übertrieben^^, einfach die spi-leitungen direkt mit 
dem controller verbinden und ein pull-up an den /CS, --> fertig!

von Rudolph (Gast)


Lesenswert?

Na klar kann man den Controller auch auf 3V betreiben, was aber,
wenn das nicht gewünscht ist?

von Peter (Gast)


Lesenswert?

einen pegelwandler-chip nehmen, max1841 oder sowas. :-)

von spess53 (Gast)


Lesenswert?

Hi

Einfacher und billiger: 74HC4050. Verträgt Eingangsspannungen oberhalb 
Betriebsspannung.

MfG Spess

von Rudolph (Gast)


Lesenswert?

Blöd, dass in dem MAX1841 nur drei Level-Shifter drin sind und den man 
wahrscheinlich nur als Muster bekommen kann.

Und der 74HC4050 ist auch als TSSOP16 (5,1x6,6+ mm) ein wenig klobig. 
:-)

von Hans W. (hans_wurst)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe mich bisher zwar noch nicht mit der Hardware für die SD-card 
beschäftigt, jedoch nutze ich sie mit Hilfe des Eval-boards EVK1100 von 
Atmel.
Vielleicht hilft dir dessen Schaltplan weiter? Ich füge ihn hier mit 
ein. Links oben siehst du die Ausgänge MOSI,usw. vom uP und rechts unten 
die Anschlüsse an den card-connector. Die nutzen dort externe pull-up 
Widerstände.

Falls dein uP jedoch keinen 3,3V Ausgang hat: laut spec 
(http://www.sdcard.org/about/memory_card/pls/Simplified_Physical_Layer_Spec.pdf) 
darf die card nur max 3,6V erhalten.

Hoffe ich konnte weiter helfen.

von Mario E. (Firma: Vet. med. Uni Wien) (pfeife)


Lesenswert?

Hi alle,

Ichh abe so wie am Anfang des Thread beschrieben den gleichen Fehler.
Das CMD0 (0x40) kommt korrekt hinüber, die Karte Antwortet auch korrekt,
sonst ginge es ja nicht zu CMD1 (0x41) weiter. Dann kommt auch bei mir 
als Antwort die 5.

Wo war jetzt die Lösung des Problems, kann das aus dem Thread nicht ganz 
erkennen?! Auch wenn die obige Schaltung ein wenig einfach ist, die 5 
bedeutet ja, dass der Chip geantwortet hat.

Mein Adapter ist der von RIBU Elektronik mit integriertem Pegelwandler.

Gruß aus Wien, Mario

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.