Autor Tema: Comenzando con memorias SD/MMC. Librería a nivel hardware.  (Leído 158467 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Suky

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 6758
Comenzando con memorias SD/MMC. Librería a nivel hardware.
« en: 02 de Octubre de 2009, 15:22:22 »
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ón
En 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:
Código: C
  1. /** \brief Envia comando a memoria SD.-
  2.    
  3.    \param cmd: Comando a enviar.-
  4.    \param arg: Argumento del comando.-
  5.    \return res: Respuesta al comando.-
  6.    \return  0 a ocurrido algún error, 1 todo ok.-
  7. */
  8. int1 SDCard_send_command(int cmd, int32 arg,int& res){
  9.  
  10.    int Trama[6]; // Comando, Argumento y CRC
  11.    int i,ResTmp;
  12.    // Construimos el paquete a enviar.-
  13.    Trama[0] = cmd | 0x40;
  14.    Trama[1] = make8(arg, 3); // (arg>>24);
  15.    Trama[2] = make8(arg, 2); // (arg>>16);
  16.    Trama[3] = make8(arg, 1); // (arg>>8);
  17.    Trama[4] = make8(arg, 0);// arg;
  18.  
  19.    if(cmd==0){
  20.       Trama[5]=0x95;
  21.    }else{  
  22.       Trama[5]=0xFF;
  23.    }
  24.    // Enviamos clock para sincronizar envio.
  25.    for( i=0;i<16;i++) spi_xfer(SDCard,0xFF);
  26.    // Transfiere el paquete.-
  27.    spi_xfer(SDCard, Trama[0]);
  28.    spi_xfer(SDCard, Trama[1]);
  29.    spi_xfer(SDCard, Trama[2]);
  30.    spi_xfer(SDCard, Trama[3]);
  31.    spi_xfer(SDCard, Trama[4]);
  32.    spi_xfer(SDCard, Trama[5]);
  33.      
  34.    //  Se espera respuesta R1
  35.    i=0;
  36.    do{
  37.       ResTmp=spi_xfer(SDCard,0xFF);
  38.       i++;
  39.    }while((ResTmp&0x80)!=0 && i<200);// mientras no corresponda con 0xxxxxxx.-
  40.    if(i>=200){SDDeselect();return(0);}
  41.    res=ResTmp;  
  42.    return(1);
  43. }

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

Código: C
  1. /** \brief Inicialización de SD Card
  2.  
  3.    \param Ninguno
  4.    \return 1 si se ha iniciado correctamente, 0 caso contrario.
  5. */
  6. int1 SDCard_init(void){
  7. int i,Respuesta;
  8.    
  9.    SETUP_SPI(SPI_MASTER|SPI_CLK_DIV_16|SPI_H_TO_L|SPI_XMIT_L_TO_H );
  10.  
  11.    output_high(SD_CS);
  12.    delay_ms(20);
  13.    for(i=0;i<20;i++) spi_xfer(SDCard,0xFF);   // Para sincronización.
  14.    output_low(SD_CS);
  15.    delay_ms(20);
  16.    i=0;
  17.    do{
  18.       if(SDCard_send_command(CMD0,0x00,Respuesta)==0){
  19.          return(0);        // Si se recibe 0 error por timeout.-
  20.       }else{i++;}  
  21.    }while(((Respuesta&0x01)==0x00) && i<200);
  22.    if(i>=200){return(0);} // Timeout esperando desactivación de SD Card.
  23.    // Pasamos a esperar condición de SD Card activa.
  24.    // Si R1=0x01, SD Card en estado desactivado.
  25.       i=0;
  26.    do{
  27.       if(SDCard_send_command(CMD1,0x00,Respuesta)==0){
  28.          return(0);     // Si se recibe 0 error por timeout.-
  29.       }else{i++;}
  30.    }while(((Respuesta&0x01)==0x01) && (i<100)); // Mientras se reciba R1=0x01
  31.    if(i>=100){return(0);} // Timeout esperando activación de SD Card.
  32.    
  33.    // Se fija largo del bloque lectura/escritura.
  34.    if(SDCard_send_command(CMD16,BLOCK_SIZE,Respuesta)==0){
  35.       return(0);
  36.    }else if(Respuesta!=0){
  37.       return(0);
  38.    }
  39.    // Se desactiva CRC.
  40.    if(SDCard_send_command(CMD59,0,Respuesta)==0){
  41.       return(0);
  42.    }else if(Respuesta!=0){
  43.       return(0);
  44.    }
  45.    SDDeselect();
  46.    return(1);
  47. }



Post modificado para evitar crear uno nuevo con el mismo tema.
« Última modificación: 28 de Septiembre de 2011, 14:24:20 por MGLSOFT, Razón: Modificado a pedido de Suky, para agregar enlace a nuevo hilo... »
No contesto mensajes privados, las consultas en el foro

Desconectado Suky

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Comenzando con memorias SD/MMC. Librería a nivel hardware.
« Respuesta #1 en: 08 de Enero de 2010, 21:29:37 »
Operaciones de escritura y lectura.

Las operaciones de lectura y escritura se realizan enviando el comando correspondiente junto a la dirección del primer byte del bloque con el largo indicado anteriormente (Comando CMD16). El largo del bloque puede ser desde 1 hasta 512, y no esta permitido realizar operaciones en dos sectores a la vez, ósea que si el largo de bloque fijado en CMD16 es 512 la dirección para realizar lectura o escritura debe ser la del byte inicial del sector.

Realizando escritura de un sector.
Para realizar escritura de un único bloque debemos enviar el comando CMD24 indicando la dirección del bloque en el argumento de la función. La memoria al reconocer el comando envía la respuesta R1, donde puede indicar si hay algún error. Si todo es correcto el PIC debe enviar un token (0xFE) y luego los 512 datos del bloque más 2 bytes de CRC. Luego de enviado estos datos debemos quedar a la espera de una respuesta de la memoria indicando si los datos se han recibido correctamente o ha ocurrido un error, además de condición de desocupado.
Protocolo:
Respuesta:


Código: C
  1. /** \brief Realiza escritura de un bloque.-
  2.    
  3.    \param Address: Direccion del sector.-
  4.    \param Buffer: Buffer a escribir en memoria.-
  5.    \return  0 a ocurrido algún error, 1 todo ok.-
  6. */
  7. int1 SDCard_write_block(int32 Address,int *Buffer){
  8. int Respuesta,ResTmp;
  9. int16 i;
  10.  
  11.    SDSelect();
  12.    // Se envia comando para escribir bloque de bytes.-
  13.    if(SDCard_send_command(CMD24,Address,Respuesta)==0){
  14.       return(0);
  15.    }else if(Respuesta!=0){
  16.       return(0);
  17.    }
  18.    // Enviamos Token.
  19.    spi_xfer(SDCard,0xFE);
  20.    // Enviamos data.-
  21.    for(i=0;i<BLOCK_SIZE;i++){
  22.       spi_xfer(SDCard,*Buffer++);
  23.    }
  24.    // Ignoramos CRC.-
  25.    spi_xfer(SDCard,0xFF);
  26.    spi_xfer(SDCard,0xFF);
  27.    // Esperamos respuesta.-
  28.    i=0;
  29.    do{
  30.       ResTmp=spi_xfer(SDCard,0xFF);
  31.       i++;
  32.    }while(ResTmp==0xFF && i<100);// Mientras sea 0xFF.-
  33.    if(i==100){SDDeselect();return(0);}
  34.    if((ResTmp&0x1F)!=0x05){ // Si no se recibe ***00101.-
  35.       SDDeselect();
  36.       return(0);
  37.    }
  38.    // Esperamos a que baje la linea, indicando escritura completa.-
  39.    while(spi_xfer(SDCard,0xFF)==0);
  40.    SDDeselect();
  41.    return(1);  
  42. }

Realizando lectura de un sector.

Para realizar una lectura debemos enviar el comando CMD17 indicando en el argumento la dirección del bloque. Luego se espera la respuesta R1 desde la memoria, si todo es correcto se pasa a recibir el token y luego los datos, la cantidad es establecida por el largo del bloque. (CMD16)


Código: C
  1. /** \brief Realiza lectura de un bloque.-
  2.    
  3.    \param Address: Direccion del sector.-
  4.    \return Buffer: Buffer donde se almacena lectura de memoria.-
  5.    \return  0 a  ocurrido algún error, 1 todo ok.-
  6. */
  7. int1 SDCard_read_block(int32 Address,int *Buffer){
  8. int Respuesta, TokenTmp;
  9. int16 i;
  10.    // Se envia comando para leer bloque de bytes.-
  11.       SDSelect();
  12.    if(SDCard_send_command(CMD17,Address,Respuesta)==0){
  13.       return(0);
  14.    }else if(Respuesta!=0){
  15.       return(0);
  16.    }  
  17.    // Pasamos a esperar Token.
  18.    i=0;
  19.    do{
  20.       TokenTmp=spi_xfer(SDCard,0xFF);
  21.       i++;
  22.    }while(TokenTmp==0xFF && i<100);// Mientras sea 0xFF.-
  23.    if(i==100){SDDeselect();return(0);}
  24.    if((TokenTmp&0xE0)==0){ // Si se recibe 000xxxxx y no 0xFE.-
  25.       SDDeselect();
  26.       return(0);
  27.    }
  28.       // Todo ok, recibimos data.-
  29.    for(i=0;i<BLOCK_SIZE;i++){
  30.       *Buffer++=spi_xfer(SDCard,0xFF);
  31.    }
  32.    // Ignoramos CRC.-
  33.    spi_xfer(SDCard,0xFF);
  34.    spi_xfer(SDCard,0xFF);
  35.    
  36.    SDDeselect();
  37.    return(1);  
  38. }

Registros CSD y CID
La librería también tiene funciones dedicadas a la lectura de los registros CSD y CID. En el manual de producto de las memorias SD Card de Scandisk a partir de la página 37 se indica los parámetros que devuelven estos registros.
No contesto mensajes privados, las consultas en el foro

Desconectado Suky

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Comenzando con memorias SD/MMC. Librería a nivel hardware.
« Respuesta #2 en: 08 de Enero de 2010, 21:30:53 »
Se adjunta librería para comunicación con memoria a nivel hard, código para probar librería y simulación en proteus. Por aquí pueden bajar una imagen para realizar algunas pruebas.
Ejecutando el ejemplo de prueba obtendrán el siguiente debug mediante RS232:


También utilizando el soft WinHex pueden abrir la imagen y ver que los datos se han grabado correctamente:



Saludos!
« Última modificación: 08 de Enero de 2010, 21:48:03 por Suky »
No contesto mensajes privados, las consultas en el foro

Desconectado Chenao

  • PIC18
  • ****
  • Mensajes: 414
Re: Comenzando con memorias SD/MMC. Librería a nivel hardware.
« Respuesta #3 en: 08 de Enero de 2010, 22:13:29 »
Hola Profesor Suky:

Impresionante, leeí el hilo y ya se aclararon mucha dudas  :D, no mentiras dudas son las que tengo, Suky muchas gracias por compartir tu conocimientos con los novatos y lo mejor de forma desinterezada, yo también he estado trabajando sin descanso desde ya 15 días con las memoria sd, leyendo sacando resumenes etc. Y gracias a tu ayuda he podido programar ya 4 funciones de la memoria que son (reiniciar, inicializar, tamaño del bucle, y la lectura que la acabe de programar), voy a estar pendiente y trabajando duro si es posible las 24 horas del día haber si entre todos desmañaramos a la memoria sd.

Bueno, acá pongo un granito de arena es un resumen que lo he modificado (cortodó, pegado) algunas cosas espero que les sirva a todo los que quieren empezar con está targeta.

Nota: Al menos tomaste la idea de Comenzado con la memoria xxxx :D :D :D 
Un saludo desde Pereira - Colombia

Desconectado Suky

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Comenzando con memorias SD/MMC. Librería a nivel hardware.
« Respuesta #4 en: 08 de Enero de 2010, 23:22:09 »
Nota: Al menos tomaste la idea de Comenzado con la memoria xxxx :D :D :D 

Seee!  :D :D

Hoy haciendo el resumen y re-leyendo el manual de especificaciones me di cuenta que había entendido algo mal  :oops: Se pueden escribir bloques de 1 a 512 bytes siempre y cuando se trabaje en una sola página o sector de la memoria. Aunque trabajar cambiando constantemente el tamaño del bloque de datos puede ser un poco engorroso.  :?


Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado Chenao

  • PIC18
  • ****
  • Mensajes: 414
Re: Comenzando con memorias SD/MMC. Librería a nivel hardware.
« Respuesta #5 en: 08 de Enero de 2010, 23:54:38 »

Suky sigo dandome golpes en la cabeza con la memoria  :5]. Revisando lo que leí el post, y de acuerdo con mi rutina de inicio el decir el comando CMD0 me di cuenta que tenia un error segun mi rutina.

Cuando retorna un 1 -------- Error
Cuando retorna un 0 -------- Todo bien

Pero siempre que llamo la rutina me aparece un "1 error" :5]

he revisado y no encuentro el error no se que pueda pasar. Acá pongo las rutinas

Citar
int init_mmc()
  {
   
    OUTPUT_HIGH(PIN_C2);
    SETUP_SPI(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_16 | SPI_SS_DISABLED);
    for(i=0; i<10; i++)
      {
        SPI_WRITE(0XFF);             // espero a que se inicialice la memoria que van desde 8 a 10 pulso del reloj
      }
    OUTPUT_LOW(PIN_C2);             // Activo la targeta
    SPI_WRITE(0X40);
    SPI_WRITE(0X00);
    SPI_WRITE(0X00);
    SPI_WRITE(0X00);
    SPI_WRITE(0X00);
    SPI_WRITE(0X95);                // Comando CMDO datos a enviar
    if(mmc_respuesta(0x01)==1)
     {
       return 1;                    // Error en memoria por que se supero el tiempo
     }
    OUTPUT_HIGH(PIN_C2);
    return 0;                     // Todo bien
  }


La rutina de la función mmc_respuesta(xxx)

Citar
int mmc_respuesta(unsigned char respuesta)
  {
    unsigned long espera = 0xFFFF;
    while(SPI_READ(0xFF) != respuesta && --espera > 0);
    if(espera==0) return 1;
    else return 0;
  }

He revisado y rectificado y no se que pasá, hechale una miraita y comentas si voy bien o definitavamente o a cambiarme de profesión :D :D :D.

Saludos.
Un saludo desde Pereira - Colombia

Desconectado Chenao

  • PIC18
  • ****
  • Mensajes: 414
Re: Comenzando con memorias SD/MMC. Librería a nivel hardware.
« Respuesta #6 en: 09 de Enero de 2010, 20:12:53 »
Hola Suky.

Te tengo una consultica :mrgreen: y es la siguiente:

y es en código que pusiste para la escritura de un bloque de 512 bytes

Citar
if((ResTmp&0x1F)!=0x05){


Porque realizas la and lógica con 0x1f no comprendo como logras el 5 con esta operación :shock: :shock:.

Y la otra no sé si te la sepas he buscado y no encuentro nada.

Cual es la diferencia entre SPI_READ(XXXX) y la función SPI_READ()

Saludos.
 
Un saludo desde Pereira - Colombia

Desconectado Suky

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Comenzando con memorias SD/MMC. Librería a nivel hardware.
« Respuesta #7 en: 09 de Enero de 2010, 21:20:29 »

Suky sigo dandome golpes en la cabeza con la memoria  :5]. Revisando lo que leí el post, y de acuerdo con mi rutina de inicio el decir el comando CMD0 me di cuenta que tenia un error segun mi rutina.

Cuando retorna un 1 -------- Error
Cuando retorna un 0 -------- Todo bien

Pero siempre que llamo la rutina me aparece un "1 error" :5]

he revisado y no encuentro el error no se que pueda pasar. Acá pongo las rutinas

Citar
int init_mmc()
  {
   
    OUTPUT_HIGH(PIN_C2);
    SETUP_SPI(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_16 | SPI_SS_DISABLED);
    for(i=0; i<10; i++)
      {
        SPI_WRITE(0XFF);             // espero a que se inicialice la memoria que van desde 8 a 10 pulso del reloj
      }
    OUTPUT_LOW(PIN_C2);             // Activo la tarjeta
    SPI_WRITE(0X40);
    SPI_WRITE(0X00);
    SPI_WRITE(0X00);
    SPI_WRITE(0X00);
    SPI_WRITE(0X00);
    SPI_WRITE(0X95);                // Comando CMDO datos a enviar
    if(mmc_respuesta(0x01)==1)
     {
       return 1;                    // Error en memoria por que se supero el tiempo
     }
    OUTPUT_HIGH(PIN_C2);
    return 0;                     // Todo bien
  }


La rutina de la función mmc_respuesta(xxx)

Citar
int mmc_respuesta(unsigned char respuesta)
  {
    unsigned long espera = 0xFFFF;
    while(SPI_READ(0xFF) != respuesta && --espera > 0);
    if(espera==0) return 1;
    else return 0;
  }

He revisado y rectificado y no se que pasá, hechale una miraita y comentas si voy bien o definitavamente o a cambiarme de profesión :D :D :D.

Saludos.

Prueba modificando la configuración del SPI a :

Código: C
  1. SETUP_SPI(SPI_MASTER|SPI_CLK_DIV_16|SPI_H_TO_L|SPI_XMIT_L_TO_H );

Luego agrega un par de ciclos de reloj antes de enviar el comando:

Código: C
  1. for(i=0; i<10; i++) SPI_WRITE(0XFF);
  2.     OUTPUT_LOW(PIN_C2);             // Activo la tarjeta
  3.     for(i=0; i<10; i++) SPI_WRITE(0XFF);

Creo que con eso se soluciona el problema  :?


Hola Suky.

Te tengo una consultica :mrgreen: y es la siguiente:

y es en código que pusiste para la escritura de un bloque de 512 bytes

Citar
if((ResTmp&0x1F)!=0x05){


Porque realizas la and lógica con 0x1f no comprendo como logras el 5 con esta operación :shock: :shock:.

Y la otra no sé si te la sepas he buscado y no encuentro nada.

Cual es la diferencia entre SPI_READ(XXXX) y la función SPI_READ()

Saludos.
 

Lo que hago con ResTmp&0x1F es aplicar una mascara para solo dejar los bits 0..4 de la variable ResTmp y después comparar si es 0x05 u otro.

Luego, SPI_READ(0xFF)  queda a la espera de un byte desde un dispositivo (Envia clock), pero además carga el valor dentro del paréntesis en SDO. Fíjate que la memoria necesita que SDO sea 1 cuando está en reposo.


Saludos!


No contesto mensajes privados, las consultas en el foro

Desconectado Chenao

  • PIC18
  • ****
  • Mensajes: 414
Re: Comenzando con memorias SD/MMC. Librería a nivel hardware.
« Respuesta #8 en: 10 de Enero de 2010, 14:01:15 »
Hola Suky.

Citar
Lo que hago con ResTmp&0x1F es aplicar una mascara para solo dejar los bits 0..4 de la variable ResTmp y después comparar si es 0x05 u otro.
.

En resumidas estas haciendo lo siguiente (xxxxxxxx)&(00011111)=(000xxxxx) para poder compararlo con (00000101)=(0x05)=5 en decimal, que en este caso es la repuesta de la memoria al los datos guardados, es decir que si se guardaron correctamente.

Citar
Luego, SPI_READ(0xFF)  queda a la espera de un byte desde un dispositivo (Envia clock), pero además carga el valor dentro del paréntesis en SDO. Fíjate que la memoria necesita que SDO sea 1 cuando está en reposo.
.

Y con está instrucción estoy garantizando que siempre se estes enviando datos a la memoria por el registro SSPBUF, para que la memoria este áctiva.

Suky estuve revisando tu post en ucontrol, estuve haciendo algunos cálculos simple y me resulto una inquietud por que pones un oscilador de 48MHz para conseguir un frecuencia del clock (slk) de 750KHz "no es una frecuencia muy alta". :?

Citar
Prueba modificando la configuración del SPI a :


Código
GeSHi (c):SETUP_SPI(SPI_MASTER|SPI_CLK_DIV_16|SPI_H_TO_L|SPI_XMIT_L_TO_H );
Luego agrega un par de ciclos de reloj antes de enviar el comando:


Código
GeSHi (c):    for(i=0; i<10; i++) SPI_WRITE(0XFF);    OUTPUT_LOW(PIN_C2);             // Activo la tarjeta    for(i=0; i<10; i++) SPI_WRITE(0XFF);
Creo que con eso se soluciona el problema 

Muchas gracias por los tips ya me pongo a probarlos, pero creo donde puede haber un problema y es en la siguiente línea.

Código: [Seleccionar]
  while(SPI_READ(0xFF) != respuesta && --espera > 0);

Nota la condición --espera > 0 hay un postdecremento, es decir, se decrementa sin hacer el ciclo lo cual cuando no esta en ciclo se está decrementando, por lo tanto creo que la instrución debé ser así:

Citar
  while(SPI_READ(0xFF) != respuesta && espera-- > 0);
 

Creo que esto puede ayudar. De todas formas ya se nota el trabajo cada día aprendo nuevas cosas acerca de esté monacho y cada vez se vuelve más complicado (resultan nuevas dudas), pero con trabajo, diciplina y esfuerzo se logra todo. Saludos. ;-)
 
Un saludo desde Pereira - Colombia

Desconectado Suky

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Comenzando con memorias SD/MMC. Librería a nivel hardware.
« Respuesta #9 en: 10 de Enero de 2010, 19:14:48 »
Suky estuve revisando tu post en ucontrol, estuve haciendo algunos cálculos simple y me resulto una inquietud por que pones un oscilador de 48MHz para conseguir un frecuencia del clock (slk) de 750KHz "no es una frecuencia muy alta". :?

La frecuencia es 48MHz/16, ósea 3 MHz, pero se puede usar /4, para usar 12MHz que funciona correctamente.

Hay que hacer --espera==0, por utilizar un unsigned char, no me percate de eso   :mrgreen: Así trabajaría de la siguiente manera, leemos un byte por SPI, es igual a respuesta? No, decrementamos cuenta, es cuenta igual a 0? Si, salimos, ....


Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado Chenao

  • PIC18
  • ****
  • Mensajes: 414
Re: Comenzando con memorias SD/MMC. Librería a nivel hardware.
« Respuesta #10 en: 10 de Enero de 2010, 20:31:46 »
Hola Suky

mmmm. Estoy confundido :oops:. Según mi función:

Citar
int mmc_respuesta(unsigned char respuesta)
  {
    unsigned long espera = 0xFFFF;
    while(SPI_READ(0xFF) != respuesta && --espera > 0);
    if(espera==0) return 1;
    else return 0;
  }

Citar
Hay que hacer --espera==0, por utilizar un unsigned char, no me percate de eso    Así trabajaría de la siguiente manera, leemos un byte por SPI, es igual a respuesta? No, decrementamos cuenta, es cuenta igual a 0? Si, salimos, ....

Según la rutina la que es de tipo unsigned char es respuesta que es el parámetro que se carga en la función cuando se va ha llamar desde cualqiuier parte del programa mientras espera es de tipo unsigned long entonce no veo porque se debe utiliza --espera. Suky acá creo que es el problema de mi programa.

Casi se me olvida, revisando tu post de Ucontro nuevamente :mrgreen:, hay un arreglo llamado Buffer [512]="xxxxxxxx"
esté arreglo tan "grande" pone problemas en mi compilador (que sólo funciona con 12fxx y 16fxxxx) y creo que porque 512 bytes supera la memoria RAM del micro (16F877) que es como el más grandesito que puedo simular :( . Es un mensaje constructivo por si alguién ha tenido problemas.

Saludos
Un saludo desde Pereira - Colombia

Desconectado Suky

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Comenzando con memorias SD/MMC. Librería a nivel hardware.
« Respuesta #11 en: 11 de Enero de 2010, 00:12:59 »
Discúlpame a mi que metí la pata  :oops: No me concentre!  :oops: Se debe colocar --espera>0 o --espera!=0, (Como lo tenias) así espera mientras sea distinto de 0. Fíjate que al comenzar cargas espera con 0xFF, entonces la rutina haría lo siguiente: Lee un byte por SPI, si no es la respuesta pasa a decrementar espera, osea 0xFFFE, como es mayor a cero sigue dentro del while.


Con respecto al Buffer, en los pic de la familia 16F no lo vas a poder implementar. Podes utilizar buffer de 128 datos, y trabajarlos de forma correcta. Con esto me refiero a tener precaución en la dirección inicial a escribir para no trabajar en 2 sectores a la vez que según manual de características no esta permitido. Yo no he trabajado con escritura parcial de sectores así habría que hacer la prueba  :mrgreen:

Saludos!

No contesto mensajes privados, las consultas en el foro

Desconectado Chenao

  • PIC18
  • ****
  • Mensajes: 414
Re: Comenzando con memorias SD/MMC. Librería a nivel hardware.
« Respuesta #12 en: 11 de Enero de 2010, 13:01:58 »
Hola Suky.

Continua las pruebas :mrgreen:.

he modificado una cosita, haber si estas deacuerdo. La siguiente líneas son equivalentes a estás otras:

Citar
int mmc_respuesta(unsigned char respuesta)
  {
    while(SPI_READ(0xFF) != respuesta && --espera > 0);
  }

Equivalente a:

Citar
while(SPI_READ(0XFF) != respuesta && espera> 0)
     {
       espera= espera - 1;
     }

Ya estoy dudando de lo poco que se de C :D :D :D, esta memoria ya no me deja ni dormir  :D :D :D, pero hay vamos.

Con estas otras líneas se arregla el problema, será que el compilador no acepta --espera.

Saludos.
Un saludo desde Pereira - Colombia

Desconectado RICHI777

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1498
Re: Comenzando con memorias SD/MMC. Librería a nivel hardware.
« Respuesta #13 en: 11 de Enero de 2010, 17:55:10 »
Suky, muy bueno el post, lo único que tengo para comentar es que ese tipo de timeouts son muy dependientes de la velocidad a la que corre el micro y del compilador. No tenes ningún timer desocupado ?

Saludos !

Desconectado Slalen

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1079
    • Página web personal de Guillermo Herrero González
Re: Comenzando con memorias SD/MMC. Librería a nivel hardware.
« Respuesta #14 en: 11 de Enero de 2010, 19:17:37 »
Joder maestro, te dejo solo unos días y la que lías!!!!! :D :D :D :D

Ahora en serio, a ver si puedo retomarlo ya que ahora estoy muy liado con otro proyecto más rentable económicamente hablando (ya que voy a ganar algo de dinero porque con la sd....)

Una vez más, gracias por tu ayuda!!!



 

anything