Hallo, Ich habe gewisse Probleme beim Initialisieren meiner SD-Karte. Der C-Code basiert auf den Routinen von Ulrich Radig. Ich benutze allerdings keinen AVR Controller sondern einen XC161 von Infineon. Bekomme beim Versuch das CMD0 zu senden keine Antwort von der Karte. Oder besser gesagt, besitzt mein SSC0_RB (Empfangsregister) dauerhaft den Wert 0xFF und das Receive-Error-Flag ist im SSC0_CON_EN = 1 gesetzt. Was ja soviel bedeutet, wie das ein Datenempfang abgeschlossen wurde, jedoch nicht in das Empfangsregister übertragen wurde. Bekomme ich hier irgendwie einen Überlauf? Bei der Übertragung des CMD0 erscheinen alle Bytes nacheinander in der richtigen Reihenfolge (MSB first) im SSC0_TB. Erhalte danach aber keine Antwort von der Karte. Wert von SSC0_RB weiterhin 0xFF. Die Schnittstelle initialisiere ich mit 1Mbit/s. Sollte also kein Problem sein. Wäre super, wenn jemand einen Tipp parat hätte. Habe meinen Code angehangen.
Ich kenne den XC161 zwar nicht, aber probiere es mal mit 400kHz. Diese start-clk gibt SD als value vor bevor es nach lesen von CSD & CID bis auf 20MHz geht ... hier mein Beispiel-code, der MMC MMCplus M-Bridge SD SDHC beherrscht: http://www.embedded-os.de/index.html?pcfat_port.htm
Hallo, erstmal Danke für die Hilfe. Habe es aber auch schon mit 400kHz versucht, auch mit 200kHz. Bin aber nun auf ein anderes Problem gestoßen. Anscheinend arbeitet meine Pegelumsetzung an der MISO-Leitung nicht so wie ich das will. Hier werde ich als erstes noch mal ansetzen.
Es lag wirklich an der Pegelumsetzung von der MISO-Leitung. Hatte dort einen Verdrahtungsfehler. Bekomme nun die gewünschte Antwort von der Karte.
Hey! Passt hier vielleicht nicht ganz, aber ich bekomme auch keine Antwort auf CMD0....kann also meine SD-Karte gar nicht in den SPI-Modus Initialisieren. Hab meinen Code mehr oder weniger von Procyon übernommen und eigentlich auch verstanden. Beobachte die SD Karte am Oszi: SCK = 300kHz CS=high die 10 "dummy Bytes" 0xFF werden gesendet, kommen am DI der SD-Karte an das Command GO_IDLE_STATE wird auch gesendet (0x40,0x00,0x00,0x00,0x00,0x95) hier müsste dann allerdings von der SD-Karte ein 0xFF zurückkommen, aber ich erhalte keine Antwort von der Karte,.... An was könnte das liegen?? Die Pegel an der Karte sind auch bei 3V3 Grüße Oli
>...das Command GO_IDLE_STATE wird auch gesendet...
aber nicht nur einmal, oder? GO_IDLE_STATE muss öfter gesendet werden
bis die karte korrekt drauf antwortet
Wird eigentlich schon mehrmals gesendet: Hier mal der Teil meines Codes:
1 | unsigend char SPI_Transfer_Byte(unsigned char data) |
2 | {
|
3 | unsigned char received=0; |
4 | |
5 | SPDR =data; |
6 | while(!(SPSR&(1<<SPIF))); |
7 | received=PSDR; |
8 | return(received); |
9 | }
|
10 | |
11 | |
12 | |
13 | unsigend char SD_Reset(void) |
14 | {
|
15 | |
16 | PORTB|=(1<<SPI_CS); //setzt CS high |
17 | unsigned char i; |
18 | unsigend char retry; |
19 | unsigned char r1=0; |
20 | |
21 | do
|
22 | {
|
23 | for(i=0;i<10;i++) SPI_Transfer:Byte(0xFF); //sendet dummy bytes |
24 | |
25 | r1 = SD_Send_Command(SD_GO_IDLE_STATE,0); //sende CMD0 |
26 | retry++; |
27 | if(retry>10){return -1;} |
28 | }
|
29 | while(r1 != SD_R1_IN_IDLE_STATE); // 0x01 |
30 | |
31 | |
32 | //.....weiter komm ich gar nicht
|
33 | |
34 | |
35 | |
36 | unsigned char SD_Command(unsigned char cmd, unsigend long arg) |
37 | {
|
38 | |
39 | PORTB &=~(1<<SPI_CS) //CS low |
40 | |
41 | unsigend char r1; |
42 | unsigend char retry=0; |
43 | |
44 | |
45 | SPI_Transfer_Byte(cmd|0x40); |
46 | SPI_Transfer_Byte(arg<<24); |
47 | SPI_Transfer_Byte(arg<<16); |
48 | SPI_Transfer_Byte(arg<<8); |
49 | SPI_Transfer_Byte(arg); |
50 | SPI_Transfer_Byte(0x95); //CRC |
51 | |
52 | |
53 | |
54 | // hier hängt das Programm
|
55 | |
56 | |
57 | while( (r1=SPI_Transfer_Byte(0xFF)) ==0xFF) |
58 | |
59 | if(retry++>8){break;} |
60 | |
61 | PORTB |=(1<<SPI_CS); // CS high |
62 | |
63 | return r1; |
64 | }
|
Also eigentlich will ich nach einmaligem Senden des CMD0, dass die Karte mit 0xFF antwortet (stand glaub im Datenblatt) Über USART hab ich festgestellt, dass da das Programm hängt und wartet bis eben r1 den Wert 0xFF hat.... Ich wäre ja schon froh wenn die SD-Karte überhaupt antworten würde...Aber die DataOut Leitung bleibt low. Und im ProductManual 1.9 von SanDisc steht dass jedes Command eine Antwort bekommt (außer SEND_STATUS) Und es ist ja schon richtig, dass Chip Select der Karte low sein muss während ich CMD0 sende, oder??? Danke schon mal!
/CS muss auf 0 sein. Das ist schon richtig so, weil dann die Karte aktiv ist. Wie sieht denn bei dir die Pegelumsetzung aus? Oder benötigst du keine? Ist ja auch merkwürdig, dass du keine Änderung der MISO-Leitung erhälst. Das gleiche Problem hatte ich ja auch.
Meine Karte spricht jetzt mit mir :-) War doch ein Hardware-Fehler, der Spannungsteiler war zwar richtig berechnet, hab dann aber versehentlich einen Fahlschen Wiederstand eingelötet...aber das sieht man auch so schwer bei den 0603 SMD Teilchen... Die Software stimmt also soweit. Und die Karte befindet sich immerhin im Idle State... Als nächstes will ich CMD1 schicken und als Antwort müsste ich 0x00 bekommen (also für R1) Allerdings sieht mein DataOut Signal nicht wirklich "schön" aus, die Flanke ist nicht wirklich steil... Leider kenn ich mich Hardwaretechnisch nicht soo gut aus, dass ich jetzt wüsste wie ich das beheben könnte. Im Anhang ein Bild... Man sieht wie die letzten beiden 0x00 übertragen werden, dann 0x95(CRC), dann nochmal 0xFF und dann müsste meine Antwort 0x00 kommen. ABer DO geht viel zu langsam auf low....dann fängt das Senden des CMD1 von vorne an Soll ich an DataOut der SD Karte ein Pull-Down Widerstand ranmachen? Bringt das was? Danke schon mal.... Grüße
Ok, das hätte ich geschafft...aber die Antwort der Karte kommt zu spät... Mhhh...
Ich habe zwar keinen Beitrag zu Deiner Frage, allerdings würde mich Dein Meßequipment interessieren :-)
>Soll ich an DataOut der SD Karte ein Pull-Down Widerstand ranmachen? >Bringt das was? Sicher bringt das was. Deine Schaltung zieht unnötig viel Strom, und dein für 5V sowieso schon kritischer Highpegel wird noch kleiner.
schickes Agilent Oszi...nicht mein eigenes versteht sich^^ Bringt mir trotzdem nichts :( Meine SD Karte antwortet einfach zu langsam....
So, ich geb auf für heute... Morgen werde ich noch ein paar andere Karten testen, habe momentan nur eine 1GB Karte von SanDisk hier, aber eigentlich dürfte das ja auch keinen unterschied machen, oder?! Ich mach ja noch nichts mit dem Dateisystem FAT.....nur initialisieren... Vielleicht hat von euch noch jemand eine Idee wiso die Karte mit verzögertem Signal antwortet... Grüße Olivia
Kann es sein, dass die Karte noch nicht ready ist ? Eventuell eine Sekunde warten, bis auf die Karte das erste mal zugegriffen wird.
Morgen! Es funktioniert :-) Hab noch eine 256MB SD-Card gefunden, mit der funktioniert es einwandfrei...(DO kommt rechtzeitig) Ich habe aber leider keine Ahnung wiso es mit der 1GB nicht funktioniert. Dann kann ich mich mal an die nächsten Funktionen Read/Write machen.. Grüße Oli
Gib einfach nach dem CMD0 noch 8 zusätzliche Clocks mit DI=$FF, bevor Du mit R1 weiterfragst. Dann sollte es gehen. Dies wird von einigen Karten benötigt, um das Ausgangsregister zu initialisieren.
Danke, werd ich ausprobieren. Dachte nur das darf ich nicht, weil im Product Manual auch "nur" 2 mal FF gesendet wird und die Antwort dann kommen müsste! Brauch aber zuerst noch einen ATmega mit größerem RAM, weil Schreiben und anschließend lesen geht nicht auf einmal, meine Buffer belegn wohl zu viel Platz...aber bin ja ausgerüstet, hab noch einen ATmega644 in der Schublade :-) Grüße
Generell muß die Anfrage nach R1 solange wiederholt werden, bis die Karte einen Wert ungleich $FF ausgibt, bzw. das obere Bit der Antwort "0" ist. Bei meinen getesteten Karten war dies stets 8 Clocks nach dem CMD0 der Fall. Um dies eindeutig erkennen zu können, sollte DO der Karte bzw. MISO am Controller mit einem PullUp beschaltet werden, da eine frisch eingesteckte Karte den Bus erst nach erfolgreichem CMD0 anschaltet und die Leitung vorher floatet, also auch Low sein kann. Somit kann der Controller überhaupt nichts erkennen. Der interne PullUp reicht völlig (falls vorhanden).
Mhh, irgendwie will das ganze doch nicht. Bin mir zwar ziemlich sicher, dass Softwaremäßig alles stimmt, hier aber nochmal mein Code:
1 | SD_Reset(void) |
2 | {
|
3 | do
|
4 | {
|
5 | for(i=0;i<10;i++) SPI_Transfer_Byte(0xFF); //10 dummy bytes 0xFF |
6 | |
7 | r1= SD_Send_Command(SD_GO_IDLE_STATE,0); //send CMD0 //r1= response |
8 | |
9 | if(retry++>200) {return-1;} |
10 | }
|
11 | while(r1!=SD_R1_IN_IDLE_STATE); |
12 | |
13 | //an dieser stelle befindet sich SD-Card IN IDLE STATE
|
14 | retry=0; |
15 | do
|
16 | {
|
17 | r1= SD_Send_Command(SD_SEND_OP_COND,0); |
18 | |
19 | if(retry++>100) {return-1;} |
20 | }
|
21 | while(r1) // also solange bis r1=0x00 |
22 | |
23 | //An dieser Stelle wäre SD_RESET ERFOLGREICH
|
24 | |
25 | //CRC OFF und SET BLOCKLEN kommen dann noch
|
26 | |
27 | }
|
28 | |
29 | |
30 | //Die SD_Send_Command function
|
31 | |
32 | |
33 | unsigned char SD_Command(unsigned char cmd, unsigend long arg) |
34 | {
|
35 | |
36 | PORTB &=~(1<<SPI_CS) //CS low |
37 | |
38 | unsigend char r1; |
39 | unsigend char retry=0; |
40 | |
41 | |
42 | SPI_Transfer_Byte(cmd|0x40); |
43 | SPI_Transfer_Byte(arg<<24); |
44 | SPI_Transfer_Byte(arg<<16); |
45 | SPI_Transfer_Byte(arg<<8); |
46 | SPI_Transfer_Byte(arg); |
47 | SPI_Transfer_Byte(0x95); //CRC |
48 | |
49 | |
50 | while( (r1=SPI_Transfer_Byte(0xFF)) ==0xFF) |
51 | |
52 | if(retry++>8){break;} |
53 | |
54 | PORTB |=(1<<SPI_CS); // CS high |
55 | |
56 | return r1; |
57 | }
|
58 | |
59 | |
60 | |
61 | |
62 | unsigned char SPI_transfer_Byte(unsigned char data) |
63 | {
|
64 | unsigend char received=0; |
65 | SPDR=data; |
66 | while(!(SPSR&(1<<SPIF))); |
67 | received=PSDR; |
68 | return(received); |
69 | }
|
Was mich jetzt verwirrt ist, dass ich die Richtige Antwort auf CMD0 bekomme (0x01). Die Karte befindet sich also im Idle State. Dann sende ich auf GENAU die GLEICHE weiße CMD1...aber hier erhalte ich nicht das erwünschte r1 von 0x00 Natürlich wird dann CMD1 wieder und wieder gesendet... Die Antworten von der Karte sind immer: 0xC1 0xF0 0xFC 0x05 also immer die gleichen und halt 100mal.... Aber wie gesagt, genau diese Software funktioniert mit der 256MB Karte. Gibt es denn noch andere unterschiede zw. einzelnen Karten? Weil genaue Datenblätter zu den einzelnen SD Karten finde ich nicht. Hab alles aus ScanDisk ProductManual 1.9 für SD Karten. Die 1GB Karte ist ja sogar von ScanDisk Kann es an der Stromaufnahme liegen?? Aber wenn ich mit dem Oszi die Pegel an der Karte messe sind die ok. Kann es am Takt liegen? Zur Init muss der Takt zw. 100KHz und 400KHz ligen. Bei mir sind es 260KHz....gibt es Karten die doch einen anderen brauchen? Kann es sein dass die Karte defekt ist auch wenn ich sie am PC ansprechen kann und auch schon die Defekten Sektoren unter Windows repariert habe?? Und das erste CMD0 ja funktioniert? Danke schon mal....
Kaum hier gepostet hab ich auch schon die Lösung meines Problems :-) Manchmal hilft es doch hier nochmal alles niederzuschreiben....sorry!! hab im Code BEVOR ich CMD1 sende nochmal 10 dummyBytes gesendet (0xFF)... In der Spec steht davon auf S.87 zwar nichts aber was solls. Juhuuu :-) Falls jemand das gleiche Problem hat: (Kann ja nicht sein dass ich die erste bin die das Problem hatte)
1 | //an dieser stelle befindet sich SD-Card IN IDLE STATE
|
2 | retry=0; |
3 | do
|
4 | {
|
5 | for(i=0;i<10;i++) SPI_Transfer_Byte(0xFF); // diese Zeile zusätzlich einfügen!!! |
6 | ...
|
7 | ...
|
8 | ...
|
Bis morgen^^
>unsigned char SD_Command(unsigned char cmd, unsigend long arg)
Was ist ein "unsigend long" ?
Dein Compiler übersetzt das sicher nicht ;)
CMD1 wird von SD-Karten aber gar nicht verwendet - zumindest nicht für die Init. Dazu braucht es CMD8 und ACMD41. Siehe Simplified SD-Card Specification.
Travel Rec. wrote: > CMD1 wird von SD-Karten aber gar nicht verwendet - zumindest nicht für > die Init. Dazu braucht es CMD8 und ACMD41. Siehe Simplified SD-Card > Specification. Das ist so nicht ganz richtig. CMD1 wird von allen MMCs und allen "dicken" SD-Karten unterstützt. Für die "dünnen" (1.4mm) ist CMD1 ein illegales Kommando! Wenn man erstmal den einfachen Weg gehen möchte, ist es in den meisten Fällen OK CMD1 zu benutzen. Sobald aber eine Unterscheidung der Kartentypen erfolgen soll, muss man für SD-Karten ACMD41 benutzen. Hier muss vorher jedoch noch das CMD55 gesendet werden, um auf das "Anwendungsspezifische"-Kommando zugreifen zu können. CMD8 ist nur für die Initialisierung von SDHC-Karten relevant. Gruß Markus
@ Travel Rec.
>CMD1 wird von SD-Karten aber gar nicht verwendet
Das ist falsch. Ältere SD Karten nehmen CMD1 durchaus.
CMD8 mögen die älteren auch nicht. Das geht erst ab
SD Spec. V2.00. Es ist aber immer einen Versuch wert
erstmal ACMD41 statt CMD1 bei SD Karten zu nehmen.
Da stimme ich mit dir überein.
Na okay, ich kann nur von eigenen Erfahrungen berichten. Alle Karten, die bei mir herumliegen, waren CMD1 gegenüber etwas zurückhaltend. CMD8 habe ich zur Differenzierung eingefügt, bislang gibt es auch darauf nur ein "illegal" zurück. Mit ACMD41 ließen sich alle initialisieren. Die Karten stammen aus 2003-2006, HC-SD habe ich nicht mit dabei.
>Was ist ein "unsigend long" ? >Dein Compiler übersetzt das sicher nicht ;) Wiso? Würde er dann nicht meckern? ich habe doch
1 | #include <stdint.h> |
eingebunden...
War ja klar, dass ich schon vor dem nächsten Problem stehe... Will das CID Register auslesen. Schicke das richtige CMD, die SD Karte antwortet auch mit 0xFF und müsste dann 0xFE (STARTBLOCK_READ) senden...
1 | while(SPI_Transfer_Byte(0xFF)!= STARTBLOCK_READ); |
Ich trau ja meinen C-Künsten mittlerweile und auch meinem ATmega ^^ Nur die SD-Karten sind mir suspekt... Kann es sein dass sich das CID Register manchmal nicht auslesen lässt?? Danke schon mal...
Nein, das läßt sich immer auslesen. Da hast Du bestimmt irgendetwas übersehen. Ich lege Dir oben aufgeführtes Dokument an´s Herz. >Schicke das richtige CMD, die SD Karte >antwortet auch mit 0xFF 0xFF ist keine Antwort sondern der Hinweis, daß die Karte noch nicht fertig ist mit Datenschaufeln. Du mußt solange weiterclocken, bis 0xFE kommt. Das kann, je nach Karte, schon ein paar Bytes dauern.
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.