Forum: Mikrocontroller und Digitale Elektronik sd_card probleme block lesen


von Sonke A. (soeni)


Lesenswert?

Hi,

ich habe folgenden Versuchsaufbau: atmega 128 über spi an einer SD Card.

initialisieren funktiniert wunderbar, CID Register auslesen usw auch. 
leider kann ich jedoch keine Blöcke vom Speicher lesen. Ich habe die 
Blocksize auf 512 gestellt und will auch einen block  (addresse 0x00-) 
also genau einen Block lesen.

Das kommando wird von der SD erkannt, aber wenn ich dann auf das 
starttoken der Daten warte 0xfe laue ich in meinen Timeout rein und der 
ist wirklich großzügig bemessen, sonst braucht kein befehl so lange.

hier der Codeausschnitt:
1
char readBlock_SD(char * cmd, char* buffer, int length){
2
3
  int timeout = 5000;
4
  // Send Command
5
  if(cmd_SD(cmd))
6
    // Return if an Error occurred
7
    return -1;
8
9
  // Waiting for initial transmission
10
  while(SPI_RECEIVE() != 0xfe && timeout){
11
    timeout--;
12
  }
13
14
  // Timeout brake
15
  if(timeout == 0)
16
    return -2;
17
18
  // Read value
19
  for( int i = 0; i < length; i++){
20
    buffer[i] = SPI_RECEIVE();
21
  }
22
23
  // CRC
24
  SPI_RECEIVE();
25
  // Close block
26
  SPI_RECEIVE();
27
28
  return 1;
29
30
31
}

wie gesagt bim timeout springt er raus.

ran kann das liegen??

Gruß

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Spekulation!

Das Problem steckt nicht im Code oben, sondern in der Kommuniaktion mit 
der Karte. Die Karte schickt in der vorgegebenen Zeit nicht die 
erwarteten Daten.

Ich würde das Anstoßen der Blockübertragung und deren Abwicklung 
debuggen. Dazu würde ich mir ausgeben lassen, was in der Zeile 
while(SPI_RECEIVE() != 0xfe && timeout) von SPI_RECEIVE() zurückgegeben 
wird.

Programmiertechnisch ist die Zeitvorgabe mit dem Runterzählen von 
timeout "hässlich". Es kann passend getunt sein, bei der nächsten 
Compilerversion, Änderungen an der Source oder Änderungen der Taktrate 
passt es schon nicht mehr.

von Sonke A. (soeni)


Lesenswert?

wie würdest du das timeout denn realisieren?

das timeout hab ich weg bekomen, ich hatte beim lesen cs nicht richtig 
gesetzt. nur bekomme ich nun nur schwachsinn gelesen. immer das gleich. 
habe die sd card mit nem hexeditor eingelesen und das was ich bekomme 
steht definitiv nicht an der stelle im MBR den ich da auslese also 
addresse 0x00

von Sonke A. (soeni)


Lesenswert?

Kann mir hier nochmal jemand helfen?? wie gesagt ich empfange immer nur 
(komischerweise 3 zeichen lang?!?!) olgende Hexzahl 0xedf. Wie kann das 
kommen??

Hier nochmal der gesammte code: read_Block_SD wir mit der Adresse 0 
aufgeruen. Das kommando wird quittiert, alles scheint ok, nur die Daten 
stimmen nicht. Liegt das an meinem umwandeln?
1
/**    PROTECT
2
 *
3
 * This function sends a command to the sd card and receives the answer
4
 * @param cmd the command to send
5
 * @param arg the argument send to the Card (4 Bytes)
6
 * @return the answer of the SD Card
7
 */
8
static char cmd_SD(char * cmd){
9
  /**
10
   * Es müssen wohl 32 byte gesendet werden,28 nutzbytes und der rest command und crd
11
   */
12
  unsigned short ret=0;
13
  int timeoutvar=0;
14
15
16
  // Release CS SD Card (low active)
17
  PORTB &=~(1<<SDCARD_CS);
18
19
  cmd[0] += 0x40; // put on a offset of 0x40
20
21
22
  SPI_SEND(cmd[0]);
23
  SPI_SEND(cmd[1]);
24
  SPI_SEND(cmd[2]);
25
  SPI_SEND(cmd[3]);
26
  SPI_SEND(cmd[4]);
27
  SPI_SEND(cmd[5]); // CRC Checksum
28
29
  // Wait for response
30
  timeoutvar=500;
31
  do{
32
    ret = SPI_RECEIVE();
33
    timeoutvar--;
34
  }while(ret == 0xFF && timeoutvar);
35
36
37
  // set CS SD Card (low active)
38
  PORTB |=(1<<SDCARD_CS);
39
  return ret;
40
}
41
42
43
44
45
46
47
/**
48
 * This function reads a block from the SD Card to the Buffer
49
 *
50
 * @param * cmd   pointer to a 6 byte array containing the command
51
 * @param * buffer  pointer to a buffer where the bytes could be storage
52
 * @param length  length of buffer
53
 * @return   1   if everything is all right
54
 *       -1  if cmd error
55
 *       -2  if timeout while receiving
56
 */
57
char readBlock_SD(char * cmd, char* buffer, int length){
58
59
  int timeout = 5000;
60
  // Send Command
61
  if(cmd_SD(cmd))
62
    // Return if an Error occurred
63
    return -1;
64
65
  // Release CS SD Card (low active)
66
  PORTB &=~(1<<SDCARD_CS);
67
68
  // Waiting for initial transmission
69
  while(SPI_RECEIVE() != 0xfe && timeout){
70
    timeout--;
71
  }
72
73
  // Timeout brake
74
  if(timeout == 0)
75
    return -2;
76
  char str[6];
77
  str[0]=" ";
78
  str[1]=" ";
79
  str[2]=" ";
80
81
  // Read value
82
  for( int i = 0; i < length; i++){
83
    buffer[i] = SPI_RECEIVE();
84
    itoa((int)buffer,str,16);
85
    sendStringRS232(" 0x");
86
    sendStringRS232(str);
87
    if(((i+1)%16)==0)
88
      sendStringRS232("\r\n");
89
  }
90
91
  // CRC
92
  SPI_RECEIVE();
93
  // Close block
94
  SPI_RECEIVE();
95
96
  // set CS SD Card (low active)
97
  PORTB |=(1<<SDCARD_CS);
98
99
  return 1;
100
101
102
}
103
104
105
  void SPI_SEND(char cmd){
106
    SPDR = cmd;
107
    while(!(SPSR & (1<<SPIF))){} //Wait until Byte is send
108
109
  }
110
111
  char SPI_RECEIVE(){
112
  SPDR = 0xff;
113
  while(!(SPSR & (1<<SPIF))){} //Wait until Byte is send
114
  return SPDR;
115
  }

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.