Forum: Mikrocontroller und Digitale Elektronik SD SPI Bytes lesen


von Flo W. (Firma: privat) (florian1x)


Lesenswert?

Hallo,
ich habe ein Problem Bytes zu lesen
hier mal mein Code
1
#ifndef __SDCARD__
2
#define __SDCARD__
3
4
/* Includes */
5
#include "../uart/uart.h"
6
#include "../spi/spi.h"
7
#include <util/delay.h>
8
9
#ifndef DEBUG
10
  #define DEBUG //Should be only defined if Debug messages are needed
11
#endif
12
13
/*spi methods*/
14
#define spi_send_byte(x)   spi2_transmit(x)  //Method to transmit a Byte via SPI
15
#define spi_speed_low()   {SPSR|=(1<<SPI2X);SPCR|=(1<<SPR1);SPCR&=~(1<<SPR0);} //sets SPI Clockrate between 100kHz and 400kHz
16
17
              
18
#define spi_speed_high()    {SPSR&=~(1<<SPI2X);SPCR&=~(1<<SPR1);SPCR&=~(1<<SPR0);} //sets SPI Clockrate to maximum
19
20
/*defines for Hardware Initialisation*/
21
#define SD_CS_PIN        PC6    //Chipselect for SD Card
22
#define SD_CS_PORT       PORTC  //Port of SD_CS
23
#define SD_CS_DDR        DDRC   //Data Direction Register for SD_CS
24
25
#define sd_cs_low()       SD_CS_PORT &= ~(1 << SD_CS_PIN) // SD_CS -> '1'
26
#define sd_cs_high()      SD_CS_PORT |= (1 << SD_CS_PIN)  // SD_CS -> '0'
27
28
/*some other defines:*/
29
#define SD_INIT_TIMEOUT   30 //value between 0 and 254 
30
#define SD_HCS            1   // 0 = SDHC disable, 1 = SDHC enable
31
32
/*SD Card Versions*/
33
#define SD_UNSUPPORTED    0
34
#define SD_SPEC1      1 
35
#define SD_SPEC2       2 
36
#define SD_SDHC       3 
37
38
/* 
39
Command defines:
40
41
Command Format (6 Bytes): 
42
start bit ('0') + transmission bit('1') + command index (6bit) + arguments (4 byte) + CRC7 (7bit)+ end bit('1')
43
*/
44
45
/*SPI specifik commands (start bit+transmission bit+command index):*/   
46
#define SD_GO_IDLE_STATE        0x00 //CMD0
47
#define SD_SEND_OP_COND        0x01 //CMD1
48
#define SD_SWITCH_FUNC        0x06 //CMD6
49
#define SD_SEND_IF_COND        0x08 //CMD8
50
#define SD_SEND_CSD         0x09 //CMD9
51
#define SD_SEND CID         0x0A //CMD10
52
#define SD_STOP_TRANSMISSION     0x0C //CMD12
53
#define SD_SEND_STATUS         0x0D //CMD13
54
#define SD_SET_BLOCKLEN       0x10 //CMD16
55
#define SD_READ_SINGLE_BLOCK     0x11 //CMD17
56
#define SD_READ_MULTIPLE_BLOCK     0x12 //CMD18
57
#define SD_WRITE_BLOCK         0x18 //CMD24
58
#define SD_WRITE_MULTIPLE_BLOCK    0x19 //CMD25
59
#define SD_PROGRAM_CSD         0x1B //CMD27
60
#define SD_SET_WRITE_PROT        0x1C //CMD28
61
#define SD_CLR_WRITE_PROT       0x1D //CMD29
62
#define SD_SEND_WRITE_PROT       0x1E //CMD30
63
#define SD_ERASE_WR_BLK_START_ADDR   0x20 //CMD32
64
#define SD_ERASE_WR_BLK_END_ADDR   0x21 //CMD33
65
#define SD_ERASE          0x26 //CMD38
66
#define SD_LOCK_UNLOCK         0x2A //CMD42
67
#define SD_APP_CMD           0x37 //CMD55
68
#define SD_GEN_CMD           0x38 //CMD56
69
#define SD_READ_OCR         0x3A //CMD58
70
#define SD_CRC_ON_OFF         0x3B //CMD59
71
72
#define SD_SD_SEND_OP_COND      0x29 //ACMD41s
73
74
#define SD_CMD_MASK         0x40; //star bit and transmission bit
75
76
/* command responses */
77
/* Format R1 (1 byte)*/
78
#define SD_R1_IDLE_STATE       1
79
#define SD_R1_ERASE_RESET        2
80
#define SD_R1_ILLEGAL_COMMAND     3
81
#define SD_R1_COM_CRC_ERR       4
82
#define SD_R1_ERASE_SEQ_ERR     5
83
#define SD_R1_ADDRESS_ERR      6
84
#define SD_R1_PARAMETER_ERR     7
85
86
/* Format R3 (5 bytes)*/
87
#define SD_R3_IDLE_STATE       33
88
#define SD_R3_ERASE_RESET       34
89
#define SD_R3_ILLEGAL_COMMAND     35
90
#define SD_R3_COM_CRC_ERR       36
91
#define SD_R3_ERASE_SEQ_ERR     37
92
#define SD_R3_ADDRESS_ERR       38
93
#define SD_R3_PARAM_ERR       39
94
95
/*Methods*/
96
97
//initialize SD Card 
98
uint8_t sd_init(void); 
99
100
//Sends a 6 Byte long SD/MMC-Cardcommand via SPI
101
uint8_t sd_send_cmd(uint8_t, uint32_t, uint8_t); 
102
103
//Reads the next 4 Bytes after a command with R3 response
104
uint32_t sd_read_four_byte(void);
105
106
uint8_t sd_read_single_block(uint32_t, uint8_t *buffer, uint16_t);
107
108
void sd_print_buffer(uint8_t *buffer, uint16_t);
109
#endif

------------------------------------------------------------

die c file zur h
1
#include "sd.h"
2
3
volatile uint8_t sdversion = SD_UNSUPPORTED; 
4
5
// Method to initialize SDCard/MMC after Powerup
6
// name: sd_init()
7
// @param
8
// @return returns type of inserted Card
9
10
uint8_t sd_init(){
11
  
12
  spi_speed_low();
13
  
14
  /* Hardware initialisation */
15
  
16
  //Chips select for SDCard to output
17
    SD_CS_DDR |= ( 1 << SD_CS_PIN );  
18
    //CS to logic 1
19
    sd_cs_high();
20
  //wait 1 ms
21
  _delay_ms(1);
22
    //send 74+ dummy clocks
23
    for(uint8_t i = 0; i<8 ; i++)
24
        spi_send_byte(0xFF);
25
26
  /* Software initialisation - Go IDLE MODE */
27
  
28
  #ifdef DEBUG
29
    printf("Go IDLE mode ... \n");
30
  #endif
31
  
32
  uint8_t timeout = SD_INIT_TIMEOUT;
33
  uint8_t rec = 0;
34
  
35
    //CMD0 to get Card into IDLE State
36
    while(rec!=1){
37
    rec = sd_send_cmd( SD_GO_IDLE_STATE, 0, 0x95 );
38
    if(!timeout--){
39
      #ifdef DEBUG
40
        printf("Timeout reached. Stop card initialisation\n");
41
      #endif
42
      return sdversion = SD_UNSUPPORTED;
43
    }
44
  }
45
  
46
  /* Software initialisation - Card verification */
47
    
48
    #ifdef DEBUG
49
    printf("Card is in IDLE mode. Begin to verify version\n");
50
  #endif
51
52
  //send CMD08
53
  rec = sd_send_cmd(SD_SEND_IF_COND, 0x1AA, 0x87);
54
  
55
  if(rec==0x05){ //means SDC V1 or MMC
56
    sdversion = SD_SPEC1;
57
    #ifdef DEBUG
58
      printf("MMC/SDCV1\n");
59
    #endif
60
  }else{
61
    uint32_t ocr = sd_read_four_byte();
62
    
63
    if((ocr&0x0FFF)==0x01AA){ //means SDC V2
64
      #ifdef DEBUG
65
        sdversion = SD_SPEC2;
66
        printf("SDCV2\n");
67
      #endif
68
    }
69
    rec = sd_send_cmd(SD_READ_OCR, 0, 0);
70
    sd_read_four_byte();
71
  }
72
  
73
  /* Software initialisation - Initialisation with ACMD41 */
74
  
75
  timeout = SD_INIT_TIMEOUT;
76
  while(rec){
77
    sd_send_cmd(SD_APP_CMD, 1L<<30, 0xFF); //CMD55
78
    rec = sd_send_cmd(SD_SD_SEND_OP_COND, 1L<<30, 0xFF);//ACMD41
79
    if(!(--timeout)){
80
      #ifdef DEBUG
81
        printf("Timeout reached. Stop card initialisation with ACMD41\n");
82
      #endif
83
      break;
84
    }
85
  }
86
  
87
  /* Software initialisation - Initialisation with CMD1 */
88
  #ifdef DEBUG
89
    if(rec)
90
      printf("Try to initiate with CMD1\n");
91
  #endif
92
  timeout = SD_INIT_TIMEOUT;
93
  while(rec){
94
    rec = sd_send_cmd(SD_SEND_OP_COND, 0, 0xFF); //CMD1
95
    if(!(--timeout)){
96
      #ifdef DEBUG
97
        printf("Timeout reached. Stop card initialisation\n");
98
      #endif
99
      return sdversion = SD_UNSUPPORTED;
100
    }
101
  }
102
  
103
  spi_speed_high();
104
  return rec;
105
}  
106
107
// Sends a command to SDC via SPI and returns R1
108
// name: sd_hw_init
109
// @param cmd command for SD Card
110
// @param arg Arguments for the CMD
111
// @param crc checksum
112
// @return command response in R1 format
113
114
uint8_t sd_send_cmd(uint8_t cmd, uint32_t arg, uint8_t crc){
115
  
116
  /*build complete Command*/
117
  uint8_t buffer[6] ;                   //temporary Buffer for the CMD
118
  buffer[0] = cmd | SD_CMD_MASK;        //Set start and transmission bit + Command
119
  buffer[1] = (arg & 0xFF000000) >> 24; //Set parameter byte 1
120
  buffer[2] = (arg & 0x00FF0000) >> 16; //Set parameter byte 2 
121
  buffer[3] = (arg & 0x0000FF00) >> 8;  //Set parameter byte 3
122
  buffer[4] = (arg & 0x000000FF);       //Set parameter byte 4
123
  buffer[5] = crc | 0x01;               //CRC + Endbit '1'
124
125
  #ifdef DEBUG
126
    //Prints the Command
127
    printf("Sending CMD: ");
128
    printf("%d, ", buffer[0]&0b00111111);
129
    printf("ARGS: ");
130
    for(uint8_t i=1; i<5; i++)
131
      printf("0x%x, ", buffer[i]);
132
    printf("CRC: 0x%x, ", buffer[5]);
133
  #endif
134
  
135
  sd_cs_low();
136
  spi_send_byte(0xFF); 
137
  
138
  //Send complete Command via SPI
139
    for(uint8_t i=0; i<6; i++)
140
        spi_send_byte(buffer[i]); 
141
  
142
  //receive answer byte
143
  uint8_t ret = 0xFF;
144
  uint8_t timeout = 0;
145
  while(ret==0xFF){
146
    ret = spi_send_byte(0xFF);
147
    if(timeout++>100)
148
      break;
149
  }
150
  
151
  sd_cs_high();            //clear SPI  
152
  #ifdef DEBUG
153
    //Prints the Command
154
    printf("recv.: 0x%x", ret);
155
    printf(".\n");
156
  #endif  
157
  
158
    return ret;
159
}
160
161
uint32_t sd_read_four_byte(){
162
  uint32_t values = (uint32_t)spi_send_byte(0xFF)<<24;
163
  values |= (uint32_t)spi_send_byte(0xFF)<<16;
164
  values |= (uint32_t)spi_send_byte(0xFF)<<8;
165
  values |= spi_send_byte(0xFF);
166
  
167
  #ifdef DEBUG
168
    printf("ocr: 0x%x 0x%x 0x%x 0x%x\n", (uint8_t)((values>>24)&0xFF), (uint8_t)((values>>16)&0xFF), (uint8_t)((values>>8)&0xFF), (uint8_t)(values&0xFF));
169
  #endif  
170
  return values;
171
}
172
173
uint8_t sd_read_single_block(uint32_t startBlock, uint8_t *buffer, uint16_t buf_size){
174
  
175
  //Send command to MMC/SDC/SDHC Card
176
  uint8_t rec = sd_send_cmd(SD_READ_SINGLE_BLOCK, startBlock, 0xFF); //read a Block command
177
  
178
  //Check for errors 
179
  if(rec != 0x00) 
180
    return rec; 
181
  
182
  /*read Bytes and write to Buffer*/
183
  sd_cs_low();
184
  
185
  //Wait for startbyte 
186
  uint8_t timeout = 100;
187
  while(spi_send_byte(0xFF) != 0xfe){
188
    if(timeout--){
189
      sd_cs_high(); 
190
      return 0;
191
    } 
192
  }
193
  
194
  //Read Block
195
  while(buf_size--){ //read buf_size bytes
196
    *buffer++ = spi_send_byte(0xFF);
197
    
198
  }
199
  //receive CRC
200
  spi_send_byte(0xFF); //ignored
201
  spi_send_byte(0xFF); //ignored
202
  
203
  sd_cs_high(); 
204
205
  return 1;
206
}
207
208
#ifdef DEBUG
209
  void sd_print_buffer(uint8_t *buffer, uint16_t buf_size){
210
    printf("read %d Bytes after address %p\n", buf_size, &buffer);
211
    printf("offset\t1\t2\t3\t4\t5\t6\t7\t8\t9\tA\tB\tC\td\n");
212
    uint8_t offset = 0;
213
    for(uint8_t i = 0; i<buf_size; i=i+16){
214
      printf("0x%x", offset++);  //Offset
215
      printf("\t%x", *buffer++); //1
216
      printf("\t%x", *buffer++); //2
217
      printf("\t%x", *buffer++); //3
218
      printf("\t%x", *buffer++); //4
219
      printf("\t%x", *buffer++); //5
220
      printf("\t%x", *buffer++); //6
221
      printf("\t%x", *buffer++); //7
222
      printf("\t%x", *buffer++); //8
223
      printf("\t%x", *buffer++); //9
224
      printf("\t%x", *buffer++); //A
225
      printf("\t%x", *buffer++); //B
226
      printf("\t%x", *buffer++); //C
227
      printf("\t%x", *buffer++); //D
228
      printf("\t%x", *buffer++); //E
229
      printf("\t%x", *buffer++); //F
230
      printf("\n"); 
231
    }
232
  }
233
#endif

-------------------------------------------------

und die main:
1
/* 
2
   Name: main.c
3
   Author: Mathäus Sander & Florian Weinhold
4
5
   Desc.: Main Programm for testing purposes
6
   License: LGPL
7
*/
8
9
10
#define F_CPU 20000000L
11
#define BAUD 9600L
12
#define DEBUG
13
14
#include <avr/io.h>
15
#include <util/delay.h>
16
#include "uart/uart.h"
17
#include "spi/spi.h"
18
#include "sd/sd.h"
19
#include "enc28j60/enc28j60.h"
20
21
int main(void) {
22
  
23
  USART_Init();
24
  SPI1_Init(); //ENC OR SDCard
25
    SPI2_Init(); //ENC OR SDCard
26
    
27
  printf("Welcome to WeSa System v0.0.1a\n");
28
29
    printf("Starting SD initialsation.\n");  
30
  
31
  printf("%x", sd_init());
32
  uint8_t buff[32];
33
  sd_read_single_block(0, buff, 32);
34
  sd_print_buffer(buff, 32);
35
  while(1) {  
36
    _delay_ms(500);
37
  }
38
39
  return 0;
40
}


ich hoffe das reicht an quelltext.
ich versuche derzeit die ersten 32 byte der karte zu lesen. bekomme aber 
nur nullen raus.

Hardware: Myethernet 2.03, Uart über MySmartUsb, Kingston 4GB SDHC karte

Also initialisieren klappt soweit ... nur habe ich hinterher nur nullen 
drin stehen. Weiss einer woran das liegt?

mfG Flo

von Sascha W. (sascha-w)


Lesenswert?

Hallo,

welche spi.h verwendest du?

'spi_send_byte' gibt glaube ich keinen Wert zurück, wie wärs mit 
'spi_Transfer_Byte'

Sascha

von Flo W. (Firma: privat) (florian1x)


Lesenswert?

oh das hätte ich vlt noch dazu packen sollen, ich verwende meine eigene 
SPI methoden. Funktionieren auch soweit. Ich gebe halt das Byte zurück 
welches mit der clock ankommt in der ich auch sende.

meine ausgabe in GTKTerm sieht wie folgt aus:

UART Initialized

SPI Initialized
USART as SPI Initialized

Welcome to WeSa System v0.0.1a

Starting SD initialsation.
Go IDLE mode ...
Sending CMD: 0, ARGS: 0x0, 0x0, 0x0, 0x0, CRC: 0x95, recv.: 0x1.

Card is in IDLE mode. Begin to verify version

Sending CMD: 8, ARGS: 0x0, 0x0, 0x1, 0xaa, CRC: 0x87, recv.: 0x1.
ocr: 0x0 0x0 0x0 0x0

Sending CMD: 58, ARGS: 0x0, 0x0, 0x0, 0x0, CRC: 0x1, recv.: 0x1.
ocr: 0x0 0x0 0x0 0x0

Sending CMD: 55, ARGS: 0x40, 0x0, 0x0, 0x0, CRC: 0xff, recv.: 0x1.
Sending CMD: 41, ARGS: 0x40, 0x0, 0x0, 0x0, CRC: 0xff, recv.: 0x1.

Sending CMD: 55, ARGS: 0x40, 0x0, 0x0, 0x0, CRC: 0xff, recv.: 0x1.

Sending CMD: 41, ARGS: 0x40, 0x0, 0x0, 0x0, CRC: 0xff, recv.: 0x0.
0Sending CMD: 17, ARGS: 0x0, 0x0, 0x0, 0x0, CRC: 0xff, recv.: 0x0.
read 32 Bytes after address 0x10cc

offset  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F

0x0  2c  e3  f5  aa  ff  f  69  c2  a2  cf  ad  98  fe  7d  f8

0x1  cf  5e  3d  f1  60  d4  eb  e9  67  99  8  d8  f7  c5  f6


edit ... ok ich hab seid gestern ncihts mehr gemacht und auf einma 
spuckt der was aus.

von Flo W. (Firma: privat) (florian1x)


Lesenswert?

Ok nachdem es nun einige male Werte ausgegeben hat, jedoch andere, wie 
die die bei mir in WinHex angezeigt werden. Kommt nun wieder nix

UART Initialized
SPI Initialized

USART as SPI Initialized

Welcome to WeSa System v0.0.1a
Starting SD initialsation.
Go IDLE mode ...
Sending CMD: 0, ARGS: 0x0, 0x0, 0x0, 0x0, CRC: 0x95, recv.: 0x1f.
Sending CMD: 0, ARGS: 0x0, 0x0, 0x0, 0x0, CRC: 0x95, recv.: 0x5.

Sending CMD: 0, ARGS: 0x0, 0x0, 0x0, 0x0, CRC: 0x95, recv.: 0x1.

Card is in IDLE mode. Begin to verify version

Sending CMD: 8, ARGS: 0x0, 0x0, 0x1, 0xaa, CRC: 0x87, recv.: 0x1.
ocr: 0x0 0x0 0x0 0x0

Sending CMD: 58, ARGS: 0x0, 0x0, 0x0, 0x0, CRC: 0x1, recv.: 0x1.

ocr: 0x0 0x0 0x0 0x0
Sending CMD: 55, ARGS: 0x40, 0x0, 0x0, 0x0, CRC: 0xff, recv.: 0x1.

Sending CMD: 41, ARGS: 0x40, 0x0, 0x0, 0x0, CRC: 0xff, recv.: 0x1.
Sending CMD: 55, ARGS: 0x40, 0x0, 0x0, 0x0, CRC: 0xff, recv.: 0x1.
Sending CMD: 41, ARGS: 0x40, 0x0, 0x0, 0x0, CRC: 0xff, recv.: 0x0.

0Sending CMD: 17, ARGS: 0x0, 0x0, 0x0, 0x0, CRC: 0xff, recv.: 0x0.
read 32 Bytes
offset  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
0x0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
0x1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0


anfangs will cmd0 aber auch nicht so recht vlt liegs auch daran.

von Flo W. (Firma: privat) (florian1x)


Lesenswert?

ahhh fail, hab meinen fehler :), hatte die Abfrage zum timeout falsch, 
weshalb der immer direkt aus der Methode raus is. Aber der liest dann 
ziehmlich lange.

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.