Forum: Mikrocontroller und Digitale Elektronik PIC24FJ64GA002 - SD-Card ansteuern - falsche Response auf CMD0


von Patrick U. (patrick_u)


Lesenswert?

Hallo liebes Forum,

für ein Schulprojekt habe ich eine Platine erstellt, die mithilfe eines 
PIC24FJ64GA002 eine Micro-SD-Card beschreiben soll.

Folgenden Code habe ich dazu auf die Beine gestellt:
1
int spi_send (char u)
2
{
3
  SPI1BUF = u;
4
  while(SPI1STATbits.SPIRBF == 0);
5
  if (ucIndex < 180)
6
    {
7
    ucaInput[ucIndex] = SPI1BUF;
8
    ucIndex ++;
9
    }
10
  ucRec = SPI1BUF;
11
  return ucRec;
12
}
13
14
15
void spi_send_dummy (int k)  //sendet einen 0xFF "k-mal" mit "CS = high" !!
16
{
17
  CS = 1;
18
  while(k > 0)
19
  {
20
  k--;
21
  spi_send(0xFF);
22
  }
23
}
24
25
unsigned char spi_send_cmd (char cmd, char param1, char param2, char param3, char param4, char crc)
26
{
27
  CS = 0;
28
  cmd = cmd + 0x40;
29
  spi_send (cmd);
30
  spi_send (param1);
31
  spi_send (param2);
32
  spi_send (param3);
33
  spi_send (param4);
34
  spi_send (crc);
35
  
36
  while((ucRec && 0x80) != 0)
37
  spi_send (0xFF);
38
39
  ucResponse = ucRec;
40
41
  spi_send_dummy(1);      //lässt ein Dummy Byte durchlaufen, um der Karte clocks zu geben
42
  return ucResponse;
43
  
44
}
45
46
int main()
47
{
48
  init();
49
  int i = 125;      // 10ms bei 125kHz
50
  while(i--);
51
  
52
  CS = 1;
53
54
  spi_send_dummy (10);
55
  spi_send_cmd (0x00,0x00,0x00,0x00,0x00,0x95);
56
57
  if (ucResponse == 0x01)
58
59
  LED_ON = 1;
60
61
  else
62
63
  LED_ON = 0;
64
65
while(1);

die Antwort durch die SD-Card sollte "0x01" lauten, allerdings spuckt 
diese nur wahllose Daten aus. Ich verzweifle langsam, kann mir jemand 
sagen was ich falsch mache??

vielen Dank im Voraus, Patrick U.

von holger (Gast)


Lesenswert?

>  while((ucRec && 0x80) != 0)

  while((ucRec & 0x80) != 0)

von Patrick U. (patrick_u)


Lesenswert?

Codefehler meinerseits, danke!

allerdings hat es wohl nichts mit dem eigentlichen problem zu tun, da 
völlig wahllos geschickt wird, teilweise gar nichts

Edit: Bist du sicher, dass "&&" ein Fehler ist? soll eine 
"UND-Verknüpfung" darstellen und damit das MSB maskieren. (C30 von 
Microchip wird verwendet).

von holger (Gast)


Lesenswert?

Bringt wahrscheinlich auch nichts, aber man weiss ja nie:
1
int spi_send (char u)
2
{
3
  SPI1BUF = u;
4
  while(SPI1STATbits.SPIRBF == 0);
5
  if (ucIndex < 180)
6
    {
7
    ucaInput[ucIndex] = SPI1BUF;
8
    ucIndex ++;
9
    }
10
  ucRec = SPI1BUF;
11
  return ucRec;
12
}

Du liest dort zweimal SPI1BUF. Das sollte man auf keinen
Fall tun wenn das SPI Modul einen FIFO hat. Mach es so:
1
int spi_send (char u)
2
{
3
 
4
  SPI1BUF = u;
5
  while(SPI1STATbits.SPIRBF == 0);
6
  ucRec = SPI1BUF;
7
  if (ucIndex < 180)
8
    {
9
    ucaInput[ucIndex] = ucRec;
10
    ucIndex ++;
11
    }
12
  return ucRec;
13
}

von holger (Gast)


Lesenswert?

Und das hier:

  while((ucRec && 0x80) != 0)
  spi_send (0xFF);

besser so machen:

  do
   {
    spi_send (0xFF);
   } while(ucRec == 0xFF);

So klappt das bei mir mit AVR, ARM und sonst was;)

von Patrick U. (patrick_u)


Lesenswert?

das Problem bei deinem Code ist jedoch, dass wenn die antwort nicht 0xFF 
sondern z.B. 0x80 ist, wird die Schleife beendet (hatte ich schonmal).

Da die bits 0-6 irgendeinen Wert enthalten können, solange bit 7 (MSB) 
auf high ist, wäre das nicht gesund. (Die Weisheit kommt übrigens nicht 
von mir sondern die hab ich hier aus dem Forum)

von holger (Gast)


Lesenswert?

Ein letzter Tipp:

Wenn du keinen Pullup am Ausgang der SD Karte hast sende
CMD0 einfach mehrmals. Dabei nicht zimperlich sein.
So 100 und mehr Wiederholungen versuchen.
Irgendwann klappt es dann schon.

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.