FTPmicro Tutorial – SD.c

Le schede di memoria MMC/SD hanno diverse modalità di comunicazione (alcune opzionali), in particolare le memorie di tipo SD (Secure Digital) supportano sempre il protocollo SPI ed il protocollo nativo ad 1bit.

La comunicazione avviene attraverso l'invio di diversi comandi, ai quale segue sempre una risposta da parte della memoria.
Per entrare in modalità SPI, è sufficiente portare il segnale CS basso durante l'invio del comando CMD0 (Che porta il dispositivo in Idle Mode).
A questo punto, per terminare l'inizializzazione, è necessario inviare il comando ACMD41 finchè la SD non esce dallo stato Idle (lo status è contenuto nel primo byte di una risposta).
Il comando ACMD41, però, è di tipo Application-Specific perciò esso è sempre preceduto dal comando CMD55.

char SDInit()	
{
	char i;
	char status;
	
	TRISCbits.TRISC5 = 0;
	TRISCbits.TRISC4 = 1;
	TRISCbits.TRISC3 = 0;
	SSP1STAT = 0x00;
	SSP1CON1 = 0x30;			// SPI master, Fosc/4
	PIR1bits.SSP1IF = 0;
	SD_CS_TRIS = 0;
	SD_CS = 1; 		

	for(i=0; i < 16; i++)
		spi(0xFF);			// Clock extra per il powerup	

	SD_CS = 0;

	SDCmd(CMD0, 0);				// Invia il comando di reset
	if (SDWait()!=0x01)
			goto SDError;

	i = 20;
	do {
		SDCmd(CMD55, 0);
		SDWait();
		SDCmd(ACMD41,  0);		// Invia il comando ACMD41 per terminare l'inizializzazione
		if (i-- < 0)
			goto SDError;
	} while ((SDWait()&1) != 0x00); 	// attende l'uscita dallo stato Idle

	SD_CS = 1;
	return	TRUE;
SDError:
	SD_CS = 1;
	return FALSE;
}

Con il metodo SDInit viene configurato il modulo SPI e vengono effettuate le operazioni appena descritte per inizializzare la memoria SD.

In questo frammento di codice si fa uso di due metodi: SDCmd serve ad inviare un comando alla scheda, mentre con SDWait si attende la risposta.

char SDCmd(char cmd, unsigned long param)
{
	spi(0xFF);				// extra clock
	spi(cmd);				// command
	spi(param >> 24);
	spi(param >> 16);
	spi(param >> 8);
	spi(param);
	spi(cmd == CMD0 ? 0x95 : 0xFF);		// CRC, obbligatorio solo per CMD0
}

char SDWait(void)
{
	unsigned short count = 0xFF;
	char response;

	while((response=spi(0xFF)) == 0xFF && --count > 0);
// attende una risposta diversa da 0xFF, con timeout

	return response;
}

Infine, il metodo che ci permette di leggere dalla memoria, sfruttando il comando CMD17 è SDReadSector.
La lettura deve avvenire a blocchi di n byte, dove n per default vale 512.

char SDReadSector(unsigned long sector)
{
	int i;
	char* buf_pt = &sd_buffer[0];
	char status;

	SD_CS = 0;
	SDCmd(CMD17, (sector * SECTOR_SIZE));	// legge a partire dal byte sector*512

	if(SDWait()!=0x00 || SDWait()!=0xFE)
//attende prima una risposta al comando, poi attende l'inizio del campo dati
	{
		SD_CS = 1;
		sdPresent = FALSE;	
// se la lettura fallisce, si suppone che la SD sia stata rimossa
		return FALSE;   		
	}

	for (i = 0; i < SECTOR_SIZE; i++)
		buf_pt[i] = spi(0xFF);		// read block

	spi(0xFF);
	spi(0xFF); 				// flush CRC

	SD_CS = 1;
	return	TRUE;
}

Il settore letto viene memorizzato in un buffer, che per la sua dimensione deve essere collocato esattamente in due banchi RAM, grazie alla direttiva pragma; inoltre questa zona deve essere dichiarata protetta nel linker, affinchè non venga occupata da altre variabili.

Tutta la documentazione su FTPmicro è disponibile a questa pagina FTPmicro per Utenti Premium.
Potete realizzarlo da soli (fai-da-te) scaricando tutti i codici sorgenti (Schema elettrico realizzato con Orcad, lista parti, circuito stampato realizzato con Orcad, file gerber, codice sorgente assembler realizzato su piattaforma Microchip).

Il progetto montato e collaudato è disponibile sul nostro store --> FTPmicro

Scarica subito una copia gratis

Scrivi un commento

Seguici anche sul tuo Social Network preferito!

Send this to a friend