Hallo! Ich habe mir eigene Routinen in Assembler geschrieben, um die SD-Karte zu initialisieren. Beim Senden des CMD0 funktioniert das auch, ich bekomme eine 1 zurück, allerdings bekomme ich die auch bei einem CMD1 immer zurück, ich habe es schon in einer Schleife versucht, die über eine halbe Minute lang CMD1 sendet und immer nur 1 empfängt. meine Routine: !ANMERKUNG! in r1 steht immer eine 0 und in r2 immer 255 .equ SD_Addr = 0x60 ;reservierter SRAM Speicher für SD-Karten Befehl SD_SendCommand: ;sendet 6 Befehlsbytes [SD_Addr..SD_Addr+5] sbi PORT_SPI,SEL ;Chip NICHT selektieren out SPDR,r2 ;$ff senden sbis SPSR,SPIF rjmp PC-1 cbi PORT_SPI,SEL ;Chip select lds r16,SD_Addr+0 ;1. Byte lesen out SPDR,r16 ;und senden lds r16,SD_Addr+1 ;nächstes Byte schonmal einlesen sbis SPSR,SPIF ;warten bis erstes fertig gesendet wurde rjmp PC-1 ; out SPDR,r16 ;2. Byte senden... usw.. lds r16,SD_Addr+2 sbis SPSR,SPIF rjmp PC-1 out SPDR,r16 ;3 lds r16,SD_Addr+3 sbis SPSR,SPIF rjmp PC-1 out SPDR,r16 ;4 lds r16,SD_Addr+4 sbis SPSR,SPIF rjmp PC-1 out SPDR,r16 ;5 lds r16,SD_Addr+5 sbis SPSR,SPIF rjmp PC-1 out SPDR,r16 ;6 sbis SPSR,SPIF rjmp PC-1 ;auf Antwort Warten ldi r17,10 ;Zähler für Anzahl der Versuche wr: ;Auf Antwort warten.. out SPDR,r2 ;Takt für eingehendes Byte erzeugen sbis SPSR,SPIF rjmp PC-1 in r16,SPDR ;empfangenes Byte lesen cpi r16,$ff brne weiter ;Byte nicht $ff, dann fertig dec r17 ;Zähler schon bei 0? brne wr ;nein, dann weitere Bytes lesen weiter: ret ;empfangenes Byte in r16, bei Timeout stets $ff Hier die Initialisierungsroutine: SD_Init: sbi PORT_SPI,SEL ;Chip NICHT selektieren ;## 80 Clock-Pulse senden ldi r17,$0a ;Zähler für zu sendende Bytes clkLoop: ldi r16,$ff out SPDR,r16 ;$ff senden sbis SPSR,SPIF rjmp PC-1 dec r17 brne clkLoop ;## CMD 0 senden ldi r16,$40 ;Befehl sts SD_Addr+0,r16 sts SD_Addr+1,r1 ;Adressbytes.. sts SD_Addr+2,r1 sts SD_Addr+3,r1 sts SD_Addr+4,r1 ldi r16,$95 ;Prüfsumme sts SD_Addr+5,r16 rcall SD_SendCommand ;Befehl senden cpi r16,$01 ;Idle-State? breq SD_OK1 ;Ja, dann weiter //**Fehlerbehandlung*** ;Nein, Fehlermeldung ret ;und Abbruch. SD_OK1: ;## CMD 1 senden ldi r16,$41 sts SD_addr+0,r16 ;Befehl sts SD_Addr+5,r2 ;Prüfsumme auf $ff clr r18 ;Zähler für Anzahl der Versuche clr r19 cLoop: rcall SD_SendCommand ;Befehl senden cpi r16,$00 ;Init erfolgreich? breq SD_OK2 ;ja, dann weiter dec r18 ;nein, dann dec(Zähler) brne cLoop dec r19 brne cLoop ; ;Zähler bei 0 angekommen: Fehler... //**Fehlerbehandlung*** ;Fehlermeldung ret ;und Abbruch. SD_OK2: ;Alles OK! ret
Ein funktionierendes Beispiel in Assembler findest Du hier: http://members.aon.at/voegel oder genauer http://members.aon.at/voegel/Downloads/Driver/MMC/MMC.LIB (ist eigentlich für Bascom und MMC gedacht, sollte aber in Deinem Fall keine Rolle spielen)
Hallo Johannes Ich hoffe, du verstehst etwas C. So dürfte es dir nicht mehr schwer fallen deinen Code in Assembler zum laufen zu bringen. Gruss, Daniel //********************************************************************** ******************** // MMC Kontrollieren und korrekt Einstellen //********************************************************************** ******************** int MMC_0_Check (void) { // Karte eingelegt? if (MMC_0_io_CDS()) // Ist eine Karte eingelegt? { MMC_0_SPI_Modus(); // Karte in den SPI Modus umschalten if (MMC_0_Kommando(0x40, 0x00, 0x95) == 0x01) // Karte Reseten { if (MMC_0_Init()) // Karte initialisieren { // Karten CRC ausschalten if ((MMC_0_Kommando(0x7B, 0x00, 0x00) == 0x00)) { // Karten Blocklaenge 512 if ((MMC_0_Kommando(0x50, 0x0200, 0xFF) == 0x00)) { MMC0_Status = MMC_CARD_OK; return TRUE; } } } } } return FALSE; } //********************************************************************** ******************** // Karte in den SPI Modus umschalten //********************************************************************** ******************** void MMC_0_SPI_Modus (void) { MMC_0_io_card_select(MMC_CARD_DESELECT); // Damit der User mehr Zeit hat, die Karte in den // Kartenslot zu schieben for (int x = 0;x < 40000; x++) {spi0_send_receive (0xFF);} } //********************************************************************** ******************** // MMC Initialisieren //********************************************************************** ******************** int MMC_0_Init (void) { int c; for (c = 0; c < 0xFF; c++) { if (MMC_0_Kommando(0x41, 0x00, 0xFF) == 0x00) { return TRUE; } } return FALSE; } //****************************************** // Kommandos an die MMC senden //****************************************** int MMC_0_Kommando (unsigned int Kommando, unsigned int Adresse, unsigned int CRC) { int out; MMC_0_io_card_select(MMC_CARD_SELECT); spi0_send_receive (0xFF); spi0_send_receive (Kommando); spi0_send_receive (Adresse >> 24); spi0_send_receive (Adresse >> 16); spi0_send_receive (Adresse >> 8); spi0_send_receive (Adresse); spi0_send_receive (CRC); spi0_send_receive (0xFF); out = spi0_send_receive (0xFF); MMC_0_io_card_select(MMC_CARD_DESELECT); return out; }
Ja, ich kann den Code gut nachvollziehen, finde aber leider keine Unterschiede in der Vorgehensweise... habe mal weiter getestet: wenn man keine karte einsteckt, dann bekomme ich FF zurück leider kann ich an stelle von CMD0 alles mögliche senden: andere Befehlscodes oder eine Falsche Prüfsumme liefert trotzdem den wert 1 mein spi ist folgendermaßen initialisiert: ldi r16,(1<<SPE)|(1<<MSTR)|(1<<SPR0);MASTER, Prescaler: 16 out SPCR,r16
hallo, vielleicht schon zu schnell die initialisierung!!! ldi temp1, 0x53 out SPCR, temp1 ldi temp1, 0x00 out SPSR, temp1 ;vorteiler 128 wenns dann nit klapppt muss man deine routine mal anschauen oder deine hardwarwe!!
Die eingänge der Karte sind alle über Spannungsteiler mit dem ATMega8 verbunden. Data-out liegt direkt an. Versorgt wird die Karte über einen Spannungsregler (3.3V) Ich habe alles nochmal ausgiebig getestet: Wenn man die Karte rinsteckt, und die 80 clock-Pulse gesendet hat und den CMD 0 gesendet hat, dann bekommt man 1 als Rückgabewert. Wenn ich nun einen Falschenbefehlscode sende, bekomme ich eine 5 zurück. Das würde bedeuten, das "Illegal Command"-Bit und das "Idle" bit sind gesetzt -> übertragung macht keine Probleme. jedoch das Senden des CMD1 sendet immernoch eine 1 zurück, egal wie oft ich es wiederhole. Zum Ausprobieren habe ich 2 verschiedene Karten. Jetzt das komische: einmal habe ich es geschafft! es kam schon nach kurzer Zeit eine 0 zurück! auch wenn ich jetzt einen ungültigen befehl sende, bekomme ich nur noch eine 4 zurück, also das "Idle" Bit ist tatsächlich gelöscht. Dann hab ich die Schaltung neu in betrieb genommen, also Strom aus,an und schon stand ich vor dem alten Problem..
hallo, wenn du willst kann ich dir mal meine SD/MMC routinen (auch in asm) geben und du kannst testen oder erlesen worans liegt. gruss
Benutz mal anständige Pegelkonverter für MISO,MOSI,SCK,CS. Ich hab mittlerweile 10 verschiedene MMC/SD am laufen. Von 16MB bis 4GB. Probleme wie du sie hast kenne ich gar nicht.
holger wrote:
> Benutz mal anständige Pegelkonverter für MISO,MOSI,SCK,CS.
Hat er doch. Ich benutze bei meinem AVRNAS auch Spannungsteiler, und das
Dingen fluppt sehr gut...
Ich kann mich nicht mehr genau erinnern, aber mein C-Code der
Initialisierung sieht so aus:
1 | #define CMD0 (0x40+0)
|
2 | #define CMD1 (0x40+1)
|
3 | |
4 | void spi_putb(uint8_t b) |
5 | {
|
6 | |
7 | SPDR0 = b; |
8 | while(!(SPSR0 & (1<<SPIF0))); |
9 | }
|
10 | |
11 | uint8_t sd_cmd(uint8_t cmd, uint32_t arg) |
12 | {
|
13 | uint8_t temp; |
14 | |
15 | spi_putb(cmd); |
16 | spi_putb((uint8_t) (arg >> 24)); |
17 | spi_putb((uint8_t) (arg >> 16)); |
18 | spi_putb((uint8_t) (arg >> 8)); |
19 | spi_putb((uint8_t) (arg)); |
20 | spi_putb(0x95); |
21 | |
22 | while((temp = spi_getb()) == 0xFF); |
23 | |
24 | return temp; |
25 | }
|
26 | |
27 | void sd_init() |
28 | {
|
29 | //....
|
30 | //select
|
31 | while(sd_cmd(CMD0, 0) != 1); |
32 | while(sd_cmd(CMD1, 0) != 0); |
33 | //deselect
|
34 | //...
|
35 | }
|
Ich sende CMD0 also so oft, bis das Responsebyte stimmt. Ich kann mich glaube ich daran erinnern, dass die Karte in der ersten Schleife auch einen Moment verharrte. Vielleicht mal ausprobieren.
>Hat er doch. Ich benutze bei meinem AVRNAS auch Spannungsteiler, und das >Dingen fluppt sehr gut... Schön für dich. Was macht das Teil bei 8MHz SPI ? Bringen alle SD/MMC wirklich mindestens 3V am Ausgang damit der AVR das auch noch als High erkennt ?
holger wrote: > Schön für dich. Was macht das Teil bei 8MHz SPI ? Läuft. Als Spannungsteiler benutze ich 1k8/3k3 Ohm > Bringen alle SD/MMC wirklich mindestens 3V am Ausgang > damit der AVR das auch noch als High erkennt ? Jo.
>> Bringen alle SD/MMC wirklich mindestens 3V am Ausgang >> damit der AVR das auch noch als High erkennt ? >Jo. Sorry, das wusste ich nicht ;) Welche ALLE SD/MMC schaffen das bei dir ?
holger wrote:
> Welche ALLE SD/MMC schaffen das bei dir ?
Versteh ich jetzt nicht. Wenn die Betriebsspannung 3,3V ist, dann wird
ein High-Pegel heutzutage auch etwa um 3,3V liegen...
>Versteh ich jetzt nicht. Wenn die Betriebsspannung 3,3V ist, dann wird >ein High-Pegel heutzutage auch etwa um 3,3V liegen... Versteh ich jetzt auch nicht, das es immer wieder Probleme mit diesen Primitiv-Schaltungen gibt. Das ist mir völlig unverständlich !? Meine positiv Liste mit richtigen Pegelkonvertern: MMC === Canon 16MB extrememory 32MB SanDisk 128MB MMC plus extrememory 256MB PREMIUM MAXflash 1GB MMC PLUS SD == Mini SD Nokia 64MB SD takeMS 128MB SD Toshiba 128MB SD SanDisk 256MB SD hama 256MB SD NoName 60x 512MB SD Qimonda 512MB SD Kingston 512MB SD Stone 1GB SD extreMEmory 1GB PERFORMANCE SD CnMemory 1GB Firstclass Silver 60x SD memorex 2GB SD NoName 2GB XF00068850 (Reichelt) SDHC Toshiba 4GB 10 Stück davon habe ich selbst ausprobiert, der Rest wurde als positiv gemeldet.
> Bringen alle SD/MMC wirklich mindestens 3V am Ausgang > damit der AVR das auch noch als High erkennt ? Ich hatte in meinem ersten Layout ärgerlicherweise auch in der MISO - Leitung einen Spannungsteiler drin, hat nicht die Bohne gestört, hat trotzdem einwandfrei funktioniert. :)
ich bin grad auch dabei ne sd/mmc karte anzusteuern. außer der karte und nem resettaster hängt im prinzip nix am µc. steck ich die karte rein und drücke reset bekomme ich auf den initbefehl auch ne falsche antwort. erst nach dem zweiten reset läuft alles ohne problem. keine ahnung warum und ich hab schon alles ausprobiert um das zu ändern. ohne erfolg. das mit den pegelwandlern halte ich für nicht notwendig. bei mir läuft das mit spannungsteiler und 10Mhz SPI-frequenz ohne probleme
@fubu1000: Ja, das wäre Nett, wenn du mir dein Assemblerprogramm mal zum Testen geben könntest. @Thilo M.: Bei mir ist der MISO Eingang direkt mit der Karte verbunden. Ich glaube nicht, dass das Problem in meiner Software zu suchen ist, da ich ja Befehle senden kann und auch die zu erwarteden Antworten von der Karte bekomme. Das Problem ist nur, dass die Karte nicht aus ihrem Idle-Zustand heraus will. Ich benutze SD-Karten der Firma Kingston und Jenoptik
>Bei mir ist der MISO Eingang direkt mit der Karte verbunden.
Bei mir jetzt auch ;)
Wollte nur sagen dass der µC-Eingang schon recht kleine Spannungen als
high erkennt. Muss mal testen wo die Grenzen sind (ob's Datenblatt recht
hat) ..
gast wrote: > ich bin grad auch dabei ne sd/mmc karte anzusteuern. außer der karte und > nem resettaster hängt im prinzip nix am µc. steck ich die karte rein und > drücke reset bekomme ich auf den initbefehl auch ne falsche antwort. > erst nach dem zweiten reset läuft alles ohne problem. keine ahnung warum > und ich hab schon alles ausprobiert um das zu ändern. ohne erfolg. > das mit den pegelwandlern halte ich für nicht notwendig. bei mir läuft > das mit spannungsteiler und 10Mhz SPI-frequenz ohne probleme Wie schon gesagt, es kann sein, dass man CMD0 in einer Schleife so oft senden muss, bis die SD Karte aus dem Idle heraus ist. Ich weiß es aber nicht mehr, es stand aber in meinem Code drin (oben). Und das beste: Dieser Code funktioniert.
@simon küppers: bei mir aber nicht. ich hab CMD1 in ner schleife, so dass es öfter gesendet wird, und diese schleife schonmal bis 100 gesetzt. immer das gleiche, erst nach dem zweiten reset gehts. vieleicht liegts an der karte
Hallo Euer Initialisierungsproblem liegt darin, dass z.T. selbst die gleiche Karte z.T. unterschiedliche Zeiten hat beim initialisieren. Entweder nimmt man es sehr gemütlich, oder man wartet so lange, bis der Befehl die korrekte Antwort zurück gibt. In der Funktion MMC_0_Init(void) (C Code fast am anfang der Seite) kannst du sehen, dass max. 255 mal das Kommando gesendet wird. Da kam es schon mal vor, dass der Befehl 7mal, 1mal, 30mal aufgerufen wird. Genauso gibt es Fehler, wenn du eine Card detect Funktion einbaust und man die Karte zu initialisieren beginnt, wenn der Benützer gerade die Karte einlegt. Da heisst es ebenfalls Geduld. Entweder nicht sofort die Karte zu Initialisieren oder man lässt ein paar dummy Daten länger über den SPI zur Karte senden um die Karte in den SPI Modus zu schalten. Beides bewirkt eine Verzögerung. Sollte die initialisierung fehlschlagen, unbedingt mit dem SPI Modus umschalten wieder beginnen. Gasz billige Karten, schaffen ab und zu nicht mal das und dann kann man lange versuchen zu initialisieren. Sollte jemand auch ein Filesystem verwenden, dann die Karte auf keinen Fall mit Wi***ws Formatieren. Nimm Li**x, dann ist auch ein rechter MBR (Master Boot Record) drauf. Sonst gibt es so Geduldspiele wie: such den Anfang der Partition. Je nach OS Version ist es etwas besser oder schlechter. Gruss, Daniel
hallo johannes, sry das ich mich jezt erst wieder melde, hatte viel zu tun. wenn du noch interressiert bist, dann schreib deine email addresse hier ins forum. dann kann ich dir den code schicken und womöglich weiterhelfen!!! gruss
@Daniel Schwab: Ich habe versucht den Befehl CMD1 über 65536 mal zu senden und es kommt nichts bei heraus.. @fubu1000: meine EMail Adresse : Johannes-Thull@web.de
Hallo, hab ein ganz ähnliches Problem: Die hardwaremäßige Anbindung scheint zu funktionieren (zumindest lässt sich den Signalen gut hinterheroszillographieren), aber: Auf CMD0 antwortet meine SD-Karte (1GB, Platinum, quasi NoName von Reichelt) mit 00000101, also "Idle" und "Illegal Command". Sowohl das ausgehende CMD0, als auch die Antwort kann ich mit dem Oszillographen beobachten und habe die Bits von Hand nachgezählt - die stimmen mit dem überein, was mein Atmega168 behauptet. Habt Ihr einen Verdacht, woran es liegen könnte, dass die Karte nicht mag? Danke Mathias
@Matze: Um CMD0 zu senden musst du $40 an die SD karte senden, für CMD1 $41..usw! hast du das bedacht?
Hi! ich hatte mal das selbe Problem nachdem ein falscher Befehl ,durch ne kalte Lötstelle,gesendet wurde. Aus Verzweiflung habe ich sie in den PC gesteckt, die Eigenschaften und den Inhalt betrachtet -nichts auffälliges. Danach in meinen Kartenhalter und was soll ich sagen, die Karte geht heute noch->????? Zu den Pegelkonvertern, manche Karten haben so schwache Ausgänge das der AVR, wenn an 5V, die Signale manchmal nicht sauber empfängt. Seit ich einen drinn habe, habe ich auch keine Probleme mehr. Was mir an deinem Code auffällt, du sendest kein Dummybyte bevor du die Daten empfangen willst. Auch ans Ende jeder Übertragung gehören min 8 Takte besser 16. Der SPI Takt darf, bis CMD1 ok ist, nicht über 400kHz sein. Viel Erfolg, Uwe
@ uwe >Was mir an deinem Code auffällt, du sendest kein Dummybyte bevor du die >Daten empfangen willst. Auch ans Ende jeder Übertragung gehören min 8 >Takte besser 16. Meinst du Dummybytes wenn CS High ist ? Die braucht man nicht.
aha, da sagen die SD Card Datenblätter was anderes. Ist das jetzt von dir nur eine Feststellung aus der Praxis oder hats du dazu offizielle Datenblätter die das besagen ? Gruß Hagen
>aha, da sagen die SD Card Datenblätter was anderes. Ok, beim Init vor CMD0 muss man das natürlich. Danach aber nicht mehr. An welcher Stelle sagen die Datenblätter das man bei CS High noch takten MUSS ? Es ist wohl eher das man takten KANN ! SPI halt. Alles andere wäre bei einer SPI Schnittstelle schlicht Unsinn. >Ist das jetzt von dir nur eine Feststellung aus der Praxis oder >hats du dazu offizielle Datenblätter die das besagen ? Das ist eine Feststellung aus der Praxis. Siehe oben. 18 verschiedene getestete Karten und keine Probleme wenn man bei CS High KEINE Dummys sendet. Hast du eine Karte wo es nicht so ist ? Verkauf sie mir !
Ganz einfach, die SD Karte ist vom Takt abhängig, der Takt steuert die interne FSM. Werden zb. Daten geschrieben so benötigt die Karte einen Takt und der muß par Zyklen nach dem Senden des Datenblockes weiterlaufen. So habe ich die Datenblätter interpretiert. In meiner mmcSendCommand() Funktion sende ich bei deaktiviertem CS der Karte erstmal 8 Bits, danach aktiviere ich die SD Karte und sende den Kommandoblock. Beim Warten auf das Response sende ich weiter immer 0xFF und warte auf die Antwort der SD Karte. Also VOR und NACH dem Kommandoblock lege ich schon einen Takt für die Karte an. Und.. das funktioniert bei mir mir mit allen Karten die ich testen konnte, ohne die üblichen Fehler bei anderen Libs. Gruß Hagen
1 | #ifdef MMC_CALC_CRC7
|
2 | uint8_t mmcCRC7(uint8_t crc, uint8_t data) { |
3 | |
4 | crc ^= data; |
5 | unsigned char poly = 0x89; |
6 | for (unsigned char i = 8; i > 0; i--) { |
7 | if ((crc & 0x80) != 0) crc ^= poly; |
8 | crc <<= 1; |
9 | }
|
10 | return(crc); |
11 | }
|
12 | #endif
|
13 | |
14 | uint8_t mmcCommand(uint8_t command) { |
15 | |
16 | return(mmcCommandParam(command, 0, 0)); |
17 | }
|
18 | |
19 | uint8_t mmcCommandExpected(uint8_t command, uint16_t expected) { |
20 | |
21 | return(mmcCommandParam(command, 0, expected)); |
22 | }
|
23 | |
24 | uint8_t mmcCommandParam(uint8_t command, uint32_t address, uint16_t expected) { |
25 | |
26 | uint8_t result; |
27 | uint8_t data = 0xFF; |
28 | |
29 | mmcDisable(); // CS=HIGH |
30 | mmcSend(data); |
31 | |
32 | uint8_t crc = 0; |
33 | #ifdef MMC_CALC_CRC7
|
34 | crc = mmcCRC7(crc, command); |
35 | crc = mmcCRC7(crc, (uint8_t)(address >> 24)); |
36 | crc = mmcCRC7(crc, (uint8_t)(address >> 16)); |
37 | crc = mmcCRC7(crc, (uint8_t)(address >> 8)); |
38 | crc = mmcCRC7(crc, (uint8_t)(address)); |
39 | crc = crc | 1; |
40 | #else
|
41 | crc = 0x95; |
42 | #endif
|
43 | |
44 | |
45 | mmcWait(); |
46 | mmcEnable(); |
47 | for (uint8_t i = MMC_COMMAND_TRIALS; i > 0; i--) { |
48 | mmcSend(command); |
49 | mmcWait(); |
50 | mmcSend((uint8_t)(address >> 24)); |
51 | mmcWait(); |
52 | mmcSend((uint8_t)(address >> 16)); |
53 | mmcWait(); |
54 | mmcSend((uint8_t)(address >> 8)); |
55 | mmcWait(); |
56 | mmcSend((uint8_t)(address)); |
57 | mmcWait(); |
58 | mmcSend(crc); |
59 | mmcWait(); |
60 | |
61 | for (uint8_t j = MMC_RESPONSE_TRIALS; j > 0; j--) { |
62 | mmcSend(data); |
63 | mmcWait(); |
64 | result = mmcRead(); |
65 | if ((result & 0x80) == 0) break; |
66 | }
|
67 | |
68 | if ((result >= (uint8_t)(expected >> 8)) && (result <= (uint8_t)(expected))) break; |
69 | |
70 | mmcDisable(); |
71 | mmcSend(data); |
72 | for (uint8_t j = MMC_COMMAND_DELAY -1; j > 0; j--) { |
73 | mmcWait(); |
74 | mmcSend(data); |
75 | }
|
76 | mmcWait(); |
77 | mmcEnable(); |
78 | }
|
79 | return(result); |
80 | }
|
81 | |
82 | uint8_t mmcInit(void) { |
83 | |
84 | MMC_PORT |= (1 << MMC_CS); |
85 | MMC_DDR |= (1 << MMC_CS) | (1 << MMC_SCLK) | (1 << MMC_MOSI); |
86 | MMC_DDR &= ~(1 << MMC_MISO); |
87 | SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0); |
88 | SPSR = 0; |
89 | |
90 | uint8_t result = mmcCommandExpected(0x40, 0x0101); |
91 | if (result <= 0x01) { |
92 | for (uint8_t i = 20; i > 0; i--) { |
93 | result = mmcCommand(0x41); |
94 | if (result != 0x01) break; |
95 | }
|
96 | if (result == 0x00) { |
97 | SPCR = (1 << SPE) | (1 << MSTR); |
98 | SPSR = (1 << SPI2X); |
99 | #ifdef MMC_CALC_CRC7
|
100 | result = mmcCommandParam(0x7B, 1, 0x0000); // activate CRC checking |
101 | #endif
|
102 | if (result == 0) { |
103 | result = mmcReadCSD(MMC_Buffer); |
104 | |
105 | }
|
106 | }
|
107 | }
|
108 | mmcDisable(); |
109 | return(result); |
110 | }
|
>Ganz einfach, die SD Karte ist vom Takt abhängig, der Takt steuert die >interne FSM. Werden zb. Daten geschrieben so benötigt die Karte einen >Takt und der muß par Zyklen nach dem Senden des Datenblockes >weiterlaufen. Nein, muss er nicht. Das ist bei SPI NICHT erforderlich. >Und.. das >funktioniert bei mir mir mit allen Karten die ich testen konnte, ohne >die üblichen Fehler bei anderen Libs. Welche Karten ? Hast du eine Liste ? Meine Lib ist keine der üblichen. Siehe Anhang. Lesen und schreiben von MMC/SD macht OHNE diese Dummybytes keine Probleme. Bei immerhin 18 Karten. Da sind ziemlich alte Dinger dabei und moderne SDHC Karten.
Stop mal in MMCCommand hast du 1.) SPI_WRITE(DUMMY_WRITE); noch bevor du das Commando Byte sendest und dabei schon CS=LOW !? Das widerspricht den SD Card Spezifikationen, also das CS schon LOW ist beim DUMMY_WRITE. 2.) du wartest auf das Response Byte par Sourcezeilen später. Da sendest du auch solange das DUMMY_BYTE bis du ein Response bekommst Und davon rede ich die ganze Zeit. Du musst vor und nach dem Senden des Commandos auf die SD Karte warten und dabei muß die SD Karte weiterhin getaktet werden, weshalb auch in deinen Code, weiterhin getaktet wird. Und auch bei deiner Funktion MMCReadSector machst du das gleiche ! Auch da taktest du die SD Karte solange bis ein Timeout entsteht oder das gültig Response der SD Karte empfangen wurde. Diese Dummy Writes sind essentiell nur dazu da das die FSM der SD Karte weiterarbeiten kann. Denn die SD Karte hat keinen eigenen Takt aber ehrwohl einen Prozessor, sogar Kryptoprozessor. Der braucht nen Takt ;) Nicht verärgert sein, aber ist das der Source den du anhängen wolltest ? "Kennst du deinen Source ?" könnte man versucht sein zu fragen ;=) Gruß Hagen
>Welche Karten ? Hast du eine Liste ?
Nöö kann aber versuchen eine zu machen, dazu muß ich nur alle Karten
einsammeln. Auf alle Fälle einige Nonames von eBay, überwiegend SanDisk
ab 16Mb aufwärts und par Kingsten (sind doch die grünen) und
ExtremMemory, die ich aber nur noch für die DigiCam benutzen werde, wäre
mir zu schade.
Ach und Nomame MMC Karte, die habe ich geschrottet, bei meinen ersten
Tests ;)
Es ist aber kein Indiz das eine Library sauber funktioniert. Ich halte
mich an die Datenblätter des Standards und das hat gereicht.
So, jetzt kommt die Frage ob ich das Datenblatt noch habe. Sicherlich,
muß aber erstmal suchen immerhin war das vor 2 Jahren.
Gruß hagen
Absatz 4.5. Clock Control im ProdManual von Sandisk Version 1.9. Anhängen werde ichs hier nicht, es ist eh schon schwierig legal an diese Datenblätter zu kommen. In meinem Code sende ich bei CS=HIGH 8 Bits bevor ich das eigentliche Kommando sende. Laut Spezifikation sollten diese 8Bits aber nach eienr Aktion gesendet werden. Das spare ich mir. D.h die besagten 8 Bits bei CS=HIGH die man der Karte nach einer Sequenz senden sollte mache ich VOR dem senden des nächsten Kommandos. Gruß Hagen
@ Hagen
>"Kennst du deinen Source ?" könnte man versucht sein zu fragen ;=)
Scheinbar nicht :(
Du hast natürlich recht. Ich hab Unsinn erzählt.
Dieses Dummy vor dem Kommando hatte ich mal entfernt.
Funktioniert bei MMC und einigen noname SD übrigends hervorragend.
Hab ich gerade noch mal ausprobiert. Bei ner Sandisk und Toshiba SD
gehts so gar nicht. Irgendwann muss ich das Dummy wieder eingebaut
haben. Und dann sofort vergessen.
Es funktioniert aber bisher problemlos das Dummy Byte zu senden
ohne die CS Leitung nach der Response auf High zu ziehen.
Vieleicht sollte man nach der Response CS aber besser doch
auf High ziehen, um Ärger mit empfindlichen Karten zu vermeiden.
Meine Karten tun es auch so, aber ich schreibs mir mal auf !
Danke für den Tritt in den Hintern ;)
Holger
Ja CS ist anscheindend egal, es zählen nur die Takte auf der Clockleitung. Allerdings sollte Dummy=0xFF sein. Laut SD Spec, irgendso ein inoffizielles Datenblatt, sollte aber CS=HIGH sein, um unnötige Fehlcodierungen des Commandobytes zu verhindern. Gruß Hagen
@Johannes: Ja, dass jeder Befehl im Prinzip |0x40 genommen werden muss ist beachtet - hab es mit den Quellcodes von Ulrich Radig und Roland Riegel ausprobiert (die tun das ja alles korrekt und sind sehr gut nachvollziehbar). Hab in einem Handy noch ne RS-MMC gefunden, die freundlich und zufrieden antwortet - es scheint also ein Problem mit genau dieser SD-Karte zu geben - hab mir erstmal noch eine Sandisk-Karte bestellt und werde schauen, was die so macht. Wenn die auch nicht klappt, dann muss ich wohl mal drüber nachdenken, ob ich ein Hardwareproblem habe (Spannungsversorgung oder sowas - die RS-MMC sind ja im möglichen Spannungsbereich etwas toleranter...). Oder fällt Euch noch irgendwas ein? Mathias
Hallo, habe demnächst auch vor erste Versuche mit SD-Karten zu machen. Eine Frage dazu: Man ließt immer wieder von SD-Karten die mit bestimmten Sourcecodes nicht funktionieren usw. Gibt es eigentlich Sourcecode der mit allen Karten arbeitet? Oder anders ausgedrückt: Gibt es auch kommerzielle Software (in Digi-Cams, Kartenlesern usw.) die nicht mit allen SD-Karten funktioniert? Ciao Chris
Ich habe nun mal eine Karte der Marke "Intenso" versucht, und habe die Karte erfolgreich initialisiert. Deshalb muss es einfach an den Karten liegen und nicht an meiner Software. @Chris: Ich denke der Königsweg für SD-Karten auszulesen geht über den normalen SD-Karten-Bus. Ich denke nicht, dass die SD-Reader an meinem Pc über die langsamere SPI-Schnittstelle kommunizieren, aber das wäre dann noch auszuprobieren ;-)
Ich habe bis jetzt keine SD- oder MMC-Karte, die bei meiner Hard- und Software nicht lief. Ich habe aber keine Lust, mir von allen Herstellern alle Typen zu Kaufen.
Hallo, die "normalen" SD-Karten kann ich initialisieren. Hab den Assembler-Code, hoffentlich halbwegs verständlich, hier veröffentlicht. Beitrag "SD-Karte Initialisierung Read Write FAT ATmega8 (Assembler)" Jedoch eine 4GB (SDHC) Karte lässt sich nicht initialisieren. CMD0 wird korrekt beantwortet aber bei ACMD41 bzw. CMD1 lautet die Antwort immer x01. Werden die SDHC Karten anders initialisiert ? Bernhard
hallo, unten in de pdf sind die zeiten beschrieben für das ansprechen der mmc-karte http://www.mikrocontroller.net/attachment/24687/spitiming.pdf wer kann mir diese werte unten mal erläutern, verstehe die nicht ganz mit fixed und multiples usw. 8x4= fixed multiple of 8 clocks 8x= multiples of 8 clock 8 =number of dummy clocks 8 =number of clocks danke mfg
> 8x4= fixed multiple of 8 clocks Es ist eine feste Anzahl an Tackten vorgeschrieben und zwar muss die Anzahl ein vielfaches von 8 sein. In diesem Fall 8 x 4 = 32 > 8x= multiples of 8 clock Die Tackt anzahl muss ein vielfaches von auch sein. Wieviel mal 8 Tacke ist egal. > 8 =number of dummy clocks 8 Tackte bei denen aber keine Daten gesentet oder empfangen werden. > 8 =number of clocks Feste Anzahl von 8 Tackten.
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.