ATmega8GPSLoggerBasismodul  20131018
mmc.c
Go to the documentation of this file.
1 /*#######################################################################################
2 Connect AVR to MMC/SD
3 
4 Copyright (C) 2004 Ulrich Radig
5 
6 Bei Fragen und Verbesserungen wendet euch per EMail an
7 
8 mail@ulrichradig.de
9 
10 oder im Forum meiner Web Page: www.ulrichradig.de
11 
12 Dieses Programm ist freie Software. Sie können es unter den Bedingungen der
13 GNU General Public License, wie von der Free Software Foundation veröffentlicht,
14 weitergeben und/oder modifizieren, entweder gemäß Version 2 der Lizenz oder
15 (nach Ihrer Option) jeder späteren Version.
16 
17 Die Veröffentlichung dieses Programms erfolgt in der Hoffnung,
18 daß es Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE,
19 sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT
20 FÜR EINEN BESTIMMTEN ZWECK. Details finden Sie in der GNU General Public License.
21 
22 Sie sollten eine Kopie der GNU General Public License zusammen mit diesem
23 Programm erhalten haben.
24 Falls nicht, schreiben Sie an die Free Software Foundation,
25 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
26 #######################################################################################*/
27 
28 #include "mmc.h"
29 
30 //############################################################################
31 //Routine zur Initialisierung der MMC/SD-Karte (SPI-MODE)
32 unsigned char mmc_init ()
33 //############################################################################
34 {
35  unsigned int Timeout = 0;
36  unsigned char a=0; //for loop variable
37  unsigned char b = 0; //for loop variable
38 
39  //Konfiguration des Ports an der die MMC/SD-Karte angeschlossen wurde
40  MMC_Direction_REG &=~(1<<SPI_DI); //Setzen von Pin MMC_DI auf Input
41  MMC_Direction_REG |= (1<<SPI_Clock); //Setzen von Pin MMC_Clock auf Output
42  MMC_Direction_REG |= (1<<SPI_DO); //Setzen von Pin MMC_DO auf Output
43  MMC_Direction_REG |= (1<<MMC_Chip_Select); //Setzen von Pin MMC_Chip_Select auf Output
44  MMC_Direction_REG |= (1<<SPI_SS);
45  MMC_Write |= (1<<MMC_Chip_Select); //Setzt den Pin MMC_Chip_Select auf High Pegel
46 
47  for(a;a<200;a++){
48  nop();
49  }; //Wartet eine kurze Zeit
50 
51  #if SPI_Mode
52  //Aktiviren des SPI - Bus, Clock = Idel LOW
53  //SPI Clock teilen durch 128
54  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1); //Enable SPI, SPI in Master Mode
55  SPSR = (0<<SPI2X);
56  #endif
57 
58  //Initialisiere MMC/SD-Karte in den SPI-Mode
59  for (b;b<0x0f;b++) //Sendet min 74+ Clocks an die MMC/SD-Karte
60  {
61  mmc_write_byte(0xff);
62  }
63 
64  //Sendet Commando CMD0 an MMC/SD-Karte
65  unsigned char CMD[] = {0x40,0x00,0x00,0x00,0x00,0x95};
66  while(mmc_write_command (CMD) !=1)
67  {
68  if (Timeout++ > 200)
69  {
70  MMC_Disable();
71  return(1); //Abbruch bei Commando1 (Return Code1)
72  }
73  }
74  //Sendet Commando CMD1 an MMC/SD-Karte
75  Timeout = 0;
76  CMD[0] = 0x41;//Commando 1
77  CMD[5] = 0xFF;
78  while( mmc_write_command (CMD) !=0)
79  {
80  if (Timeout++ > 400)
81  {
82  MMC_Disable();
83  return(2); //Abbruch bei Commando2 (Return Code2)
84  }
85  }
86  #if SPI_Mode
87  //SPI Bus auf max Geschwindigkeit
88  SPCR &= ~((1<<SPR0) | (1<<SPR1));
89  SPSR = SPSR|(1<<SPI2X);
90  #endif
91 
92  //set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
93  MMC_Disable();
94  return(0);
95 }
96 
97 //############################################################################
98 //Sendet ein Commando an die MMC/SD-Karte
99 unsigned char mmc_write_command (unsigned char *cmd)
100 //############################################################################
101 {
102  unsigned char tmp = 0xff;
103  unsigned int Timeout = 0;
104  unsigned char a = 0; //for loop variable
105 
106  //set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
107  MMC_Disable();
108 
109  //sendet 8 Clock Impulse
110  mmc_write_byte(0xFF);
111 
112  //set MMC_Chip_Select to low (MMC/SD-Karte Aktiv)
113  MMC_Enable();
114 
115  //sendet 6 Byte Commando
116  for (a;a<0x06;a++) //sendet 6 Byte Commando zur MMC/SD-Karte
117  {
118  mmc_write_byte(*cmd++);
119  }
120 
121  //Wartet auf ein gültige Antwort von der MMC/SD-Karte
122  while (tmp == 0xff)
123  {
124  tmp = mmc_read_byte();
125  if (Timeout++ > 500)
126  {
127  break; //Abbruch da die MMC/SD-Karte nicht Antwortet
128  }
129  }
130  return(tmp);
131 }
132 
133 //############################################################################
134 //Routine zum Empfangen eines Bytes von der MMC-Karte
135 unsigned char mmc_read_byte (void)
136 //############################################################################
137 {
138  unsigned char Byte = 0;
139 #if SPI_Mode //Routine f�r Hardware SPI
140  SPDR = 0xff;
141  while(!(SPSR & (1<<SPIF))){};
142  Byte = SPDR;
143 
144 #else //Routine f�r Software SPI
145  for (unsigned char a=8; a>0; a--) //das Byte wird Bitweise nacheinander Empangen MSB First
146  {
147  MMC_Write &=~(1<<SPI_Clock); //erzeugt ein Clock Impuls (Low)
148 
149  if (bit_is_set(MMC_Read,SPI_DI) > 0) //Lesen des Pegels von MMC_DI
150  {
151  Byte |= (1<<(a-1));
152  }
153  else
154  {
155  Byte &=~(1<<(a-1));
156  }
157  MMC_Write |=(1<<SPI_Clock); //setzt Clock Impuls wieder auf (High)
158  }
159 #endif
160  return (Byte);
161 }
162 
163 
164 //############################################################################
165 //Routine zum Senden eines Bytes zur MMC-Karte
166 void mmc_write_byte (unsigned char Byte)
167 //############################################################################
168 {
169 #if SPI_Mode //Routine f�r Hardware SPI
170  SPDR = Byte; //Sendet ein Byte
171  while(!(SPSR & (1<<SPIF))) //Wartet bis Byte gesendet wurde
172  {
173  }
174 #else //Routine f�r Software SPI
175  for (unsigned char a=8; a>0; a--) //das Byte wird Bitweise nacheinander Gesendet MSB First
176  {
177  if (bit_is_set(Byte,(a-1))>0) //Ist Bit a in Byte gesetzt
178  {
179  MMC_Write |= (1<<SPI_DO); //Set Output High
180  }
181  else
182  {
183  MMC_Write &= ~(1<<SPI_DO); //Set Output Low
184  }
185  MMC_Write &= ~(1<<SPI_Clock); //erzeugt ein Clock Impuls (LOW)
186 
187  MMC_Write |= (1<<SPI_Clock); //setzt Clock Impuls wieder auf (High)
188  }
189  MMC_Write |= (1<<SPI_DO); //setzt Output wieder auf High
190 #endif
191 }
192 
193 //############################################################################
194 //Routine zum schreiben eines Blocks(512Byte) auf die MMC/SD-Karte
195 unsigned char mmc_write_sector (unsigned long addr,unsigned char *Buffer)
196 //############################################################################
197 {
198  unsigned char tmp;
199  //Commando 24 zum schreiben eines Blocks auf die MMC/SD - Karte
200  unsigned char cmd[] = {0x58,0x00,0x00,0x00,0x00,0xFF};
201  unsigned char a=0; //for loop variable
202  unsigned int b=0; //for loop variable
203 
204  /*Die Adressierung der MMC/SD-Karte wird in Bytes angegeben,
205  addr wird von Blocks zu Bytes umgerechnet danach werden
206  diese in das Commando eingef�gt*/
207 
208  addr = addr << 9; //addr = addr * 512
209 
210  cmd[1] = ((addr & 0xFF000000) >>24 );
211  cmd[2] = ((addr & 0x00FF0000) >>16 );
212  cmd[3] = ((addr & 0x0000FF00) >>8 );
213 
214  //Sendet Commando cmd24 an MMC/SD-Karte (Write 1 Block/512 Bytes)
215  tmp = mmc_write_command (cmd);
216  if (tmp != 0)
217  {
218  return(tmp);
219  }
220 
221  //Wartet einen Moment und sendet einen Clock an die MMC/SD-Karte
222  for (a;a<100;a++)
223  {
224  mmc_read_byte();
225  }
226 
227  //Sendet Start Byte an MMC/SD-Karte
228  mmc_write_byte(0xFE);
229 
230  //Schreiben des Bolcks (512Bytes) auf MMC/SD-Karte
231  for (b;b<512;b++)
232  {
233  mmc_write_byte(*Buffer++);
234  }
235 
236  //CRC-Byte schreiben
237  mmc_write_byte(0xFF); //Schreibt Dummy CRC
238  mmc_write_byte(0xFF); //CRC Code wird nicht benutzt
239 
240  //Fehler beim schreiben? (Data Response XXX00101 = OK)
241  if((mmc_read_byte()&0x1F) != 0x05) return(1);
242 
243  //Wartet auf MMC/SD-Karte Bussy
244  while (mmc_read_byte() != 0xff){};
245 
246  //set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
247  MMC_Disable();
248 
249 return(0);
250 }
251 
252 //############################################################################
253 //Routine zum lesen des CID Registers von der MMC/SD-Karte (16Bytes)
254 void mmc_read_block(unsigned char *cmd,unsigned char *Buffer,unsigned int Bytes)
255 //############################################################################
256 {
257  unsigned int a=0; //for loop variable
258 
259  //Sendet Commando cmd an MMC/SD-Karte
260  if (mmc_write_command (cmd) != 0)
261  {
262  return;
263  }
264 
265  //Wartet auf Start Byte von der MMC/SD-Karte (FEh/Start Byte)
266 
267  while (mmc_read_byte() != 0xfe){};
268 
269  //Lesen des Bolcks (normal 512Bytes) von MMC/SD-Karte
270  for (a;a<Bytes;a++)
271  {
272  *Buffer++ = mmc_read_byte();
273  }
274  //CRC-Byte auslesen
275  mmc_read_byte();//CRC - Byte wird nicht ausgewertet
276  mmc_read_byte();//CRC - Byte wird nicht ausgewertet
277 
278  //set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
279  MMC_Disable();
280 
281  return;
282 }
283 
284 //############################################################################
285 //Routine zum lesen eines Blocks(512Byte) von der MMC/SD-Karte
286 unsigned char mmc_read_sector (unsigned long addr,unsigned char *Buffer)
287 //############################################################################
288 {
289  //Commando 16 zum lesen eines Blocks von der MMC/SD - Karte
290  unsigned char cmd[] = {0x51,0x00,0x00,0x00,0x00,0xFF};
291 
292  /*Die Adressierung der MMC/SD-Karte wird in Bytes angegeben,
293  addr wird von Blocks zu Bytes umgerechnet danach werden
294  diese in das Commando eingef�gt*/
295 
296  addr = addr << 9; //addr = addr * 512
297 
298  cmd[1] = ((addr & 0xFF000000) >>24 );
299  cmd[2] = ((addr & 0x00FF0000) >>16 );
300  cmd[3] = ((addr & 0x0000FF00) >>8 );
301 
302  mmc_read_block(cmd,Buffer,512);
303 
304  return(0);
305 }
306 
307 //############################################################################
308 //Routine zum lesen des CID Registers von der MMC/SD-Karte (16Bytes)
309 unsigned char mmc_read_cid (unsigned char *Buffer)
310 //############################################################################
311 {
312  //Commando zum lesen des CID Registers
313  unsigned char cmd[] = {0x4A,0x00,0x00,0x00,0x00,0xFF};
314 
315  mmc_read_block(cmd,Buffer,16);
316 
317  return(0);
318 }
319 
320 //############################################################################
321 //Routine zum lesen des CSD Registers von der MMC/SD-Karte (16Bytes)
322 unsigned char mmc_read_csd (unsigned char *Buffer)
323 //############################################################################
324 {
325  //Commando zum lesen des CSD Registers
326  unsigned char cmd[] = {0x49,0x00,0x00,0x00,0x00,0xFF};
327 
328  mmc_read_block(cmd,Buffer,16);
329 
330  return(0);
331 }
unsigned char mmc_read_byte(void)
Definition: mmc.c:135
unsigned char mmc_write_command(unsigned char *cmd)
Definition: mmc.c:99
#define nop()
Definition: mmc.h:72
unsigned char mmc_read_csd(unsigned char *Buffer)
Definition: mmc.c:322
#define MMC_Write
Definition: mmc.h:15
#define MMC_Disable()
Definition: mmc.h:63
unsigned char mmc_read_cid(unsigned char *Buffer)
Definition: mmc.c:309
unsigned char mmc_init()
Definition: mmc.c:32
#define MMC_Enable()
Definition: mmc.h:66
unsigned char mmc_write_sector(unsigned long addr, unsigned char *Buffer)
Definition: mmc.c:195
unsigned char mmc_read_sector(unsigned long addr, unsigned char *Buffer)
Definition: mmc.c:286
#define MMC_Direction_REG
Definition: mmc.h:17
void mmc_read_block(unsigned char *cmd, unsigned char *Buffer, unsigned int Bytes)
Definition: mmc.c:254
#define MMC_Read
Definition: mmc.h:16
void mmc_write_byte(unsigned char Byte)
Definition: mmc.c:166