Creo/modifico este hilo para comenzar de forma ordenada la presentación de la librería para manejo de memoria SD Card a nivel hardware adjuntada en
microSD por puerto SPI del micro 18f4550 . Presentándola y dando un pequeño resumen de lo que se trata, dado que he recibido varios MP con preguntas similares que podremos tratar en este hilo.
IntroducciónEn muchas aplicaciones de sistemas embebidos es necesario almacenar grandes cantidades de datos en donde las memorias seriales EEPROM son insuficientes, además de que no son portables y leerlas en una computadora requieren de un hardware adicional. En este caso el uso de las memorias flash (SD/MMC) nos brinda una gran ventaja, otorgándonos gran capacidad de almacenamiento, una interface física/eléctrica sencilla y gran disponibilidad en el mercado a costos reducidos.
Estas memorias poseen dos maneras de comunicación, la estándar denominado BUS SD que utiliza 4 líneas paralelas para la comunicación (1 Nible de ancho de bus) y comunicación serial SPI. Es esta última forma de comunicación la razón por la cual es sencillo utilizarlo en sistemas embebidos, donde la mayoría de los microcontroladores disponen de interface SPI.
Pin-out memorias SD/MMC.Hardware mínimo para su utilización.Librería a nivel hardware.Esta librería esta creada a partir de las
especificaciones de las memorias SD de Scandisk. Con la ésta se puede inicializar la memoria en modo SPI, escribir/leer sectores de la misma (512 Bytes), leer los registros CSD y CID.
Envío de comandos y respuestas.
Los comandos tienen un tamaño fijo de 6 bytes, donde el formato es el siguiente:
Comandos y argumentos utilizados:
Vemos que al utilizar estos comandos solo vamos a recibir respuesta del tipo R1 y R1b:
RB1 es idéntica a R1, solo que luego de recibir la respuesta hay que esperar condición de memoria desocupada en donde la línea SDO de la memoria se lleva a nivel de 0 lógico.
Función que envía comando y espera respuesta:/** \brief Envia comando a memoria SD.-
\param cmd: Comando a enviar.-
\param arg: Argumento del comando.-
\return res: Respuesta al comando.-
\return 0 a ocurrido algún error, 1 todo ok.-
*/
int1 SDCard_send_command(int cmd, int32 arg,int& res){
int Trama[6]; // Comando, Argumento y CRC
int i,ResTmp;
// Construimos el paquete a enviar.-
Trama[0] = cmd | 0x40;
Trama[1] = make8(arg, 3); // (arg>>24);
Trama[2] = make8(arg, 2); // (arg>>16);
Trama[3] = make8(arg, 1); // (arg>>8);
Trama[4] = make8(arg, 0);// arg;
if(cmd==0){
Trama[5]=0x95;
}else{
Trama[5]=0xFF;
}
// Enviamos clock para sincronizar envio.
for( i=0;i<16;i++) spi_xfer(SDCard,0xFF);
// Transfiere el paquete.-
spi_xfer(SDCard, Trama[0]);
spi_xfer(SDCard, Trama[1]);
spi_xfer(SDCard, Trama[2]);
spi_xfer(SDCard, Trama[3]);
spi_xfer(SDCard, Trama[4]);
spi_xfer(SDCard, Trama[5]);
// Se espera respuesta R1
i=0;
do{
ResTmp=spi_xfer(SDCard,0xFF);
i++;
}while((ResTmp&0x80)!=0 && i<200);// mientras no corresponda con 0xxxxxxx.-
if(i>=200){SDDeselect();return(0);}
res=ResTmp;
return(1);
}
Inicialización en modo SPI:Al iniciar la memoria se establece en modo SD. Para entrar en modo SPI se debe enviar el comando CMD0 con el pin CS a 0V, si la memoria reconoce que petición de cambio de protocolo responde con la respuesta R1.
Luego de haber fijado el protocolo SPI procedemos a encender la memoria y configurar algunos parámetros de trabajo, como largo del bloque para lectura y escritura, fijar modo CRC, etc.
NOTA: Por aquí una versión actualizada para SD Card HC :
http://www.todopic.com.ar/foros/index.php?topic=27786.msg300924#msg300924/** \brief Inicialización de SD Card
\param Ninguno
\return 1 si se ha iniciado correctamente, 0 caso contrario.
*/
int1 SDCard_init(void){
int i,Respuesta;
SETUP_SPI(SPI_MASTER|SPI_CLK_DIV_16|SPI_H_TO_L|SPI_XMIT_L_TO_H );
output_high(SD_CS);
delay_ms(20);
for(i=0;i<20;i++) spi_xfer(SDCard,0xFF); // Para sincronización.
output_low(SD_CS);
delay_ms(20);
i=0;
do{
if(SDCard_send_command(CMD0,0x00,Respuesta)==0){
return(0); // Si se recibe 0 error por timeout.-
}else{i++;}
}while(((Respuesta&0x01)==0x00) && i<200);
if(i>=200){return(0);} // Timeout esperando desactivación de SD Card.
// Pasamos a esperar condición de SD Card activa.
// Si R1=0x01, SD Card en estado desactivado.
i=0;
do{
if(SDCard_send_command(CMD1,0x00,Respuesta)==0){
return(0); // Si se recibe 0 error por timeout.-
}else{i++;}
}while(((Respuesta&0x01)==0x01) && (i<100)); // Mientras se reciba R1=0x01
if(i>=100){return(0);} // Timeout esperando activación de SD Card.
// Se fija largo del bloque lectura/escritura.
if(SDCard_send_command(CMD16,BLOCK_SIZE,Respuesta)==0){
return(0);
}else if(Respuesta!=0){
return(0);
}
// Se desactiva CRC.
if(SDCard_send_command(CMD59,0,Respuesta)==0){
return(0);
}else if(Respuesta!=0){
return(0);
}
SDDeselect();
return(1);
}
Post modificado para evitar crear uno nuevo con el mismo tema.