Hallo Leute,
Ich will mit meinem 1Mhz Atmega8 von einer SD-Karte lesen können (:
PD0: = CS
PD1: = DI(Karte)
PD2: = DO(KARTE)
PD3: = CLK
Nun musste ich mir ne SoftwareSPI stricken. Laut Oszi sieht die
Datenausgabe+Clock OK aus.
Ich hänge schon an der Initialisierung.
Ich sende 80 Takte mit CS und DI auf HIGH.
Anschließend send eich folgende 6 Bytes: 0x40 0x00 0x00 0x00 0x00 0x95
mit CS auf LOW.
Darauf folgend sende ich ein Dummibyte und sollte parallel dazu eine
0x01 erhalten ist das richtig?
Ich lese nur Nullen. Wenn ich DO mit 10kOhm auf Vcc (3.3V) lege lese ich
nur 0xFF (der Pegel ist von Anfang an vorhanden!) Habe leider nur ein
altes Röhrenoszi ohne Speicher.
Es gibt keine Interrupts.
Hier meine Sende-/Empfangsroutine.
R16 kriegt das Sendebyte und R20 enthält das Empfangsbyte.
R17 setze ich vorher immer auf 0 (ausser für die (74)oder 80
Anfangstakte)
1
SPIBYTE: ;hier soll ein Byte gesendet oder empfangen werden
2
push r16
3
push r17
4
push r18
5
push r19
6
push r20
7
push r21
8
push r22
9
10
ldi r20,0 ; Inputbyte auf Null setzen (r20 ist das gelesene Byte!)
11
ldi r21,8 ;Bit Downcounter
12
ldi r19,128 ;Shiftbit = das Verglechsbit für die Schiebeoperationen
13
14
15
NBIT: ;hier wird jetzt Bitweise vorrangegangen
16
mov r18,r16 ;lade in r18 das Sendebyte
17
and r18,r19 ;Und-Verknüpfung mit dem Shiftbit
18
19
breq SETZ ;kommt Null raus?
20
SETO: ;Wenn nein...
21
ori r17,0b00000010 ;Setze PB1 (DI)
22
andi r17,0b11110111 ;CLK auf Null (CS)
23
rjmp SETIT
24
SETZ: ;wenn bei dem Bitvergleich(AND) keine Null rauskommt...
25
andi r17,0b11110101 ;CLK (CS) und PB1 (DI) uf null
26
nop ;Zeit schinden
27
SETIT:
28
out PORTD,r17 ;Ausgabe auf PD
29
rcall WBIT20 ;Warte 60 bis 70 µS
30
31
32
in r22,PIND ;lese PORTD ein
33
andi r22,4 ;gucke ob PD2 steht (DO)
34
cpi r22,4
35
brne READZERO
36
READONE: ;wenn ja dann
37
or r20,r19 ;setze in r20 das Shiftbit
38
rjmp READNBIT
39
READZERO:
40
nop ;wenn nicht, dann lasse r20
41
READNBIT:
42
43
lsr r19 ;schiebe das Shiftbit nach rechts (128->64, usw...)
44
45
46
47
48
49
ori r17,0b00001000 ;setze das CLK-Bit
50
out PORTD,r17 ;Ausgabe
51
rcall WBIT20 ;warte wieder
52
dec r21 ;Zähle den Bitzaehler runter
53
brne NBIT ; wenn alle 8 Bit durch sind beende die Routine
54
55
pop r22
56
pop r21
57
pop r19 ;ACHTUNG Um r20 als ausgabebyte zu behalten, wird r19 doppelt gepoppt
> Nun musste ich mir ne SoftwareSPI stricken.
Ja..diese steinalten Prozessoren ohne Hardware SPI. :-)
Aber egal, natuerlich geht es auch erstmal in Software.
> Laut Oszi sieht die Datenausgabe+Clock OK aus.
Du weisst das es vier verschiedene SPI-Mode gibt? Nur einer funktioniert
immer, ein anderer oft und zwei niemals. (mit einem gegebenen Slave)
> Darauf folgend sende ich ein Dummibyte und sollte parallel> dazu eine 0x01 erhalten ist das richtig?
Es ist schon was her das ich sowas programmiert habe, aber wenn ich das
richtig erinnere dann muss eine Karte nicht sofort antworten. Es kann
auch sein das sie erstmal einige Zeit mit 0xff antwortet bis sie bereit
ist. Allerdings antworten viele Karten sofort. Das ist einer der Gruende
warum nicht jede Software mit jeder Karte arbeitet. :-)
Ansonsten empfehle ich dir Elm-schaetzchen:
http://elm-chan.org/docs/mmc/mmc_e.html
Olaf
Noch was...
Ich weiss, es ist nicht ganz unmoeglich, aber eine SD-Karte die immer
mit 512Byte Blockgroesse arbeitet mit einem Prozessor ansprechen zu
wollen der nur 1k internes Ram hat ist ein ganz doller Schmerz im Arsch.
Das wuerde ich mir heute nicht mehr antun.
Olaf
Guck mal von der avrfat32 Library
(https://www.mikrocontroller.net/articles/AVR_FAT32) ab. Die fängt auch
mit 80 Takten an, aber danach beginnt eine Schleife mit ziemlich viele
Wiederholversuchen.
Die angehängte Datei mmc.c wird gilt auch für SD Karten
Danke für die Infos.
Leider kann ich kein C. Und somit werde ich nur wenig Schlau daraus. In
dem C-Code wird nach 100 Fehlversuchen abgebrochen.
Der Link von Olaf ist gut, nebenbei habe ich noch ASM-Code gefunden und
versuche erstmal alles zu verstehen.
MfG Robert
Aber du kannst die Versuche ja erhöhen das mehr als 100 gemacht werden.
Zudem kannst du ja auch wenn x Fehlversuche gemacht wurden eine LED als
Warnung zb Anzeigen lassen.
Jetzt habe ich Veränderungen vorgenommen und das Timing angepasst. Wenn
ich jetzt 0x40 0x00 0x00 0x00 0x00 0x95 sende kriege ich nach
reprpduzierbar 8 Versuchen eine 0x1F als Antwort. Bei Verändern eines
der Bytes, kriege ich keine Antwort. Nur was soll mir 0x1F sagen, oder
lese ich die Bits falsch ein?
Ich habe es gerade mit einer anderen Karte probiert und ich kriege nach
4 Versuchen ein 0xFF. Irgendwas läuft falsch. Ich muss den
Datenverkehr beobachten können.
gute Nacht
> Nur was soll mir 0x1F sagen, oder lese ich die Bits falsch ein?
Weisst du, wie das Protokoll funktioniert? Offensichtlich nicht.
Lerne erstmal, wie die Karte funktioniert und welche
Antworten/Fehlercodes es gibt. Erst danach macht es Sinn, zu
programmieren.
Letztlich muss natürlich die SD-Spezifikation die Grundlage sein, aber
kennen Sie schon
http://elm-chan.org/docs/mmc/mmc_e.html ?
Mir hat dies vor einigen Jahren den Einstieg sehr erleichtert, "einen
Griff an die Sache geschraubt", bildlich gesprochen.
Laut den Infos und den Datenblättern sollte nach CMD00, ein R1 Response
ankommen. Bei dem, abgesehen von dem Flag "Parameter Error", bei mir
alle Flags gesetzt sind. Meine Software SPI muss ich nochmal überdenken.
Der letztgenannte Link ist sehr aufschlussreich. Im Netz findet man fast
nur C Programmbeispiele zur SD-Kartenprogrammierung.
Hier kann man einen Assemblercode finden:
http://www.elektronik-labor.de/AVR/T13contest/sdsound-tn13.htm