Hallo, ich bin dabei eine 1GB MicroSD Karte mit einem STM32 zu initialisieren. CMD0 antwortet mit 0x01, also erreiche ich den IDLE state. Auf CMD8 kommt keine Antwort also nur 0xff. Daher gehe ich von SD Vers. 1 aus. Ich sende ACMD41, doch bereits beim CMD55 kommt als Antwort nur 0xff, also keine Antwort. Ich denke nicht, dass die MicroSD Karte als MMC Vers 3 erkannt werden möchte. Welche potentiellen Fehler könnte ich gemacht haben? Vielen Dank!
Zeig mal den Code. Du musst übrigens bei CMD8 die korrekte CRC7 Checksumme angeben. Ansonsten: Ein R1 Antwort-Byte mit gesetztem 0x80 Bit ist keine Antwort, sondern die Info dass sich die Antwort verzögert und man noch ein (dummy) Byte senden muss.
Ich werde mal versuchen ein dummybyte zu senden, wenn ein 0xff kommt. Ich bin aber eigentlich davon ausgegangen, dass einfach keine Antwort gekommen ist, wenn der MISO Pin nicht irgendwann mal nach unten gezogen worden ist. Die CRC Checksumme übergebe ich als 0x87 für CMD8 Hier mal die Initialisierung:
1 | SD_CS_H; |
2 | SD_WRITE_H; |
3 | SD_SCLK_L; |
4 | |
5 | delay_us(2000); // TODO vielleicht mehr als 1000 |
6 | |
7 | SD_toggle(148); |
8 | |
9 | sendArray[0] = CMD0; |
10 | sendArray[1] = 0x00; |
11 | sendArray[2] = 0x00; |
12 | sendArray[3] = 0x00; |
13 | sendArray[4] = 0x00; |
14 | SD_CS_L; // start |
15 | SD_Command_Write(&(sendArray[0])); |
16 | SD_Receive(1); |
17 | SD_WRITE_L; |
18 | SD_toggle(8); // TODO Pruefen ob notwendig |
19 | SD_CS_H; // stop |
20 | if (SD_readArray[0] == 0x01) // JA |
21 | {
|
22 | sendArray[0] = CMD8; |
23 | sendArray[1] = 0x00; |
24 | sendArray[2] = 0x00; |
25 | sendArray[3] = 0x01; |
26 | sendArray[4] = 0xAA; |
27 | SD_CS_L; // start |
28 | SD_Command_Write(&(sendArray[0])); |
29 | if (!SD_Receive(5)) |
30 | {
|
31 | SD_WRITE_L; |
32 | SD_toggle(8); // TODO Pruefen ob notwendig |
33 | SD_CS_H; // stop |
34 | SD_Version = 1; |
35 | }
|
36 | else
|
37 | {
|
38 | SD_WRITE_L; |
39 | SD_toggle(8); // TODO Pruefen ob notwendig |
40 | SD_CS_H; // stop |
41 | if (SD_readArray[0] & 0x7F) |
42 | {
|
43 | SD_Version = 1; |
44 | }
|
45 | if (SD_readArray[3] != 0x01 || (SD_readArray[4] != 0xAA)) |
46 | {
|
47 | SD_Version = 0; |
48 | // power off card
|
49 | return; |
50 | }
|
51 | }
|
52 | int errCounter = 0; |
53 | SD_CS_L; // start |
54 | do
|
55 | {
|
56 | sendArray[0] = CMD55; |
57 | sendArray[1] = 0x00; |
58 | sendArray[2] = 0x00; |
59 | sendArray[3] = 0x00; |
60 | sendArray[4] = 0x00; |
61 | SD_Command_Write(&(sendArray[0])); |
62 | SD_Receive(1); |
63 | |
64 | |
65 | sendArray[0] = ACMD41; |
66 | sendArray[1] = 0x40; |
67 | sendArray[2] = 0x00; |
68 | sendArray[3] = 0x00; |
69 | sendArray[4] = 0x00; |
70 | SD_Command_Write(&(sendArray[0])); |
71 | SD_Receive(1); |
72 | delay_us(1000); |
73 | errCounter++; |
74 | } while ((SD_readArray[0] == 0x01) && (errCounter <= 1000)); |
75 | SD_CS_H; // stop |
76 | // TODO hier muesste eigentlich eine 00 statt einer 0xff stehen
|
77 | if ((SD_readArray[0] == 0x00) && (errCounter <= 1000)) |
78 | {
|
79 | if (SD_Version == 2) |
80 | {
|
81 | SD_toggle(8); |
82 | sendArray[0] = CMD58; |
83 | sendArray[1] = 0x40; |
84 | sendArray[2] = 0x00; |
85 | sendArray[3] = 0x00; |
86 | sendArray[4] = 0x00; |
87 | SD_Command_Write(&(sendArray[0])); |
88 | SD_Receive(4); |
89 | if (SD_readArray[1] & 0x40) |
90 | {
|
91 | SDHC = 1; |
92 | return; |
93 | }
|
94 | }
|
95 | if (!SDHC) |
96 | {
|
97 | // Blocksize 512 Bytes
|
98 | SD_toggle(8); |
99 | sendArray[0] = CMD16; |
100 | sendArray[1] = 0x00; |
101 | sendArray[2] = 0x00; |
102 | sendArray[3] = 0x02; |
103 | sendArray[4] = 0x00; |
104 | SD_Command_Write(&(sendArray[0])); |
105 | SD_Receive(1); |
106 | }
|
107 | }
|
108 | else
|
109 | {
|
110 | SD_Version = 0; |
111 | // power off
|
112 | return; |
113 | }
|
114 | }
|
115 | else
|
116 | {
|
117 | SD_Version = 0; |
118 | // power off
|
119 | }
|
Also insgesamt sende ich 64 dummybits wo ich darauf warte, dass die MicroSD mir den MISO-Pin mal nach unten zieht. Tut sie aber nicht. --> keine Antwort Außerdem habe ich ein paar SD_WRITE_L durch SD_WRITE_H vor dem Toggeln ausgetauscht, weil ich ja 0xFF senden muss und nicht 0x00. Beim Toggeln werden jetzt also Einsen an de MOSI rausgeschickt. Dennoch läuft es nicht. Nachdem ich 0x01 vom CMD0 bekommen habe bekomme ich weder von CMD8 noch von ACMD41 (schon beim CMD55) keine Antwort. CMD8 ist bei mir: 0x48 0x00 0x00 0x01 0xAA 0x87
Holger schrieb: > Also insgesamt sende ich 64 dummybits wo ich darauf warte, dass die > MicroSD mir den MISO-Pin mal nach unten zieht. Tut sie aber nicht. --> > keine Antwort Bei welchem SPI Takt? Initial darf der maximal 400 kHz sein. In meiner SD Kommandofunktion wartet er bis zu 1000 Zeichen ab, ob das 0x80 Bit mal gelöscht wird. Das gilt auch für CMD0, das außerdem noch bis zu 16 Mal wiederholt wird. Nochwas:
1 | SD_WRITE_L; |
2 | SD_toggle(8); // TODO Pruefen ob notwendig |
3 | SD_CS_H; // stop |
Falsch herhum. "SD_CS_H;" muss vor dem Toggle stattfinden, also erst deselktieren und dann 0xFF Byte schreiben.
:
Bearbeitet durch User
Also der Takt liegt momentan bei 66 kHz. Also weit unter den 400kHz. Ich warte momentan nur 128 Bit. Ich habe das auf 8000 Bit (also 1000) Zeichen erhöht. Macht keinen Unterschied, nur dass man jetzt merkt, dass das Programm wartet. Da CMD0 bei mir richtig läuft lasse ich das dort erstmal mit dem einmal aufrufen. Idle reicht doch oder muss ich dann nochmal resetten? SD_CS_H steht jetzt vor dem toggeln, funktioniert aber auch nicht. Weder CMD8 noch CMD55 oder ACMD41 liefert mir irgendwann ein 0x00;
Hast du möglicherweise einen Logik Trace von der Initialisierung? Gruss
Holger schrieb: > Weder CMD8 noch CMD55 oder ACMD41 liefert mir irgendwann ein 0x00; Die dürfen aber auch 0x01 als Ergebnis liefern. Dass die Karte im Idle State ist, das ist ja korrekt so. Bei meinem Code (Quelle is EFSL) wird das CMD8 auf "1" als Ergebniscode geprüft.
Einen LogicTrace habe ich leider nicht. Wenn ich ein 0x01 erhalten würde wäre ich ja schon mal zufrieden. Leider antwortet die Karte gar nicht auf CMD8 und CMD55 oder ACMD41. Ich habe das Projekt jetzt erst einmal zurückgestellt und werde es später noch einmal versuchen. Vielen Dank aber bis jetzt!
Was für ein STM32 ist es denn? Ich hatte mir beim STM32F0 (fast) die Karten gelegt, weil das SPI-Register standardmäßig als 16-Bit Wert gelesen/geschrieben wird, d.h. es werden dann auch 16 Bits übertragen/gelesen. Außerdem hat der STM32F0 auch einen FIFO im SPI. Stimmt natürlich alles nur wenn man ohne die periphals lib programmiert.
Es ist ein STM32F407VGT6 auf einem Discovery Board. SPI habe ich nicht konfiguriert. Das mache ich momentan über Software. Also ganz simples Bit setzen, Takt hoch, 3us warten, Takt runter und nächstes Bit... Die Übertragung scheint auch zu klappten. Ich bekomme eine richtige Antwort auf CMD0.
Ich habe mich mal durchgesteppt. Sowohl der CMD55 als auch der ACMD41 antworten beide genau einmal mit 0x01. Und das beim ersten Durchlauf. Danach kommen nur noch 0xFF, also keine Antwort. Der Fehler muss also demnach im folgenden Codestück liegen.
1 | SD_CS_L; // start |
2 | int position = 0; |
3 | do
|
4 | {
|
5 | sendArray[0] = CMD55; |
6 | sendArray[1] = 0x00; |
7 | sendArray[2] = 0x00; |
8 | sendArray[3] = 0x00; |
9 | sendArray[4] = 0x00; |
10 | SD_Command_Write(&(sendArray[0])); |
11 | if (SD_Receive(1)) |
12 | {
|
13 | position = 1; |
14 | }
|
15 | |
16 | // SD_CS_H; // stop
|
17 | // SD_toggle(8); // TODO Pruefen ob notwendig
|
18 | // SD_CS_L;
|
19 | |
20 | sendArray[0] = ACMD41; |
21 | sendArray[1] = 0x40; |
22 | sendArray[2] = 0x00; |
23 | sendArray[3] = 0x00; |
24 | sendArray[4] = 0x00; |
25 | SD_Command_Write(&(sendArray[0])); |
26 | if (SD_Receive(1)) |
27 | {
|
28 | position = 2; |
29 | }
|
30 | |
31 | SD_CS_H; // stop |
32 | SD_toggle(8); // TODO Pruefen ob notwendig |
33 | SD_CS_L; |
34 | |
35 | delay_us(1000); |
36 | errCounter++; |
37 | } while ((SD_readArray[0] != 0x00) && (errCounter <= 1000)); |
38 | SD_CS_H; // stop |
Holger schrieb: > Also ganz simples Bit setzen, dann vergleiche deinen Code mit dem bitbanging Code von Chan -avr foolproof. Oder noch besser, nimm gleich den code von chan. Beim F103 hat der fast auf Anhieb geklappt.
Praxis ist wenn es geht und weiß nicht warum. Auf jeden Fall klappt es jetzt nach der Mittagspause die Karte als SDHC zu initialisieren. Hier der fertige Initialisierungscode:
1 | void SD_init(void) |
2 | {
|
3 | unsigned char sendArray[5]; |
4 | SD_Version = 2; |
5 | SDHC = 0; |
6 | |
7 | // Konfiguration SCK, MISO, MOSI, CS
|
8 | // Pullips
|
9 | GPIOC -> PUPDR &= ~(1 << 25); |
10 | GPIOC -> PUPDR |= (1 << 24); |
11 | GPIOC -> PUPDR &= ~(1 << 23); |
12 | GPIOC -> PUPDR |= (1 << 22); |
13 | GPIOD -> PUPDR &= ~(1 << 5); |
14 | GPIOD -> PUPDR |= (1 << 4); |
15 | |
16 | // Konfiguration des Eingangs (MISO PC8)
|
17 | GPIOC -> MODER &= ~((1 << 16) + (1 << 17)); |
18 | GPIOC -> PUPDR &= ~(1 << 17); |
19 | GPIOC -> PUPDR |= (1 << 16); |
20 | // GPIOC -> TYPER |= (1 << 8); // open drain
|
21 | |
22 | // Konfiguration der Outputs
|
23 | GPIOC -> MODER |= (1 << 22) + (1 << 24); |
24 | GPIOD -> MODER |= (1 << 4); |
25 | |
26 | SD_SCLK_L; |
27 | |
28 | delay_us(2000); // TODO vielleicht mehr als 1000 |
29 | |
30 | SD_CS_H; |
31 | SD_WRITE_H; |
32 | |
33 | SD_toggle(148); // TODO vielleicht mehr als 74 |
34 | |
35 | sendArray[0] = CMD0; |
36 | sendArray[1] = 0x00; |
37 | sendArray[2] = 0x00; |
38 | sendArray[3] = 0x00; |
39 | sendArray[4] = 0x00; |
40 | SD_CS_L; // start |
41 | SD_Command_Write(&(sendArray[0])); |
42 | SD_Receive(1); |
43 | SD_CS_H; // stop |
44 | SD_toggle(8); // TODO Pruefen ob notwendig |
45 | if (SD_readArray[0] == 0x01) // JA |
46 | {
|
47 | sendArray[0] = CMD8; |
48 | sendArray[1] = 0x00; |
49 | sendArray[2] = 0x00; |
50 | sendArray[3] = 0x01; |
51 | sendArray[4] = 0xAA; |
52 | SD_CS_L; // start |
53 | SD_Command_Write(&(sendArray[0])); |
54 | if (SD_Receive(5) == 0) |
55 | {
|
56 | SD_CS_H; // stop |
57 | SD_toggle(8); // TODO Pruefen ob notwendig |
58 | SD_Version = 1; |
59 | }
|
60 | else
|
61 | {
|
62 | SD_CS_H; // stop |
63 | SD_toggle(8); // TODO Pruefen ob notwendig |
64 | if (SD_readArray[0] & 0x7E) |
65 | {
|
66 | SD_Version = 1; |
67 | }
|
68 | if (SD_readArray[3] != 0x01 || (SD_readArray[4] != 0xAA)) |
69 | {
|
70 | SD_Version = 0; |
71 | // power off card
|
72 | return; |
73 | }
|
74 | }
|
75 | int errCounter = 0; |
76 | SD_CS_L; // start |
77 | int position = 0; |
78 | do
|
79 | {
|
80 | SD_CS_H; |
81 | SD_toggle(16); // TODO Pruefen ob notwendig (16) |
82 | SD_CS_L; |
83 | |
84 | sendArray[0] = CMD55; |
85 | sendArray[1] = 0x00; |
86 | sendArray[2] = 0x00; |
87 | sendArray[3] = 0x00; |
88 | sendArray[4] = 0x00; |
89 | SD_Command_Write(&(sendArray[0])); |
90 | if (SD_Receive(1)) |
91 | {
|
92 | position = 1; |
93 | }
|
94 | |
95 | SD_CS_H; |
96 | SD_toggle(16); // TODO Pruefen ob notwendig (16) |
97 | SD_CS_L; |
98 | |
99 | sendArray[0] = ACMD41; |
100 | if (SD_Version == 2) sendArray[1] = 0x40; |
101 | else sendArray[1] = 0x00; |
102 | sendArray[2] = 0x00; |
103 | sendArray[3] = 0x00; |
104 | sendArray[4] = 0x00; |
105 | SD_Command_Write(&(sendArray[0])); |
106 | if (SD_Receive(1)) |
107 | {
|
108 | position = 2; |
109 | }
|
110 | |
111 | errCounter++; |
112 | } while ((SD_readArray[0] != 0x00) && (errCounter <= 100)); |
113 | SD_CS_H; // stop |
114 | // TODO hier muesste eigentlich eine 00 statt einer 0xff stehen
|
115 | int test = SD_readArray[0]; |
116 | if ((SD_readArray[0] == 0x00) && (errCounter <= 1000)) |
117 | {
|
118 | if (SD_Version == 2) |
119 | {
|
120 | SD_CS_H; // stop |
121 | SD_toggle(16); // TODO Pruefen ob notwendig |
122 | sendArray[0] = CMD58; |
123 | sendArray[1] = 0x40; |
124 | sendArray[2] = 0x00; |
125 | sendArray[3] = 0x00; |
126 | sendArray[4] = 0x00; |
127 | SD_Command_Write(&(sendArray[0])); |
128 | SD_Receive(4); |
129 | if (SD_readArray[1] & 0x40) |
130 | {
|
131 | SDHC = 1; |
132 | return; |
133 | }
|
134 | }
|
135 | if (!SDHC) |
136 | {
|
137 | // Blocksize 512 Bytes
|
138 | SD_CS_H; // stop |
139 | SD_toggle(16); // TODO Pruefen ob notwendig |
140 | sendArray[0] = CMD16; |
141 | sendArray[1] = 0x00; |
142 | sendArray[2] = 0x00; |
143 | sendArray[3] = 0x02; |
144 | sendArray[4] = 0x00; |
145 | SD_Command_Write(&(sendArray[0])); |
146 | SD_Receive(1); |
147 | }
|
148 | }
|
149 | else
|
150 | {
|
151 | SD_Version = 0; |
152 | // power off
|
153 | return; |
154 | }
|
155 | }
|
156 | else
|
157 | {
|
158 | SD_Version = 0; |
159 | // power off
|
160 | }
|
161 | }
|
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.