Forum: Mikrocontroller und Digitale Elektronik SDKarte SPI gibt seltsame Antwort


von Leo M. (crashc)


Angehängte Dateien:

Lesenswert?

Hallo,

ich versuche seit einigen Tagen eine SD-Karte mit einem ATMega8 über 
Hardware SPI anzusteuern.
Ich habe bereits mehrere SD-Karten ausprobiert. Der ATMega8 läuft mit 
einer Frequenz von 9,216 MHz. (Der SPI-Vorteiler auf 128 eingestellt)

Meine Idee bisher war:
1. uC startet.
2. einige ms warten (um der SDKarte Zeit zum initialisieren zu geben)
3. einige Male die SCK-Leitung Pulsen (bzw. 0xFF senden)
4. CMD0 senden (0x40,0x00,0x00,0x00,0x00,0x95)
5. auf ein 0x01 der SD-Karte warten (bzw. 0xFF senden)

Diesen ASM-Sourcecode habe ich mal unten angehängt. (Er erzielt kein 
Resultat)

Wenn ich mir die Rückgabe der SD-Karte per UART an den PC senden lasse 
erhalte ich folgendes:
bei Schritt 3: 0x00 ...
bei Schritt 4: 0x00 ...
bei Schritt 5: 0x3F 0xE0 0x3F 0xFF 0xFF 0xFF...

Das Ergebnis bei Schritt 5 entspricht ja keinem "R1 Response", da ich 
dort ja nur ein Byte zurück erhalten würde. Was also antwortet mir die 
SD-Karte dort? Liegt es vielleicht an meiner "Hardware"? Ich habe einen 
Schaltplan meines Pegelwandlers beigefügt.

Ich wäre wirklich froh, wenn mir jemand bei der Interpretation dieser 
Daten helfen könnte oder auch Ideen/Verbesserungen geben, die zur Lösung 
beitragen könnten. Ich besitze leider kein Oszilloskop mit dem ich den 
MISO-Pegel betrachten könnte.

MfG Leonardo

PS:

main.asm
1
.include "m8def.inc"
2
3
.org 0x000
4
  rjmp main
5
6
.include "spi.inc"
7
8
.def temp  = R16
9
.def com_length = R17
10
.def temp2 = R18
11
.def temp3 = R19
12
13
14
15
main:
16
  ldi temp, HIGH(RAMEND)
17
  out SPH, temp
18
  ldi temp, LOW(RAMEND)
19
  out SPL, temp
20
21
  rcall InitSPI
22
23
  ; Ein paar Millisekunden warten
24
  ldi temp, 0xFF
25
  ldi temp2, 0xFF
26
  ldi temp3, 0x10
27
28
lp:
29
  dec temp
30
  brne lp
31
  dec temp2
32
  brne lp
33
  dec temp3
34
  brne lp
35
36
  ; SS auf LOW ziehen
37
  cbi PORTB, PB1
38
39
  ; SCK 255 mal pulsen
40
  ldi temp, 255
41
pre:
42
  ldi sendbyte, 0xFF
43
  rcall SendSPI
44
  dec temp
45
  brne pre
46
47
  ; CMD0 senden
48
49
  ldi ZH, HIGH(command0*2)
50
  ldi ZL,  LOW(command0*2)
51
52
  ldi com_length, 6
53
loop:
54
  lpm
55
  mov sendbyte, R0
56
  rcall SendSPI
57
  adiw ZL, 1
58
  
59
  dec com_length
60
  brne loop
61
62
  ; Auf Antwort warten
63
endl:
64
  ldi sendbyte, 0xFF
65
  rcall SendSPI
66
  
67
  cpi sendbyte, 0x01  // 0x01 = successful
68
  breq success
69
70
  rjmp endl
71
72
success:
73
  ldi temp, 0xFF
74
  out DDRD, temp
75
  out PORTD, temp
76
  rjmp success
77
78
79
80
command0:
81
  .db 0x40, 0x00, 0x00, 0x00, 0x00, 0x95


spi.inc
1
.include "m8def.inc"
2
3
.def sendbyte = R21
4
5
6
InitSPI:
7
  ; Set MOSI, SCK and PB1 (connected to SS) as Output
8
9
10
  ldi temp , (1<<PB3) | (1<<PB5) | (1<<PB2) | (1<<PB1)
11
  out DDRB, temp
12
13
  
14
  ; SS auf HIGH ziehen
15
  sbi PORTB, PB1
16
17
18
  ; Enable SPI, Master, CLK to 1/128 frq, Mode 0
19
20
  ldi temp, (1<<SPE) | (1<<MSTR) | (1<<SPR1) | (1<<SPR0)
21
  out SPCR, temp
22
23
  ret
24
25
  
26
SendSPI:
27
  out SPDR, sendbyte
28
WaitSPI:
29
  sbis SPSR, SPIF
30
  rjmp WaitSPI
31
  in sendbyte, SPDR
32
  ret

von Bampi (Gast)


Lesenswert?

Uiii. Da wird dir keiner Weiterhelfen.
Lerne C und setze eine fertige Lib ein.

von Sascha W. (sascha-w)


Angehängte Dateien:

Lesenswert?

Hallo Leo,

ich häng dir mal meine mmc.inc an, das hab ich mal aus dem C-Code von 
Ulrich Radig übersetzt und tut schon seit Jahren seinen Dienst.

Sascha

von holger (Gast)


Lesenswert?

>Ich besitze leider kein Oszilloskop mit dem ich den
>MISO-Pegel betrachten könnte.

Schade, dann könntest du vieleicht sehen wie schei..e
deine Pegelwandler sind.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Mir scheint die Pegelwandlerschaltung sehr windig für 10MHz SPI Takt...

Probiers mal mit 1MHz.

Es ist übrigens echt unglaublich umständlich, eine solche Schnittstelle 
ohne Oszi in Betrieb zu nehmen. Du weißt ja überhaupt nichts über die 
Signalqualität.

von Jim M. (turboj)


Lesenswert?

Leo M. schrieb:
> ; SS auf LOW ziehen
>   cbi PORTB, PB1
>
>   ; SCK 255 mal pulsen
>   ldi temp, 255
> pre:
>   ldi sendbyte, 0xFF
>   rcall SendSPI
>   dec temp
>   brne pre
>
>   ; CMD0 senden

Die Dummy Clocks werden mit CS HIGH gesendet, denn die Karte ist hier 
noch im SD Modus. Es werden mindestens 80 Clocks benötigt, Du sendest 
255*8 - was aber nicht stört.

Erst für das CMD0 muss CS auf Low gezogen werden.

Außerdem fehlt im Schaltplan der Pullup (10k IIRC) an SD_MISO. Diese 
Leitung ist bis zum CMD0 ein Open Drain. Der Pegelwandler ist hier 
sinnfrei, da 3.3 Volt Ausgänge auch für 5 Volt Eingänge ausreichend 
Pegel haben.

von Leo M. (crashc)


Lesenswert?

Jim Meba schrieb:
> Erst für das CMD0 muss CS auf Low gezogen werden.

Genau dort scheint der Knackpunkt gelegen zu haben. Vielen Dank, Jim 
Meba!

Vielen Dank auch an alle anderen für euer Feedback zu dem Pegelwandler! 
Bis jetzt arbeite ich ja (mit dem Prescaler 128) nur bei einer Frequenz 
von 72kHz. Wenn ich dann später die Geschwindigkeit erhöhen will, werden 
diese Informationen bestimmt sehr nützlich sein.

MfG Leonardo

PS: Das war mein erster Beitrag in diesem Forum und ich finde die 
Hilfsbereitschaft hier extrem Klasse! Daumen hoch!

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.