Nota: Al menos tomaste la idea de Comenzado con la memoria xxxx :D :D :D
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
}
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;
}
if((ResTmp&0x1F)!=0x05){
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 rutinasCitarint 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)Citarint 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.
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 bytesCitarif((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..
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
while(SPI_READ(0xFF) != respuesta && --espera > 0);
while(SPI_READ(0xFF) != respuesta && espera-- > 0);
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". :?
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;
}
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, ....
int mmc_respuesta(unsigned char respuesta)
{
while(SPI_READ(0xFF) != respuesta && --espera > 0);
}
while(SPI_READ(0XFF) != respuesta && espera> 0)
{
espera= espera - 1;
}
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 !
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!!!
Citarwhile(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.
No entiendo naa! Si es lo mismo!
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;
}
}
int mmc_respuesta(unsigned char respuesta)Así me funciona haciendo lo mismo pero de diferente forma creo que el compilador que tengo no acepta bien --espera > 0 debe poner problemas. Creo que ese era el problema porque la una funciona bien y la otra mal pero deberian hacer lo mismo, no se si estoy equivocado pero muchas gracias por la atención.
{
unsigned long espera = 0xFFFF;
while(SPI_READ(0xFF) != respuesta && espera > 0)
{
espera = espera - 1;
}
if(espera==0) return 1;
else return 0;
}
int init_mmc()
{
SETUP_SPI(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_16 | SPI_XMIT_L_TO_H);
OUTPUT_HIGH(PIN_C2);
for(i=0; i<20; 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
for(i=0; i<20; i++)
{
SPI_WRITE(0XFF); // espero a que se inicialice la memoria que van desde 8 a 10 pulso del reloj
}
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;
}
int mmc_respuesta(unsigned char respuesta)
{
unsigned long espera = 0xFFFF;
while(SPI_READ(0xFF) != respuesta && espera> 0)
{
espera= espera - 1;
}
if(espera==0)
{
return 1; // se ha superado el tiempo
}
else
{
return 0;
}
}int inicializacion_mmc()
{
OUTPUT_HIGH(PIN_C2);
for(i=0; i<16; i++)
{
SPI_WRITE(0xFF);
}
OUTPUT_LOW(PIN_C2);
{
SPI_WRITE(0xFF);
}
i = 0;
do
{
SPI_WRITE(0x41); // Envia comando hasta que de la respuesta y hasta que se cumpla el tiempo
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0xFF); // Secuencia del comando CMD1
i= i + 1;
}
while(i<250 && mmc_respuesta(0x00)==1);
if(i==250)
{
return 1; // si se supera el tiempo de respuesta no se ha inicializado bien la targeta
}
OUTPUT_HIGH(PIN_C2);
for(i=0; i<16; i++) // Alguno cloks para estabilizar la comunicación
{
SPI_WRITE(0xFF);
}
OUTPUT_LOW(PIN_C2);
for(i=0; i<16; i++)
{
SPI_WRITE(0XFF);
}
SPI_WRITE(0x50);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x02);
SPI_WRITE(0x00);
SPI_WRITE(0xFF); // Comando CMD16 para configurarlo de 512 bytes
if(mmc_respuesta(0x00)==1)
{
return 1; // se ha inicializado incorrectamente
}
OUTPUT_HIGH(PIN_C2);
return 0; // se ha inicializado correctamente
}
(resp&0x0f=!0x05)siempe está operación lógica me da 0x01 y no se porque lo he revisado una y otra vez no se pueda pasar :shock:.int mmc_escribir_bloque()
{
resp = 0;
OUTPUT_HIGH(PIN_C2);
for(i=0; i<16; i++)
{
SPI_WRITE(0xFF); // Unos cuantos ciclos del reloj
}
OUTPUT_LOW(PIN_C2);
for(i=0; i<16; i++)
{
SPI_WRITE(0xFF); // Espero a que se estabilice la memoria
}
SPI_WRITE(0x58);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x02);
SPI_WRITE(0x00);
SPI_WRITE(0xFF); // Comando CMD24 pero escribé en el segundo bloque 0x200
if((mmc_respuesta(0x00))==0x01) // Espero la respuesta RB1
{
return 1; // no respondio correctamente la memoria
}
SPI_WRITE(0xFE); // Envio el token de inicio
for(i=0; i<512; i++)
{
SPI_WRITE(0x17); // Escribó 512 % que en hex es 0x25
}
SPI_WRITE(0xFF);
SPI_WRITE(0xFF); // espero ha que se estabilice o envio 2 CRC
i=0;
do
{
resp = SPI_READ(0xFF);
i=i+1;
}
while(i!=200 && resp==0xFF);
if(i==200) // Se ha superado el tiempo
{
return 1;
}
if((resp&0x0F)!=0x05)
{
return 1; // No se escribio correctamente el bloque de 512 bytes dirente de 00101
}
OUTPUT_HIGH(PIN_C2);
return 0;
}
void main()
{
int lectura;
set_tris_c(0x93);
disable_interrupts(global);
retorno = init_mmc();
if(retorno==0x01)
{
printf("Error en memoria");
}
else
{
retorno = inicializacion_mmc();
if(retorno==0x01)
{
printf("error");
}
else
{
retorno=mmc_escribir_bloque();
if(retorno==0x01)
{
printf("No se pudo escribir el bloque\r");
}
else
{
printf("Escritura realizada");
}
}
}
while(;)
}
#byte resp = 0x20
#byte and = 0x21
#byte retorno = 0x22El cambio de imagen a la memoria no va a cambiar el modo de funcionar (Como esta programado en proteus) de ella, seguramente es necesario como inicialización enviar estos dos comandos sin desactivar la memoria en el proceso.
int init_mmc()
{
SETUP_SPI(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_16 | SPI_XMIT_L_TO_H);
OUTPUT_HIGH(PIN_C2);
for(i=0; i<20; 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
for(i=0; i<20; i++)
{
SPI_WRITE(0xFF); // espero a que se inicialice la memoria que van desde 8 a 10 pulso del reloj
}
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
}
do
{
SPI_WRITE(0x41); // Envia comando hasta que de la respuesta y hasta que se cumpla el tiempo
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0xFF); // Secuencia del comando CMD1
i= i + 1;
}
while((i<250) && (mmc_respuesta(0x00)==0x01));
if(i>=250)
{
return 1; // si se supera el tiempo de respuesta no se ha inicializado bien la targeta
}
OUTPUT_LOW(PIN_C2);
for(i=0; i<16; i++)
{
SPI_WRITE(0xFF);
}
SPI_WRITE(0x50);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x02);
SPI_WRITE(0x00);
SPI_WRITE(0xFF); // Comando CMD16 para configurarlo de 512 bytes
if((mmc_respuesta(0x00))==0x01)
{
return 1; // se ha inicializado incorrectamente
}
OUTPUT_HIGH(PIN_C2);
return 0; // se ha inicializado correctamente
}
Gracias profe por la fecitación se hace lo que se puede :D :D :D.
Que cosa lo del socalo a buscar donde puedo conseguirme uno haber si me hecho con cautin a la mano y con mano en el teclado para superar tu proyecto :mrgreen:.
Saludos.
Guarda que mi proyecto no esta terminado!
Respecto a la pregunta numero 2, en las pruebas que desarrollaste, necesitaste borrar el sector para escribirlo?
Uff! Que semestre!!! Yo ya pasé por eso esfuerzos mentales
Respecto a la memoria, coincidimos en el numero de bytes, pero cada sector tiene 512 bytes, entonces el ultimo sector sería 16777216-512=0xFFFE00.
int mmc_erase()
{
OUTPUT_HIGH(PIN_C2);
for (i=0; i<20; i++)
{
SPI_WRITE(0xFF);
}
OUTPUT_LOW(PIN_C2); // Activo la targeta
for (i=0; i<20; i++)
{
SPI_WRITE(0xFF); // Algunos clocks.
}
SPI_WRITE(0x60);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0xFF);
if(mmc_respuesta(0x01)== 0x01) // No respondio acertadamente la memoria
{
return 1;
}
SPI_WRITE(0x61);
SPI_WRITE(0x00);
SPI_WRITE(0xFF);
SPI_WRITE(0XFE);
SPI_WRITE(0x00);
SPI_WRITE(0xFF);
if(mmc_respuesta(0x01)==0x01)
{
return 1; // No respondio la memoria y se vencio el tiempo
}
SPI_WRITE(0x66);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0xFF);
if(mmc_respuesta(0x01)== 0x01)
{
return 1;
}
while(SPI_READ(0xFF) == 0);
OUTPUT_HIGH(PIN_C2);
return 0; // Borro acertadamente toda la memori
}
Pare realizar el formateo de una memoria independientemente del tamaño se podría leer el registro CID, que creo que un parámetro da el tamaño de la memoria.
Esté método resulta muy util a la hora de formatear toda la memoria ya que sabemos con los bytes 10 y 11 tenemos el tamaño de la memoria así podemos formatear cualquier memoria conociendo esté método. De nuevo gracias al compañero Suky por el dato del CRC aunque se lo tenia bien guardadito :D :D :D.
Saludos y seguimos adelante
Iniciando SD Card
Error
Iniciando SD Card
Se ha iniciado correctamente la memoria!!!
Lectura del CID:
Lectura del CSD:
Se realiza escritura de la memoria en 512:
Se lee el sector de la memoria 0:
Error! No se ha podido leerHe revisado el esquema que has colgado, ¿te funciona sin poner un driver en el SDO? A mí no me reconoce nada.
Repeticiones para respuesta de CmdXX: 1; Respuesta recibida:0
--> Se envia CMD9 (Lectura de CSD)
Repeticiones para respuesta de CmdXX: 1; Respuesta recibida:0
Escribimos sector 0x200
--> Se envia CMD24 (Escritura de bloque)
Repeticiones para respuesta de CmdXX: 1; Respuesta recibida:0
Error en escritura
Iniciando SD Card
--> Se inicia sincronizacion
--> Se envia CMD0 (Se desactiva SD Card)
Repeticiones para respuesta de CmdXX: Iniciando SD Card
--> Se inicia sincronizacion
--> Se envia CMD0 (Se desactiva SD Card)
Repeticiones para respuesta de CmdXX: 1; Respuesta recibida:0
--> Se envia CMD1 (Se activa SD Card)
Repeticiones para respuesta de CmdXX: 1; Respuesta recibida:0
Repeticiones para respuesta de CmdXX: Iniciando SD Card
--> Se inicia sincronizacion
--> Se envia CMD0 (Se desactiva SD Card)
Repeticiones para respuesta de CmdXX: Respuesta recibida:1
Repeticiones para respuesta de CmdXX: 1; Respuesta recibida:Iniciando SD Card
--> Se inicia sincronizacion
--> Se envia CMD0 (Se desactiva SD Card)
Repeticiones para respuesta de CmdXX: 1; Respuesta recibida:0
Repeticiones para respuesta de CmdXX: Iniciando SD Card
--> Se inicia sincronizacion
--> Se envia CMD0 (Se desactiva SD Card)
ÿIniciando SD Card
--> Se inicia sincronizacion
--> Se envia CMD0 (Se desactiva SD Card)
Repeticiones para respuesta de CmdXX: Iniciando SD Card
--> Se inicia sincronizacion
--> Se envia CMD0 (Se desactiva SD Card)
Repeticiones para respuesta de CmdXX: Iniciando SD Card
--> Se inicia sincronizacion
--> Se envia CMD0 (Se desactiva SD Card)
Repeticiones para respuesta de CmdXX: 1; Respuesta recibida:0
Repeticiones para respuesta de CmdXX: Iniciando SD Card
--> Se inicia sincronizacion
--> Se envia CMD0 (Se desactiva SD Card)
Repeticiones para respuesta de CmdXX: Iniciando SD Card
--> Se inicia sincronizacion
--> Se envia CMD0 (Se desactiva SD Card)
Repeticiones para respuesta de CmdXX: 1; Respuesta recibida:0
Repeticiones para respuesta de CmdXX: 1; Respuesta recibida:0
Repeticiones para respuesta de CmdXX: 1; Respuesta recibida:0
Repeticiones para respuesta de CmdXX: 1; Respuesta recibida:0
Repeticiones para respuesta de CmdXX: 1; Respuesta recibida:0
Repeticiones para respuesta de CmdXX: 1; Respuesta recibida:0
Repeticiones para respuesta de CmdXX: 1; Respuesta recibida:0
Repeticiones para respuesta de CmdXX: 1; Respuesta recibida:0
--> Se envia CMD1 (Se activa SD Card)
Repeticiones para respuesta de CmdXX: 1; Respuesta recibida:0
Repeticiones para respuesta de CmdXX: 1; Respuesta recibida:0
--> Se envia CMD16 (Se fija largo del Bloque para escritura/lectura : 512)
Repeticiones para respuesta de CmdXX: 1; Respuesta recibida:0
--> Se envia CMD10 (Lectura de CID)
Repeticiones para respuesta de CmdXX: 1; Respuesta recibida:0
--> Se envia CMD9 (Lectura de CSD)
Repeticiones para respuesta de CmdXX: 1; Respuesta recibida:0
Escribimos sector 0x200
--> Se envia CMD24 (Escritura de bloque)
Repeticiones para respuesta de CmdXX: 1; Respuesta recibida:0
Se envia Token (0xFE)
Se envia Bloque de datos
Respuesta de recepción del bloque: 0x0 (***00101)
Error en escritura
Iniciando SD Card
--> Se inicia sincronizacion
--> Se envia CMD0 (Se desactiva SD Card)
Repeticiones para respuesta de CmdXX: 1; Respuesta recibida:0
Repeticiones para respuesta de CmdXX: 1; Respuesta recibida:0
Repeticiones para respuesta de CmdXX: 1; Respuesta recibida:0
--> Se envia CMD10 (Lectura de CID)
Repeticiones para respuesta de CmdXX: 1; Respuesta recibida:0
--> Se envia CMD9 (Lectura de CSD)
Repeticiones para respuesta de CmdXX: 1; Respuesta recibida:0
Escribimos sector 0x200
--> Se envia CMD24 (Escritura de bloque)
Repeticiones para respuesta de CmdXX: 1; Respuesta recibida:0
Se envia Token (0xFE)
Se envia Bloque de datos
Respuesta de recepción del bloque: 0x0 (***00101)
Error en escritura
Iniciando SD Card
Se ha iniciado correctamente la memoria!!!
Lectura del CID:
Lectura del CSD:
Se realiza escritura de la memoria en 512:
Se lee el sector de la memoria 0:
Valores Leidos:
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,00,01,
14,00,04,03,60,E9,33,00,00,00,CD,F4,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,55,AA,
Se lee el sector de la memoria 512:
Valores Leidos:
4C,69,62,72,65,72,69,61,20,63,6F,6E,74,72,6F,6C,20,4D,65,6D,6F,72,69,61,20,53,44
,20,62,79,20,53,
75,6B,79,2E,00,04,06,50,26,00,41,32,20,2E,E3,86,8C,44,C9,55,B4,02,25,D0,2C,53,82
,61,12,70,43,36,
3C,00,0D,3C,03,02,E9,06,94,77,28,B9,06,37,00,54,20,0C,E1,A3,4E,A0,06,D8,94,7B,00
,26,2B,00,00,00,
00,00,14,00,00,FE,FF,54,58,36,00,D1,2E,90,0C,C1,1A,32,D4,03,54,25,10,22,10,11,50
,32,9D,47,B8,A8,
28,4F,B8,9C,40,9D,E6,26,10,00,3D,65,98,32,13,65,11,4A,14,A2,09,73,81,3A,07,B7,01
,4A,10,34,2A,C0,
08,01,25,91,68,21,D4,6B,10,44,14,68,61,6F,0E,26,28,C1,06,A1,53,01,52,20,40,00,4B
,CD,08,41,2B,10,
18,53,20,F1,08,12,05,48,90,B0,42,20,88,A0,81,E9,83,00,77,4D,92,B0,43,AC,40,A1,10
,05,F8,1A,C8,45,
87,04,20,49,38,CE,00,70,0E,80,20,80,EA,80,1D,B0,25,1A,84,4B,14,11,8E,A0,A4,C0,71
,00,0C,68,A1,48,
8C,A7,0C,01,54,4A,32,79,9B,2C,00,49,94,5D,6A,A8,D3,25,D4,E6,F7,04,03,55,20,2D,5B
,93,ED,AB,16,56,
85,04,42,87,10,45,0A,84,9D,70,04,22,F2,08,FC,48,05,A2,24,EC,1A,51,45,9D,42,A1,08
,55,D9,A0,24,E4,
FB,58,03,97,A0,81,57,43,04,E5,74,0E,70,78,0A,18,13,F0,30,48,88,86,31,15,DA,B0,03
,48,D3,58,C2,06,
25,AC,1E,2D,76,02,09,A6,91,3A,0D,54,C3,2C,8B,00,2C,48,4A,6C,24,F0,C1,53,A4,C9,29
,FD,CA,40,D4,84,
19,EE,A8,98,8D,2C,C2,8B,29,85,84,39,09,92,00,C8,4E,04,31,C7,7B,07,03,2C,71,60,00
,CD,61,1F,10,52,
81,00,45,47,6A,9C,5A,70,96,00,99,DD,05,82,0C,1D,C6,23,14,54,5B,24,43,11,0F,3E,30
,7E,86,09,A4,75,
61,69,02,B3,00,40,05,03,82,9E,00,14,2C,09,59,00,01,00,D8,00,74,C0,20,34,D0,00,D0
,34,20,C0,74,FF,
01,00,20,00,18,74,20,EE,FF,01,00,03,00,25,88,72,46,2E,1D,43,46,59,90,6C,14,48,24
,10,00,11,11,11,
Iniciando SD Card
Se ha iniciado correctamente la memoria!!!
Lectura del CID:
Lectura del CSD:
Se realiza escritura de la memoria en 512:
Se lee el sector de la memoria 0:
Valores Leidos:
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,00,01,
14,00,04,03,60,E9,33,00,00,00,CD,F4,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,55,AA,
Se lee el sector de la memoria 512:
Valores Leidos:
4C,69,62,72,65,72,69,61,20,63,6F,6E,74,72,6F,6C,20,4D,65,6D,6F,72,69,61,20,53,44
,20,62,79,20,53,
75,6B,79,2E,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,A3,4E,A0,06,D8,94,7B,00
,F1,72,25,A1,48,
B4,47,30,E3,04,F0,20,50,58,36,00,D1,2E,90,0C,C1,1A,32,92,03,54,25,18,26,10,11,40
,32,9D,47,DA,A8,
28,4F,B8,9C,C0,9D,E6,06,10,00,3D,65,98,32,13,65,11,4A,14,A2,09,73,81,3A,07,B5,01
,4A,10,34,2A,D0,
08,05,25,91,68,21,D4,6B,10,04,10,68,63,6D,0E,26,28,C1,06,A1,53,11,42,20,40,00,4B
,CC,00,41,2F,10,
18,53,20,71,88,1A,05,48,90,B0,40,20,08,A0,81,CD,87,00,77,4C,92,BA,43,AC,40,A1,10
,05,E9,1A,CC,45,
87,04,22,49,38,CE,00,70,0E,80,20,00,EA,80,1D,B0,25,1A,80,4B,14,19,9E,A0,A4,C0,71
,23,04,68,A1,48,
8C,A7,2C,01,54,4A,32,79,93,2C,00,4B,94,59,6A,A8,93,25,D4,E6,F7,06,03,57,20,2D,4B
,93,ED,AB,10,56,
85,04,42,87,10,45,0A,84,99,70,04,22,F2,08,7D,48,05,86,24,EC,1A,51,45,95,42,A1,08
,55,D9,A0,24,E4,
FB,58,03,9F,A0,81,57,43,04,E5,74,0E,70,78,0A,18,13,E0,30,48,88,86,31,15,9A,B0,03
,08,D3,58,82,06,
27,AC,1E,2D,76,02,09,A6,90,3A,0D,54,C3,0C,8B,00,24,48,5A,6C,34,F0,C1,53,24,C9,29
,FD,DA,40,D4,84,
19,EE,A8,98,8D,64,C2,AB,29,84,84,39,09,92,00,E8,4E,04,31,C7,7B,17,03,2C,71,60,04
,CC,61,1F,10,5A,
81,00,45,45,6A,9C,5A,70,96,00,99,DD,05,82,0C,1D,C6,22,14,54,5B,26,43,11,0F,3E,30
,7E,84,08,A4,66,
41,69,02,B3,00,44,05,A3,82,9E,97,14,2C,09,79,03,88,E1,98,28,74,C2,20,34,D0,00,40
,01,42,EE,20,74,
08,D1,28,D2,43,30,44,A3,09,2C,00,03,08,25,88,72,42,2E,1D,43,46,59,90,6C,10,48,24
,00,00,00,00,00,
Iniciando SD Card
Error
Iniciando SD Card
Error
Iniciando SD Card
Se ha iniciado correctamente la memoria!!!
Lectura del CID:
Lectura del CSD:
Se realiza escritura de la memoria en 512:
Se lee el sector de la memoria 0:
Error! No se ha podido leer
Iniciando SD Card
Se ha iniciado correctamente la memoria!!!
Lectura del CID:
Lectura del CSD:
Se realiza escritura de la memoria en 512:
Se lee el sector de la memoria 0:
Error! No se ha podido leer
Iniciando SD Card
Error
Iniciando SD Card
Se ha iniciado correctamente la memoria!!!
Lectura del CID:
Lectura del CSD:
Se realiza escritura de la memoria en 512:
Se lee el sector de la memoria 0:
Error! No se ha podido leer
Iniciando SD Card
Error
Iniciando SD Card
Error
Iniciando SD Card
Se ha iniciado correctamente la memoria!!!
Lectura del CID:
Lectura del CSD:
Se realiza escritura de la memoria en 512:
Se lee el sector de la memoria 0:
Error! No se ha podido leer
Iniciando SD Card
Se ha iniciado correctamente la memoria!!!
Lectura del CID:
Lectura del CSD:
Se realiza escritura de la memoria en 512:
Se lee el sector de la memoria 0:
Error! No se ha podido leer
Iniciando SD Card
Error
Iniciando SD Card
Se ha iniciado correctamente la memoria!!!
Lectura del CID:
Lectura del CSD:
Se realiza escritura de la memoria en 512:
Se lee el sector de la memoria 0:
Error! No se ha podido leer
Iniciando SD Card
--> Se inicia sincronizacion
--> Se envia CMD0 (Se desactiva SD Card)
Repeticiones para respuesta de CmdXX: 2; Respuesta recibida:1
--> Se envia CMD1 (Se activa SD Card)
Repeticiones para respuesta de CmdXX: 2; Respuesta recibida:1
Repeticiones para respuesta de CmdXX: 2; Respuesta recibida:0
--> Se envia CMD16 (Se fija largo del Bloque para escritura/lectura : 512)
Repeticiones para respuesta de CmdXX: 2; Respuesta recibida:0
--> Se envia CMD59 (Desactivación de CRC)
Repeticiones para respuesta de CmdXX: 2; Respuesta recibida:0
Se ha iniciado correctamente la memoria!!!
Lectura del CID:
--> Se envia CMD10 (Lectura de CID)
Repeticiones para respuesta de CmdXX: 3; Respuesta recibida:0
Toquen recibido: 0xFE
Manufacturer ID: 03
OEM/Application ID: SD
Product Name: SD016
Product Revision: 31
Serial Number: 3E28163F
Manufacturer Date Code: 002B
CRC-7 Checksum: 75
Lectura del CSD:
--> Se envia CMD9 (Lectura de CSD)
Repeticiones para respuesta de CmdXX: 3; Respuesta recibida:0
Toquen recibido: 0xFE
CSD_STRUCTURE: 00
TAAC: 26
NSAC: 00
TRAN_SPEED: 32
CCC: 01F5
READ_BL_LEN: 09
READ_BL_PARTIAL: 01
WRITE_BLK_MISALIGN: 00
READ_BLK_MISALIGN: 00
DSR_IMP: 00
C_SIZE: 83
VDD_R_CURR_MIN: 05
VDD_R_CURR_MAX: 04
VDD_W_CURR_MIN: 05
VDD_W_CURR_MAX: 05
C_SIZE_MULT: 03
ERASE_BLK_EN: 01
SECTOR_SIZE: 1F
WP_GRP_SIZE: 7F
WP_GRP_ENABLE: 01
R2W_FACTOR: 04
WRITE_BL_LEN: 09
WRITE_BL_PARTIAL: 00
FILE_FORMAT_GRP: 00
COPY: 01
PERM_WRITE_PROTECT: 00
TMP_WRITE_PROTECT: 00
FILE_FORMAT: 00
CRC: 9F
Se realiza escritura de la memoria en 512:
--> Se envia CMD24 (Escritura de bloque)
Repeticiones para respuesta de CmdXX: 2; Respuesta recibida:0
Se envia Token (0xFE)
Se envia Bloque de datos
Respuesta de recepción del bloque: 0xE5 (***00101)
Escritura Terminada
Se lee el sector de la memoria 0:
--> Se envia CMD17 (Lectura de bloque)
Repeticiones para respuesta de CmdXX: 3; Respuesta recibida:0
Toquen recibido: 0xFE
Terminada la lectura
Valores Leidos:
33,C0,8E,D0,BC,00,7C,FB,50,07,50,1F,FC,BE,1B,7C,BF,1B,06,50,57,B9,E5,01,F3,A4,CB
,BD,BE,07,B1,04,
38,6E,00,7C,09,75,13,83,C5,10,E2,F4,CD,18,8B,F5,83,C6,10,49,74,19,38,2C,74,F6,A0
,B5,07,B4,07,8B,
F0,AC,3C,00,74,FC,BB,07,00,B4,0E,CD,10,EB,F2,88,4E,10,E8,46,00,73,2A,FE,46,10,80
,7E,04,0B,74,0B,
80,7E,04,0C,74,05,A0,B6,07,75,D2,80,46,02,06,83,46,08,06,83,56,0A,00,E8,21,00,73
,05,A0,B6,07,EB,
BC,81,3E,FE,7D,55,AA,74,0B,80,7E,10,00,74,C8,A0,B7,07,EB,A9,8B,FC,1E,57,8B,F5,CB
,BF,05,00,8A,56,
00,B4,08,CD,13,72,23,8A,C1,24,3F,98,8A,DE,8A,FC,43,F7,E3,8B,D1,86,D6,B1,06,D2,EE
,42,F7,E2,39,56,
0A,77,23,72,05,39,46,08,73,1C,EB,1A,90,BB,00,7C,8B,4E,02,8B,56,00,CD,13,73,51,4F
,74,4E,32,E4,8A,
56,00,CD,13,EB,E4,8A,56,00,60,BB,AA,55,B4,41,CD,13,72,36,81,FB,55,AA,75,30,F6,C1
,01,74,2B,61,60,
6A,00,6A,00,FF,76,0A,FF,76,08,6A,00,68,00,7C,6A,01,6A,10,B4,42,8B,F4,CD,13,61,61
,73,0E,4F,74,0B,
32,E4,8A,56,00,CD,13,EB,D6,61,F9,C3,49,6E,76,61,6C,69,64,20,70,61,72,74,69,74,69
,6F,6E,20,74,61,
62,6C,65,00,45,72,72,6F,72,20,6C,6F,61,64,69,6E,67,20,6F,70,65,72,61,74,69,6E,67
,20,73,79,73,74,
65,6D,00,4D,69,73,73,69,6E,67,20,6F,70,65,72,61,74,69,6E,67,20,73,79,73,74,65,6D
,00,00,00,00,00,
8B,F4,8A,56,24,CD,13,61,61,72,0B,40,75,01,42,03,5E,0B,49,75,06,F8,C3,41,BB,00,00
,60,66,6A,00,EB,
B0,4E,54,4C,44,52,20,20,20,20,20,20,0D,0A,52,65,6D,6F,76,65,20,64,69,73,D4,EE,21
,00,72,20,00,01,
01,00,01,FE,3F,00,3F,00,00,00,41,70,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
,00,00,00,55,AA,
Se lee el sector de la memoria 512:
--> Se envia CMD17 (Lectura de bloque)
Repeticiones para respuesta de CmdXX: 3; Respuesta recibida:0
Toquen recibido: 0xFE
Terminada la lectura
Valores Leidos:
4C,69,62,72,65,72,69,61,20,63,6F,6E,74,72,6F,6C,20,4D,65,6D,6F,72,69,61,20,53,44
,20,62,79,20,53,
75,6B,79,2E,00,00,06,50,26,00,41,32,20,2E,E1,C6,8C,44,C9,51,B4,02,25,D0,2C,51,AA
,61,12,71,43,36,
3D,00,0D,3C,03,06,E9,06,94,6F,28,99,06,1F,00,54,60,0C,E1,A3,5E,A0,06,D8,94,7B,00
,F4,72,21,A9,48,
B4,06,30,E3,04,F8,20,50,58,36,00,D1,2E,90,0C,C1,0A,32,D2,07,54,25,18,26,10,11,50
,32,95,47,FA,A8,
28,4F,B8,9C,C0,9D,E6,26,10,00,3D,65,98,32,13,65,11,4A,14,A2,09,73,81,3E,07,B7,01
,4A,10,34,2A,C0,
08,01,25,91,6A,21,D4,6B,10,44,14,68,61,6D,0E,26,28,C1,06,A1,53,01,42,20,40,00,4B
,CD,00,41,2E,10,
18,53,20,F1,08,1A,05,48,90,B0,40,20,88,80,81,C9,83,00,76,4C,92,B2,43,AC,40,A1,10
,05,F8,1A,C8,45,
87,04,22,49,38,CE,00,70,0E,80,20,00,EA,80,1D,B0,A5,1A,80,4B,14,11,9E,A0,A4,C0,71
,23,04,68,A1,48,
8C,A7,0C,01,54,4A,32,F9,BB,2C,00,49,94,59,6E,A8,D3,25,D4,E6,F7,06,03,55,20,2D,5B
,93,ED,AB,12,56,
05,04,42,87,10,45,0A,84,99,7A,04,22,72,08,7D,68,05,A6,24,EC,1A,51,45,9D,42,A1,48
,55,D9,A0,24,E4,
FB,58,03,9F,A0,81,57,43,04,E5,74,0E,70,7C,0A,19,03,F0,30,48,08,86,31,15,DA,B0,03
,08,D3,58,82,06,
25,AC,1E,2D,76,02,09,A6,10,3A,0D,54,C3,2C,8B,00,24,48,4A,6C,24,F0,C1,53,24,C9,29
,FD,DA,40,94,84,
19,EE,E8,98,8F,2C,C2,8B,29,85,84,39,09,92,00,E8,4E,04,31,C7,7B,17,03,AC,71,60,00
,CC,61,1F,10,5A,
81,00,45,47,6A,9C,5A,70,96,00,99,DD,15,82,0C,9D,C6,22,14,54,5B,26,43,10,0F,3E,30
,7E,86,08,A4,64,
41,69,02,B3,00,40,05,A3,82,9E,97,1C,2C,09,79,07,88,E1,D8,A8,74,C2,00,34,D0,00,40
,01,C2,EE,20,74,
18,D1,20,D2,43,30,40,22,01,2C,10,03,08,25,88,72,42,2E,1D,43,46,59,10,6C,10,49,24
,11,11,11,31,31,
Es que pasa algo raro, es como que se está iniciando y ocurre un reset. Agrega una demora y ve que sea estable :?Lo siento suky, no lo he podido probar hasta ahora.... ¿Dónde tengo que poner el retardo? ¿entre inicializaciones?
Saludos!
--> Se inicia sincronizacion
--> Se envia CMD0 (Se desactiva SD Card)
Repeticiones para respuesta de CmdXX: 2; Respuesta recibida:1
--> Se envia CMD1 (Se activa SD Card)
Repeticiones para respuesta de CmdXX: 2; Respuesta recibida:1
Repeticiones para respuesta de CmdXX: 2; Respuesta recibida:1
Repeticiones para respuesta de CmdXX: 2; Respuesta recibida:0
--> Se envia CMD16 (Se fija largo del Bloque para escritura/lectura : 512)
Repeticiones para respuesta de CmdXX: 2; Respuesta recibida:0
--> Se envia CMD59 (Desactivación de CRC)
Repeticiones para respuesta de CmdXX: 2; Respuesta recibida:0no entiendo nada, parece que depende del día que tenga....
Hola Richi! eh! como vas a pedir disculpas por meterte? Si para eso es un foro esto, no? :)Exactamente1 :lol:
do{
if(SDCard_send_command(CMD0,0x00,Respuesta)==0){
return(0); // Si se recibe 0 error por timeout.-
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.
Yo me inclino hacia un error de hardware, pero vamos...que no es tan complejo, eh? Son 6 resistencias solamente... :5] :5]
Yo me inclino hacia un error de hardware, pero vamos...que no es tan complejo, eh? Son 6 resistencias solamente... :5] :5]
Si podes armarte una plaquita sería mejor, capaz sea el proto que te juega una mala pasada :?
Hola Bruno, un paso importante donde se para. Podrias postear el código de la función SDCard_send_command para ver como esta implementado el corte por timeout ?
Saludos !
CREO que se soluciono al sacar #USE SPI(FORCE_HW)
Bueno, duró poco la diversión!
Iba todo excelente. En el hard se inicializaba la microSD correctamente con tu libreria Suky y con la que pensaba utilizar finalmente. Luego solo cambie las lineas de debugueo en ambas librerias(en lugar de poner "se inicializo la memoria" cambie los comentarios a los que ustedes imprimian por RS232(estoy debugueando por USB con un soft que hice)). No volvio a inicializar mas. En ninguna de las dos. Tambien cambia el comportamiento con los distintos formatos. Si formateo en ExFAT(512 bytes per sector) no me inicializaba ni siquiera cuando andaba bien.
Por otro lado nunca logre leer un bloque. Solo recibia 0xFF y debuguee el error: que resulto ser 0x01(lo que en la hoja de datos dice que seria: ERROR(digamos que no se la jugaron mucho, eh?)).
Debido a las vueltas de la vida, a mi desgracia de perder mi ICSP de mi GTP USB+ y especialmente a mi gran torpeza, anoche queme el ultimo 18F4550 que tenía al colocarlo justo al reves de lo que debia ser en el zocalo.
Hasta la proxima semana no creo que avance mucho. Ojala mis esfuerzos y reniegues le sirvan a otros al menos para orientarse.
Por lo pronto, yo hago la fácil y le echo la culpa de todo al PICC. :) :) :)
Hola Suky, osea que reemplazaste los divisores de tensión por una conversor de niveles ?
Saludos !
Suky, te comento que actualmente estoy haciendo trabajar al micro en 3.3V @ 20Mhz para eliminar ese problema. El micro funciona normal, pero del SPI ni muuu dice.
Amigo Suky, mis felicitaciones por toda la info compartida.Muchas gracias! ;-)
Esto es un claro ejemplo del uso de un foro donde se ayuda con todo lo que dispnemos (es en alusion al otro hilo amigo) Saludos.
// Se fija largo del bloque lectura/escitura.
if(SDCard_send_command(CMD16,BLOCK_SIZE,Respuesta)==0){
return(0);
}else if(Respuesta!=0){
return(0);
} si entiendo que se tiene que fijar el tamaño del bloque pero por que los 2 regresan un return(0);Suky, qué cristal has usado en las librerías??
He cambiado el pic del ejemplo a un 18f2550 y las líneas a las suyas y no tengo respuesta de la memoria :5]
Las sd y mmc son mi unicornio, definitivamente....
Los he puesto a 48 MHz en los 18Fx550 y a 40 MHz los 18Fx620.
Los he puesto a 48 MHz en los 18Fx550 y a 40 MHz los 18Fx620.
Suky, ¿has cambiado la configuración de algo para los 48mhz? Estoy usando un 18f2550 y he puesto los fuses para que trabaje a 48MHz. Lo que no sé es si la configuración que tienes hecha en el ejemplo de 40MHz vale o la tengo que cambiar.
Un saludo!!
Avances :-/ :-/
HE probado el código que me pasaste hace tiempo de CCS y funcionan todas las tarjetas, tanto las MMC como las SD. Estas últimas eran las que no conseguí hacer funcionar Y NO HE HECHO NADA!!!!
Creo que era culpa de una soldadura fría, por eso funcionaba alguna que otra vez....
Ahora, ¿porqué no lo consigo con la fat?
Me voy a poner con ccs y ya miraré el c18...
por cierto suky una gran web!!!!
me has aclarado las dudas que me quedaban en este tema....
Voy a agregar un enlace de la mía a la tuya (si no te importa)
pues he visto que con el de las fat me manda por el 232 printf("\r\n--> Se inicia sincronizacion\r\n"); y ya no me envía printf("\r\n--> Se envia CMD0 (Se desactiva SD Card)\r\n\r\n"); como si se resetease y tengo el wdt desactivado....
Te comento que realice un nuevo hardware con la adecuación de los niveles de tensión mediante buffer 74hc125, trabajando el interface SPI a 10 MHz sin ningun problema. El único cambio que hice fue en las esperas por alguna respuesta (while(i<100)) lo subi a 2000, y pude iniciar SD Card, microSD Kingston y SanDisck de 512Mb, 1 Gb y 2 Gb sin problemas! :-/
Saludos!
#if RS232_DEBUG
printf("\r\n--> Se envia CMD0 (Se desactiva SD Card)\r\n\r\n");
#endif
i=0;
do{
if(SDCard_send_command(CMD0,0x00,&Respuesta)==0){
return(0); // Si se recibe 0 error por timeout.-
}else{i++;}
}while((Respuesta.b0==0x00) && i<2000);
if(i>=2000){return(0);} // Timeout esperando desactivación de SD Card.Suky, te puedo decir exáctamente lo que hacemuchas gracias Slalen, entonces se utilizan 2 74HC125, uno para los niveles 3.3 y otro para dejar los niveles en 5. Comunicación par un lado y para el otro.Código: [Seleccionar]#if RS232_DEBUG
printf("\r\n--> Se envia CMD0 (Se desactiva SD Card)\r\n\r\n");
#endif
i=0;
do{
if(SDCard_send_command(CMD0,0x00,&Respuesta)==0){
return(0); // Si se recibe 0 error por timeout.-
}else{i++;}
}while((Respuesta.b0==0x00) && i<2000);
if(i>=2000){return(0);} // Timeout esperando desactivación de SD Card.
salta en el return(0);
msegredo lo tienes aqui (http://www.ucontrol.com.ar/forosmf/programacion-en-c/sd-card-libreria-fat16-libreria-a-nivel-hardware-%28ccs-c18-c30-ect-%29/msg32276/?topicseen#msg32276)
Suky, te puedo decir exáctamente lo que haceCódigo: [Seleccionar]#if RS232_DEBUG
printf("\r\n--> Se envia CMD0 (Se desactiva SD Card)\r\n\r\n");
#endif
i=0;
do{
if(SDCard_send_command(CMD0,0x00,&Respuesta)==0){
return(0); // Si se recibe 0 error por timeout.-
}else{i++;}
}while((Respuesta.b0==0x00) && i<2000);
if(i>=2000){return(0);} // Timeout esperando desactivación de SD Card.
salta en el return(0);
msegredo lo tienes aqui (http://www.ucontrol.com.ar/forosmf/programacion-en-c/sd-card-libreria-fat16-libreria-a-nivel-hardware-%28ccs-c18-c30-ect-%29/msg32276/?topicseen#msg32276)
BOOL SDCard_init(void){
UINT8_VAL Respuesta;
UINT16 i;
TRIS_SD_CS=0;
SD_CS=1;
// Configuración del Módulo SPI.-
InitSPI();
#if RS232_DEBUG
printf("\r\n--> Se inicia sincronizacion\r\n");
#endif
SD_CS=1;
Delay_ms20();
for(i=0;i<20;i++) WriteMedia(0xFF); // Para sincronización.
SD_CS=0;
Delay_ms20();
#if RS232_DEBUG
printf("\r\n--> Se envia CMD0 (Se desactiva SD Card)\r\n\r\n");
#endif
i=0;
do{
if(SDCard_send_command(CMD0,0x00,&Respuesta)==0){
return(0); // Si se recibe 0 error por timeout.-
}else{i++;}
}while((Respuesta.b0==0x00) && i<2000);:oops: Me vas a querer asesinar! Pensé que en la configuración de las librerías que deje en la página tenia Fosc/16 (Lo tenia presente de dejarlo así :? ) para que en la configuración del SPI no se supere los 10 MHz máximos que según datasheet soporta :oops: Pasa a Fosc/16 o SPI_FOSC_16, o también puedes configurar el microcontrolador a menor velocidad.
Disculpas :oops: Saludos!
strcpy(&NombreCorto[0],"CARPET~1");
strcpy(&NombreLargo[0],"Carpeta de PIC");
UbicacionFolder=FAT_CreateDirectory(&NombreLargo[0],&NombreCorto[0],DirectorioRaiz);
strcpy(&NombreCorto[0],"ARCHIV~1.txt");
strcpy(&NombreLargo[0],"Archivo con PIC.txt");
FAT_CreateFile(&NombreLargo[0],&NombreCorto[0],UbicacionFolder,&Texto[0]);
FAT_OpenAddFile(&NombreCorto[0],UbicacionFolder,&Texto[0]);
FAT_OpenFile(&NombreCorto[0],UbicacionFolder);Me lo abre.strcpy(&NombreCorto[0],"CARPET~1");
strcpy(&NombreLargo[0],"Carpeta de PIC");
UbicacionFolder=FAT_CreateDirectory(&NombreLargo[0],&NombreCorto[0],DirectorioRaiz);
strcpy(&NombreCorto[0],"ARCHIV~1.txt");
strcpy(&NombreLargo[0],"Archivo con PIC.txt");
FAT_CreateFile(&NombreLargo[0],&NombreCorto[0],UbicacionFolder,&Texto[0]);
FAT_OpenAddFile(&NombreCorto[0],UbicacionFolder,&Texto[0]);
strcpy(&NombreCorto[0],"PIC.txt");
FAT_OpenFile(&NombreCorto[0],DirectorioRaiz);No me hace ni caso!!Gracias Suky ya lo conecté a RC0. Pero tengo otra pregunta ya que no he caido antes yo estoy haciendo la prueba con un pic que trabaja a 3,3v. Si esto es asi no tengo por que utilizar las resistencias, ¿tendria que conectar las salidas directas desde la tarjeta mmc hasta el pic sin dichas resistencias?
gracias.
Re: Manejo de Memoria SD con CCS-Librería nivel Hardware + FAT16.-
« Respuesta #74 : Enero 22, 2010, 08:26:49 »
Hola a todos, estamos haciendo un sistema de adquisicion de datos y consiste presisamente en almacenarlos en una SD, estube chequeando sus programas y no se por que no me funciona. El cristal que estoy utilizando es de 12 Mhz y modifico la division del PLL del SPI para que en lugar de que la divida por 16 la divide por 4, tiene algo que ver eso? es que no pude conseguir un cristal de 48 MHz, o tengo que realizar alguna otra modificación?
Re: Manejo de Memoria SD con CCS-Librería nivel Hardware + FAT16.-
« Respuesta #75 : Enero 22, 2010, 10:34:29 »
Podes colocarle cualquier cristal externo hasta 20MHz, luego tienes que configurar el PLL para que trabaje a 48MHz. Revisa por aquí al respecto.
Luego para cambiarle a división por 4 en la velocidad SPI deberías implementar otra forma la adaptación de tensiones, mmm... no se si funcionará adecuadamente con los resistores.
printf("Repeticiones para respuesta de CmdXX: %u; Respuesta recibida:%u\r\n",i,ResTmp.Val);*** Error 114 "D:\Temp\Fede\LIB_SD_FAT16\SDCardSPI.c" Line 74(91,94): Printf format type is invalid ::
Ya ni me acuerdo, pero i no era de 16-bits? si es el caso tienes que colocar lu.
Saludos!
int inicializacion_mmc()
{
OUTPUT_HIGH(PIN_C2);
for(i=0; i<16; i++)
{
SPI_WRITE(0xFF);
}
OUTPUT_LOW(PIN_C2);
{
SPI_WRITE(0xFF);
}
i = 0;
do
{
SPI_WRITE(0x41); // Envia comando hasta que de la respuesta y hasta que se cumpla el tiempo
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0xFF); // Secuencia del comando CMD1
i= i + 1;
}
while(i<250 && mmc_respuesta(0x00)==1);
if(i==250)
{
return 1; // si se supera el tiempo de respuesta no se ha inicializado bien la targeta
}
OUTPUT_HIGH(PIN_C2);
for(i=0; i<16; i++) // Alguno cloks para estabilizar la comunicación
{
SPI_WRITE(0xFF);
}
OUTPUT_LOW(PIN_C2);
for(i=0; i<16; i++)
{
SPI_WRITE(0XFF);
}
SPI_WRITE(0x50);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x02);// AQUI SE DEFINE 0X200 O 512<-------------------- [b]AQUI[/b]
SPI_WRITE(0x00);
SPI_WRITE(0xFF); // Comando CMD16 para configurarlo de 512 bytes
if(mmc_respuesta(0x00)==1)
{
return 1; // se ha inicializado incorrectamente
}
OUTPUT_HIGH(PIN_C2);
return 0; // se ha inicializado correctamente
}En ese caso no utilizas el módulo MSSP del microcontrolador, sino que la comunicación se realiza por software. No creo que genere ningún problema, pero se reduce notablemente la velocidad en la comunicación SPI.
Saludos!
Lo soportan, pero tienen requerimientos distintos en la inicialización.
Es decir, se inicializan de forma ligeramente diferente a como se hace con las tarjetas de baja capacidad.
Otra cosa que no se es si CCS implementa dicha posiblidad.
Este diagrama puede ser de ayuda:
Diagrama SD/MMC (http://elm-chan.org/docs/mmc/sdinit.png)
A mi también, copie el enlace a otra solapa y funciono. Es un diagrama de flujo de como deberia ser la inicialización para detectar todos los tipos de tarjetas.A! Si ya se de que se trata, creo que la librería de Microchip lo implementa. O en la del mbed, en algún lado la vi :mrgreen:
Saludos !
--> Se inicia sincronizacion
--> Se envia CMD0 (Se desactiva SD Card)
Repeticiones para respuesta de CmdXX: 1; Respuesta recibida:127
--> Se envia CMD8
Repeticiones para respuesta de CmdXX: 2; Respuesta recibida:1,0x1AA
--> Se envia CMD55/ACMD41 (Se activa SD Card)
Repeticiones para respuesta de CmdXX: 2; Respuesta recibida:1
Repeticiones para respuesta de CmdXX: 2; Respuesta recibida:1
Repeticiones para respuesta de CmdXX: 2; Respuesta recibida:1
Repeticiones para respuesta de CmdXX: 2; Respuesta recibida:0
--> Se envia CMD58
Repeticiones para respuesta de CmdXX: 2; Respuesta recibida:0,0xC0FF8000
> SD Card modo HC
--> Se envia CMD16 (Se fija largo del Bloque para escritura/lectura : 512)
Repeticiones para respuesta de CmdXX: 2; Respuesta recibida:0
--> Se envia CMD59 (Desactivaci n de CRC)
Repeticiones para respuesta de CmdXX: 2; Respuesta recibida:0
--> Se envia CMD9 (Lectura de CSD)
Repeticiones para respuesta de CmdXX: 2; Respuesta recibida:0
Toquen recibido: 0xFE
CSD_STRUCTURE: 0
TAAC: E
NSAC: 0
TRAN_SPEED: 32
CCC: 60010
READ_BL_LEN: 9
READ_BL_PARTIAL: 0
WRITE_BLK_MISALIGN: 0
READ_BLK_MISALIGN: 0
DSR_IMP: 0
C_SIZE: 10
VDD_R_CURR_MIN: 7
VDD_R_CURR_MAX: 3
VDD_W_CURR_MIN: 2
VDD_W_CURR_MAX: 3
C_SIZE_MULT: 6
ERASE_BLK_EN: 1
SECTOR_SIZE: 7F
WP_GRP_SIZE: 0
WP_GRP_ENABLE: 0
R2W_FACTOR: 2
WRITE_BL_LEN: 9
WRITE_BL_PARTIAL: 0
FILE_FORMAT_GRP: 0
COPY: 0
PERM_WRITE_PROTECT: 0
TMP_WRITE_PROTECT: 0
FILE_FORMAT: 0
CRC: 4B
--> Se envia CMD10 (Lectura de CID)
Repeticiones para respuesta de CmdXX: 2; Respuesta recibida:0
Toquen recibido: 0xFE
Manufacturer ID: 2
OEM/Application ID: TM
Product Name: SA08G
Product Revision: 6
Serial Number: 226E644C
Manufacturer Date Code: 0AC
CRC-7 Checksum: C3
Para el divisor resistivo utiliza mejor resistencias de 1.5k y 3.3k, para altas frecuencias funciona mejor.
Osea todas esas extensiones del FAT16 las agrego al programa inicial probandoSDCard?¿?¿?¿?¿?¿ o como lo tengo q probar?¿?¿ Consegui un cristal de 48MHz, voy a probar con esto a ver que pasa ......
Saludoss
Suky, utilice la resistencias recomendadas (3.3k y 1.5k)y los valores del voltaje de este divisor son de 5voltios :O, no se supone q las memoria trabaja a 3.3v?¿?¿
Otra consulta, hehe acabo de adquirir el 74125N que utilizas en el hardware ideal, veo la resistencias conectadas a 3.3V, que valores son?¿?¿?¿
Saludos
int init_mmc()
{
SETUP_SPI(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_16 | SPI_XMIT_L_TO_H);
OUTPUT_HIGH(PIN_C2);
delay_ms(20);
for(i=0; i<20; 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
delay_ms(20);
for(i=0; i<20; i++)
{
SPI_WRITE(0xFF); // espero a que se inicialice la memoria que van desde 8 a 10 pulso del reloj
}
i = 0;
do
{
SPI_WRITE(0x40);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x95); // Comando CMDO datos a enviar
}
while((mmc_respuesta(0x01)==0x01) && (i<200));
if(i>=200)
{
printf("Error en comando CMD0");
return 1; // Error en memoria por que se supero el tiempo
}
i = 0;
do
{
SPI_WRITE(0x41); // Envia comando hasta que de la respuesta y hasta que se cumpla el tiempo
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0xFF); // Secuencia del comando CMD1
i= i + 1;
}
while((i<250) && (mmc_respuesta(0x00)==0x01));
if(i>=250)
{
printf("Error en comando CMD1");
return 1; // si se supera el tiempo de respuesta no se ha inicializado bien la targeta
}
i = 0;
do
{
SPI_WRITE(0x50);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x02);
SPI_WRITE(0x00);
SPI_WRITE(0xFF); // Comando CMD16 para configurarlo de 512 bytes
i = i + 1;
}
while((mmc_respuesta(0x00)==0x01) && (i<2));
if(i>=2)
{
printf("Error en comando CMD16");
return 1; // se ha inicializado incorrectamente
}
SPI_WRITE(59|0x40);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0xFF); // Comando CMD59 para desactivar el CRC
if(mmc_respuesta(0x00)== 0x01)
{
printf("Error en comando CMD59");
return 1;
}
OUTPUT_HIGH(PIN_C2);
return 0; // se ha inicializado correctamente
}int mmc_respuesta(unsigned char respuesta)
{
unsigned long espera = 0xFFFF;
while(SPI_READ(0xFF)!= respuesta && espera> 0)
{
espera= espera - 1;
}
if(espera==0)
{
return 1; // se ha superado el tiempo
}
else
{
return 0;
}
}
int mmc_escribir_bloque()
{
resp = 0; OUTPUT_LOW(PIN_C2);
for(i=0; i<16; i++)
{
SPI_WRITE(0xFF); // Espero a que se estabilice la memoria
}
SPI_WRITE(0x58);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x02);
SPI_WRITE(0x00);
SPI_WRITE(0xFF); // Comando CMD24 pero escribé en el segundo bloque 0x200
if(mmc_respuesta(0x00)==0x01) // Espero la respuesta RB1
{
printf("Error en CMD24");
return 1; // no respondio correctamente la memoria
}
SPI_WRITE(0xFE); // Envio el token de inicio
for(i=0; i<512; i++)
{ spi_write(17);
delay_ms(1);
}
SPI_WRITE(0xFF);
SPI_WRITE(0xFF); // espero ha que se estabilice o envio 2 CRC
printf("%Lu",i);
i=0;
do
{
resp = SPI_READ(0xFF);
i++;
}
while ((i<2000) && resp == 0xFF);
if(i>=2000)
{
printf("Se ha superado el tiempo");
return 1;
}
printf("Respuesta de recepción \n %X",resp);
if((resp&0x0F)!=0x05)
{
printf("error al escribir los datos");
SPI_WRITE(0xFF);
OUTPUT_HIGH(PIN_C2);
return 1; // No se escribio correctamente el bloque de 512 bytes dirente de 00101
}
OUTPUT_HIGH(PIN_C2);
return 0;
}
int mmc_leer_bloque()
{
OUTPUT_LOW(PIN_C2);
SPI_WRITE(0x51);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x02);
SPI_WRITE(0x00);
SPI_WRITE(0xFF); // Comando CMD17 para leer el bloque 2 de la memoria
if(mmc_respuesta(0x00)==0x01) // Espero el comando RB1 la respuesta
{
return 1; // Hubo error en la lectura del bloque 2 de la memoria
}
if(mmc_respuesta(0xFE)==0x01)
{
return 1; // espera por el token de respuesta
}
if((SPI_READ(0XFF)&0xE0)==0x00) // espero el token correcto
{
return 1;
}
OUTPUT_HIGH(PIN_C2);
return 0;
}void main()
{
long conversion;
int lectura;
i = 0;
setup_adc_ports(sAN0|sAN1|VREF_VREF);
setup_adc(adc_clock_div_32); // configuro el conversor análogo digital
set_tris_b(0x00);
set_tris_a(0xff);
set_tris_c(0x93);
disable_interrupts(global);
retorno = init_mmc();
if(retorno==0x01)
{
printf("Error en memoria");
}
else
{
do
{
if (input(pin_d2)==1)
{
retorno = mmc_escribir_bloque();
if(retorno==0x01)
{
printf("No se pudo escribir el bloque");
}
else
{
printf("Escritura realizada");
}
}
if(input(pin_d2)==0)
{
retorno== mmc_leer_bloque();
if(retorno==0x01)
{
printf("Error en lectura\r");
}
else
{
for(i=0; i<512; i++)
{
lectura = spi_read(0XFF);
printf("%x",lectura);
}
SPI_READ(0xFF);
SPI_READ(0xFF);
OUTPUT_HIGH(PIN_C2); // Chip Select = 1 (off)
SPI_WRITE(0xFF);
}
}
}
while(true);
}
} do
{
resp = SPI_READ(0xFF);
i++;
}
while ((i<2000) && resp == 0xFF);
if(i>=2000)
{
printf("Se ha superado el tiempo");
return 1;
}
printf("Respuesta de recepción \n %X",resp);
if((resp&0x0F)!=0x05)
{
printf("error al escribir los datos");
SPI_WRITE(0xFF);
OUTPUT_HIGH(PIN_C2);
return 1; // No se escribio correctamente el bloque de 512 bytes diferente de 00101
}#include <18F4550.h>
#device adc=8
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
//#use spi(MASTER,BITS=8,MODE=3,FORCE_HW,stream=SDCard)
#include "FAT16.c"
UINT8 Texto[512]="Texto Creado con PIC....\r\n";
void main(){
int1 Card_Work=0;
char NombreCorto[13];
char NombreLargo[50];
UINT16 UbicacionFolder=0;
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED|T1_DIV_BY_1);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
InitHard_SDCard();
delay_ms(1000);
while(1){
if((SD_DETEC==0)&&(Card_Work==FALSE)){
delay_ms(500);
if(SD_DETEC==0){
Card_work=1;
SDCard_init();
FAT_init();
strcpy(&NombreCorto[0],"CARPET~1");
strcpy(&NombreLargo[0],"Carpeta de PIC");
UbicacionFolder=FAT_CreateDirectory(&NombreLargo[0],&NombreCorto[0],DirectorioRaiz);
strcpy(&NombreCorto[0],"ARCHIV~1.txt");
strcpy(&NombreLargo[0],"Archivo con PIC.txt");
FAT_CreateFile(&NombreLargo[0],&NombreCorto[0],UbicacionFolder,&Texto[0]);
FAT_OpenAddFile(&NombreCorto[0],UbicacionFolder,&Texto[0]);
}
}
if((SD_DETEC==1)&&(Card_Work==TRUE)){
Card_work=0;
}
}
}
/* #if defined(SDCARD_DEBUG)
printf("\r\n--> Se envia CMD59 (Desactivación de CRC)\r\n");
#endif
// Se desactiva CRC.
if(SDCard_send_command(CMD59,0,&Respuesta)==0){
return(0);
}
if(Respuesta.R1.Val!=0){
return(0);
}*/
for(i=0;i<20;i++) WriteMedia(0xFF); // Para sincronización.void WriteMedia(UINT8 data_out){
UINT8 TempVar;
#ifdef __18CXX
TempVar = SSPBUF; // Clears BF
PIR1bits.SSPIF = 0; // Clear interrupt flag
SSPBUF = data_out; // write byte to SSPBUF register
while( !SSPSTATbits.BF ); // wait until bus cycle complete
#endif
#if defined(__PCH__)
spi_write(data_out);
#endif
#if defined (__PIC32MX__)
TempVar = SPI1BUF;
SPI1BUF = data_out; // Write to buffer for TX
while( !SPI1STATbits.SPIRBF); // Wait transfer complete
#endif
} InitSPI(VELOCITY_SPI_LOW);switch(Velocity){
case VELOCITY_SPI_LOW:
#ifdef __18CXX
CloseSPI();
OpenSPI(SPI_FOSC_64, MODE_11, SMPMID);
#endif
#if defined (__PIC32MX__)
SPI1CON = 0x0000;
SPI1BRG = 19; // Clock = FCB/2*(19+1) = 1 MHz
SPI1CON = 0x8120; // ON, CKE=1; CKP=0, Sample Middle
#endif
break; // Deshabilitado para simulación:
#ifdef RS232_DEBUG
printf("\r\n--> Se envia CMD59 (Desactivación de CRC)\r\n");
#endif
// Se desactiva CRC.
if(SDCard_send_command(CMD59,0,Respuesta)==0){
return(0);
}else if(Respuesta!=0){
return(0);
}
if(SDCard_read_block(0,&BufferFAT[0])==0){
return(0);
}SDCard_read_block(UINT32 Address,UINT8 *Buffer){
SDCARD_RESPUESTA Respuesta;
UINT8 TokenTmp;
UINT16 i;
// Se envia comando para leer bloque de bytes.-
#if defined(SDCARD_DEBUG)
printf("\r\n--> Se envia CMD17 (Lectura de bloque)\r\n");
#endif
SDSelect();
if(SDCard_send_command(CMD17,Address,&Respuesta)==0){
return(0);
}
if(Respuesta.R1.Val!=0){
return(0);
}
// Pasamos a esperar Token.
i=0;
do{
TokenTmp=ReadMedia();
i++;
}while(TokenTmp==0xFF && i<SDCARD_TIMEOUT);// Mientras sea 0xFF.-
if(i>=SDCARD_TIMEOUT){SDDeselect();return(0);}
if((TokenTmp&0xE0)==0){ // Si se recibe 000xxxxx y no 0xFE.-
SDDeselect();
return(0);
}
#if defined(SDCARD_DEBUG)
// printf("Toquen recibido: 0x%X\r\n",TokenTmp);
#endif
// Todo ok, recibimos data.-
for(i=0;i<BLOCK_SIZE;i++){
*Buffer++=ReadMedia();
}
// Ignoramos CRC.-
ReadMedia();
ReadMedia();
SDDeselect();
#if defined(SDCARD_DEBUG)
// printf("Terminada la lectura\r\n");
#endif
return(1);
/******************************************************************************
*
* Microchip Memory Disk Drive File System
*
******************************************************************************
* FileName: Demonstration.c
* Dependencies: FSIO.h
* Processor: PIC18
* Compiler: C18
* Company: Microchip Technology, Inc.
*
* Software License Agreement
*
* The software supplied herewith by Microchip Technology Incorporated
* (the �Company�) for its PICmicro� Microcontroller is intended and
* supplied to you, the Company�s customer, for use solely and
* exclusively on Microchip PICmicro Microcontroller products. The
* software is owned by the Company and/or its supplier, and is
* protected under applicable copyright laws. All rights are reserved.
* Any use in violation of the foregoing restrictions may subject the
* user to criminal sanctions under applicable laws, as well as to
* civil liability for the breach of the terms and conditions of this
* license.
*
* THIS SOFTWARE IS PROVIDED IN AN �AS IS� CONDITION. NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
* TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
* IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
*****************************************************************************/
/*****************************************************************************
Note: This file is included to give you a basic demonstration of how the
functions in this library work. Prototypes for these functions,
along with more information about them, can be found in FSIO.h
*****************************************************************************/
//DOM-IGNORE-BEGIN
/********************************************************************
Change History:
Rev Description
---- -----------------------
1.2.4 - 1.2.6 No Change
1.2.6 Add support for the PIC18F46J50_PIM
1.3.4 Added support for PIC18F8722 on PIC18 Explorer Board
********************************************************************/
//DOM-IGNORE-END
#include "FSIO.h"
#if defined(PIC18F87J50_PIM) // Configuration bits for PIC18F87J50 FS USB Plug-In Module board
#pragma config XINST = OFF // Extended instruction set
#pragma config STVREN = ON // Stack overflow reset
#pragma config PLLDIV = 3 // (12 MHz crystal used on this board)
#pragma config WDTEN = OFF // Watch Dog Timer (WDT)
#pragma config CP0 = OFF // Code protect
#pragma config CPUDIV = OSC1 // OSC1 = divide by 1 mode
#pragma config IESO = OFF // Internal External (clock) Switchover
#pragma config FCMEN = OFF // Fail Safe Clock Monitor
#pragma config FOSC = HSPLL // Firmware must also set OSCTUNE<PLLEN> to start PLL!
#pragma config WDTPS = 32768
// #pragma config WAIT = OFF // Commented choices are
// #pragma config BW = 16 // only available on the
// #pragma config MODE = MM // 80 pin devices in the
// #pragma config EASHFT = OFF // family.
#pragma config MSSPMSK = MSK5
// #pragma config PMPMX = DEFAULT
// #pragma config ECCPMX = DEFAULT
#pragma config CCP2MX = DEFAULT
#elif defined(PIC18F46J50_PIM)
#pragma config WDTEN = OFF //WDT disabled (enabled by SWDTEN bit)
#pragma config PLLDIV = 3 //Divide by 3 (12 MHz oscillator input)
#pragma config STVREN = ON //stack overflow/underflow reset enabled
#pragma config XINST = OFF //Extended instruction set disabled
#pragma config CPUDIV = OSC1 //No CPU system clock divide
#pragma config CP0 = OFF //Program memory is not code-protected
#pragma config OSC = HSPLL //HS oscillator, PLL enabled, HSPLL used by USB
#pragma config T1DIG = ON //Sec Osc clock source may be selected
#pragma config LPT1OSC = OFF //high power Timer1 mode
#pragma config FCMEN = OFF //Fail-Safe Clock Monitor disabled
#pragma config IESO = OFF //Two-Speed Start-up disabled
#pragma config WDTPS = 32768 //1:32768
#pragma config DSWDTOSC = INTOSCREF //DSWDT uses INTOSC/INTRC as clock
#pragma config RTCOSC = T1OSCREF //RTCC uses T1OSC/T1CKI as clock
#pragma config DSBOREN = OFF //Zero-Power BOR disabled in Deep Sleep
#pragma config DSWDTEN = OFF //Disabled
#pragma config DSWDTPS = 8192 //1:8,192 (8.5 seconds)
#pragma config IOL1WAY = OFF //IOLOCK bit can be set and cleared
#pragma config MSSP7B_EN = MSK7 //7 Bit address masking
#pragma config WPFP = PAGE_1 //Write Protect Program Flash Page 0
#pragma config WPEND = PAGE_0 //Start protection at page 0
#pragma config WPCFG = OFF //Write/Erase last page protect Disabled
#pragma config WPDIS = OFF //WPFP[5:0], WPEND, and WPCFG bits ignored
#elif defined(__18F8722)
#pragma config OSC=HSPLL, FCMEN=OFF, IESO=OFF, PWRT=OFF, WDT=OFF, LVP=OFF, XINST=OFF
#else
#endif
char sendBuffer[22] = "This is test string 1";
char send2[2] = "2";
char receiveBuffer[50];
char dirname1[16] = ".\\ONE\\TWO\\THREE";
char dirname2[14] = "ONE\\TWO\\THREE";
char dirname3[14] = "FOUR\\FIVE\\SIX";
char dirname4[60] = "FOUR\\FIVE\\SEVEN\\..\\EIGHT\\..\\..\\NINE\\TEN\\..\\ELEVEN\\..\\TWELVE";
char dirname5[31] = "\\ONE\\TWO\\THREE\\FOUR\\FIVE\\EIGHT";
char dirname6[10] = "FOUR\\NINE";
char dirname7[2];
void main(void) {
FSFILE * pointer;
char path[30];
char count = 30;
char * pointer2;
SearchRec rec;
unsigned char attributes;
unsigned char size = 0, i;
#if (defined(__18CXX) & !defined(PIC18F87J50_PIM)) || defined(__18F8722)
ADCON1 |= 0x0F; // Default all pins to digital
#elif !defined(PIC18F87J50_PIM)
AD1PCFG = 0xFFFF;
#endif
#if defined(PIC18F87J50_PIM)
WDTCONbits.ADSHR = 1; // Select alternate SFR location to access ANCONx registers
ANCON0 = 0xFF; // Default all pins to digital
ANCON1 = 0xFF; // Default all pins to digital
WDTCONbits.ADSHR = 0; // Select normal SFR locations
#endif
#if defined(PIC18F46J50_PIM)
ANCON0 = 0xFF; // Default all pins to digital
ANCON1 = 0xFF; // Default all pins to digital
#endif
//********* Initialize Peripheral Pin Select (PPS) *************************
// This section only pertains to devices that have the PPS capabilities.
// When migrating code into an application, please verify that the PPS
// setting is correct for the port pins that are used in the application.
#if defined(PIC18F46J50_PIM)
RPINR21 = 1; //SDI = RP1
RPOR4 = 10; //RP4 = SCK
RPOR2 = 9; //RP2 = SDO
RPINR22 = 4; //SCK = RP4
//enable a pull-up for the card detect, just in case the SD-Card isn't attached
// then lets have a pull-up to make sure we don't think it is there.
INTCON2bits.RBPU = 0;
#endif
while (!MDD_MediaDetect());
// Initialize the library
while (!FSInit());
#ifdef ALLOW_WRITES
// Set the clock value
// This will determine the create time for the file we're about to make
// This will set the time and date to 3:05:26 PM on July 27, 2007.
if (SetClockVars(2007, 7, 27, 15, 5, 26))
while (1);
// Create a file
pointer = FSfopenpgm("FILE3.TXT", "w");
if (pointer == NULL)
while (1);
// Write 21 1-byte objects from sendBuffer into the file
if (FSfwrite((void *) sendBuffer, 1, 21, pointer) != 21)
while (1);
// FSftell returns the file's current position
if (FSftell(pointer) != 21)
while (1);
// FSfseek sets the position one byte before the end
// It can also set the position of a file forward from the
// beginning or forward from the current position
if (FSfseek(pointer, 1, SEEK_END))
while (1);
// Write a 2 at the end of the string
if (FSfwrite((void*) send2, 1, 1, pointer) != 1)
while (1);
// Set the time again
// When called before fclose, this will determine the last time
// accessed and modified. This time will be 4 seconds after the last one.
if (SetClockVars(2007, 7, 27, 15, 5, 30))
while (1);
// Close the file
if (FSfclose(pointer))
while (1);
// Set the clock again
// This time is the last one possible with the FAT file system
// 11:59:59 PM, December 31, 2106.
if (SetClockVars(2107, 12, 31, 23, 59, 59))
while (1);
// Create a second file
pointer = FSfopenpgm("FILE1.TXT", "w");
if (pointer == NULL)
while (1);
// Write the string to it again
if (FSfwrite((void *) sendBuffer, 1, 21, pointer) != 21)
while (1);
// Close the file
if (FSfclose(pointer))
while (1);
#endif
// Open file 1 in read mode
pointer = FSfopenpgm("FILE3.TXT", "r");
if (pointer == NULL)
while (1);
if (FSrenamepgm("FILE2.TXT", pointer))
while (1);
// Read one four-byte object
if (FSfread(receiveBuffer, 4, 1, pointer) != 1)
while (1);
// Check if this is the end of the file- it shouldn't be
if (FSfeof(pointer))
while (1);
// Close the file
if (FSfclose(pointer))
while (1);
// Make sure we read correctly
if ((receiveBuffer[0] != 'T') ||
(receiveBuffer[1] != 'h') ||
(receiveBuffer[2] != 'i') ||
(receiveBuffer[3] != 's')) {
while (1);
}
#ifdef ALLOW_DIRS
// Create a small directory tree
// Beginning the path string with a '.' will create the tree in
// the current directory. Beginning with a '..' would create the
// tree in the previous directory. Beginning with just a '\' would
// create the tree in the root directory. Beginning with a dir name
// would also create the tree in the current directory
if (FSmkdir(dirname1))
while (1);
// Change to directory THREE in our new tree
if (FSchdir(dirname2))
while (1);
// Create another tree in directory THREE
if (FSmkdir(dirname3))
while (1);
// Create a third file in directory THREE
pointer = FSfopenpgm("FILE3.TXT", "w");
if (pointer == NULL)
while (1);
// Get the name of the current working directory
/* it should be "\ONE\TWO\THREE" */
pointer2 = FSgetcwd(path, count);
if (pointer2 != path)
while (1);
// Simple string length calculation
i = 0;
while (*(path + i) != 0x00) {
size++;
i++;
}
// Write the name to FILE3.TXT
if (FSfwrite((void *) path, size, 1, pointer) != 1)
while (1);
// Close the file
if (FSfclose(pointer))
while (1);
// Create some more directories
if (FSmkdir(dirname4))
while (1);
/*******************************************************************
Now our tree looks like this
\ -> ONE -> TWO -> THREE -> FOUR -> FIVE -> SIX
-> SEVEN
-> EIGHT
NINE -> TEN
-> ELEVEN
-> TWELVE
********************************************************************/
// This will delete only directory eight
// If we tried to delete directory FIVE with this call, the FSrmdir
// function would return -1, since FIVE is non-empty
if (FSrmdir(dirname5, FALSE))
while (1);
// This will delete directory NINE and all three of its sub-directories
if (FSrmdir(dirname6, TRUE))
while (1);
// You can't initialize an array in PIC18 to just a backslash
// Initialize it manually
dirname7[0] = '\\';
dirname7[1] = 0;
// Change directory to the root dir
if (FSchdir(dirname7))
while (1);
#endif
#ifdef ALLOW_FILESEARCH
// Set attributes
attributes = ATTR_ARCHIVE | ATTR_READ_ONLY | ATTR_HIDDEN;
// Functions "FindFirstpgm" & "FindNext" can be used to find files
// and directories with required attributes in the current working directory.
// Find the first TXT file with any (or none) of those attributes that
// has a name beginning with the letters "FILE"
// These functions are more useful for finding out which files are
// in your current working directory
if (FindFirstpgm("FILE*.TXT", attributes, &rec))
while (1);
// Keep finding files until we get FILE2.TXT
while (rec.filename[4] != '2') {
if (FindNext(&rec))
while (1);
}
// Delete file 2.
// NOTE : "FSremove" function deletes specific file not directory.
// To delete directories use "FSrmdir" function
if (FSremove(rec.filename))
while (1);
#endif
/*********************************************************************
The final contents of our card should look like this:
\ -> FILE1.TXT
-> ONE -> TWO -> THREE -> FILE3.TXT
-> FOUR -> FIVE -> SIX
-> SEVEN
*********************************************************************/
while (1);
}CLEAN SUCCESSFUL (total time: 67ms)
make -f nbproject/Makefile-default.mk SUBPROJECTS= .build-conf
make[1]: Entering directory `C:/Microchip Solutions v2012-04-03/MDD File System-SD Card/PIC18F/SD.X'
make -f nbproject/Makefile-default.mk dist/default/production/SD.X.production.hex
make[2]: Entering directory `C:/Microchip Solutions v2012-04-03/MDD File System-SD Card/PIC18F/SD.X'
"X:\Program Files (x86)\Microchip\mplabc18\v3.40\bin\mcc18.exe" -p18F8722 -I"C:/Microchip Solutions v2012-04-03/Microchip/Include/MDD File System" -I"C:/Microchip Solutions v2012-04-03/Microchip/Include" -I"C:/Microchip Solutions v2012-04-03/MDD File System-SD Card/PIC18F" -I"C:/Microchip Solutions v2012-04-03/MDD File System-SD Card" -I "X:\Program Files (x86)\Microchip\mplabc18\v3.40\bin"\\..\\h -fo build/default/production/_ext/1472/Demonstration.o ../Demonstration.c
"X:\Program Files (x86)\Microchip\mplabc18\v3.40\bin\mplink.exe" "..\18f8722_g.lkr" -p18f8722 -w -z__MPLAB_BUILD=1 -u_CRUNTIME -l "X:\Program Files (x86)\Microchip\mplabc18\v3.40\bin"\\..\\lib -o dist/default/production/SD.X.production.cof build/default/production/_ext/1472/Demonstration.o
MPLINK 4.40, Linker
Device Database Version 1.3
Copyright (c) 1998-2011 Microchip Technology Inc.
Error - could not find definition of symbol 'FSremove' in file './build/default/production/_ext/1472/Demonstration.o'.
Errors : 1
make[2]: Leaving directory `C:/Microchip Solutions v2012-04-03/MDD File System-SD Card/PIC18F/SD.X'
make[1]: Leaving directory `C:/Microchip Solutions v2012-04-03/MDD File System-SD Card/PIC18F/SD.X'
make[2]: *** [dist/default/production/SD.X.production.hex] Error 1
make[1]: *** [.build-conf] Error 2
make: *** [.build-impl] Error 2
BUILD FAILED (exit value 2, total time: 901ms)CLEAN SUCCESSFUL (total time: 117ms)
make -f nbproject/Makefile-default.mk SUBPROJECTS= .build-conf
make[1]: Entering directory `C:/Microchip Solutions v2012-04-03/MDD File System-SD Card/PIC18F/SD_Demo.X'
make -f nbproject/Makefile-default.mk dist/default/production/SD_Demo.X.production.hex
make[2]: Entering directory `C:/Microchip Solutions v2012-04-03/MDD File System-SD Card/PIC18F/SD_Demo.X'
"C:\Program Files (x86)\Microchip\xc8\v1.00\bin\xc8.exe" --pass1 --chip=18F8722 -Q -G --asmlist --double=24 --float=24 --emi=wordwrite --opt=all,+asm,-asmfile,+speed,-space,-debug,9 --addrqual=ignore --mode=pro -N31 --warn=0 --summary=default,-psect,-class,+mem,-hex,-file --runtime=default,+clear,+init,-keep,-no_startup,+osccal,-resetbits,-download,-stackcall,+config,+clib,+plib "--errformat=%%f:%%l: error: %%s" "--warnformat=%%f:%%l: warning: %%s" "--msgformat=%%f:%%l: advisory: %%s" -obuild/default/production/main.p1 main.c
"C:\Program Files (x86)\Microchip\xc8\v1.00\bin\xc8.exe" --chip=18F8722 -G --asmlist -mdist/default/production/SD_Demo.X.production.map --double=24 --float=24 --emi=wordwrite --opt=all,+asm,-asmfile,+speed,-space,-debug,9 --addrqual=ignore --mode=pro -N31 --warn=0 --summary=default,-psect,-class,+mem,-hex,-file --runtime=default,+clear,+init,-keep,-no_startup,+osccal,-resetbits,-download,-stackcall,+config,+clib,+plib "--errformat=%%f:%%l: error: %%s" "--warnformat=%%f:%%l: warning: %%s" "--msgformat=%%f:%%l: advisory: %%s" -odist/default/production/SD_Demo.X.production.cof build/default/production/main.p1
Microchip MPLAB XC8 C Compiler (Free Mode) V1.00
Copyright (C) 2012 Microchip Technology Inc.
(1273) Omniscient Code Generation not available in Free mode (warning)
:: advisory: Employing 18F8722 errata work-arounds:
:: advisory: * Corrupted fast interrupt shadow registers
main.c:167: warning: "RAM" is positioned at address 0x0 and has had its address taken; pointer comparisons may be invalid
:0: error: undefined symbols:
_FSgetcwd(dist/default/production\SD_Demo.X.production.obj) _FSfclose(dist/default/production\SD_Demo.X.production.obj) _FSfwrite(dist/default/production\SD_Demo.X.production.obj) _FSremove(dist/default/production\SD_Demo.X.production.obj) _FindNext(dist/default/production\SD_Demo.X.production.obj) _FSrenamepgm(dist/default/production\SD_Demo.X.production.obj) _FSfeof(dist/default/production\SD_Demo.X.production.obj) _FSInit(dist/default/production\SD_Demo.X.production.obj) _FSfread(dist/default/production\SD_Demo.X.production.obj) _FSfseek(dist/default/production\SD_Demo.X.production.obj) _FSftell(dist/default/production\SD_Demo.X.production.obj) _FSchdir(dist/default/production\SD_Demo.X.production.obj) _FSmkdir(dist/default/production\SD_Demo.X.production.obj) _FSrmdir(dist/default/production\SD_Demo.X.production.obj) _FSfopenpgm(dist/default/production\SD_Demo.X.production.obj) _FindFirstpgm(dist/default/production\SD_Demo.X.production.obj) _MDD_SDSPI_MediaDetect(dist/default/production\SD_Demo.X.production.obj) _SetClockVars(dist/default/production\SD_Demo.X.production.obj)
make[2]: Leaving directory `C:/Microchip Solutions v2012-04-03/MDD File System-SD Card/PIC18F/SD_Demo.X'
make[1]: Leaving directory `C:/Microchip Solutions v2012-04-03/MDD File System-SD Card/PIC18F/SD_Demo.X'
(908) exit status = 1
make[2]: *** [dist/default/production/SD_Demo.X.production.hex] Error 1
make[1]: *** [.build-conf] Error 2
make: *** [.build-impl] Error 2
BUILD FAILED (exit value 2, total time: 2s)
#elif defined(__18F8722)
#define USE_PIC18
#define USE_SD_INTERFACE_WITH_SPI
#define INPUT_PIN 1
#define OUTPUT_PIN 0
// Chip Select Signal
#define SD_CS PORTBbits.RB3
#define SD_CS_TRIS TRISBbits.TRISB3
// Card detect signal
#define SD_CD PORTBbits.RB4
#define SD_CD_TRIS TRISBbits.TRISB4
// Write protect signal
#define SD_WE PORTAbits.RA4
#define SD_WE_TRIS TRISAbits.TRISA4
// Registers for the SPI module you want to use
#define SPICON1 SSP1CON1
#define SPISTAT SSP1STAT
#define SPIBUF SSP1BUF
#define SPISTAT_RBF SSP1STATbits.BF
#define SPICON1bits SSP1CON1bits
#define SPISTATbits SSP1STATbits
#define SPI_INTERRUPT_FLAG PIR1bits.SSPIF
// Defines for the HPC Explorer board
#define SPICLOCK TRISCbits.TRISC3
#define SPIIN TRISCbits.TRISC4
#define SPIOUT TRISCbits.TRISC5
// Latch pins for SCK/SDI/SDO lines
#define SPICLOCKLAT LATCbits.LATC3
#define SPIINLAT LATCbits.LATC4
#define SPIOUTLAT LATCbits.LATC5
// Port pins for SCK/SDI/SDO lines
#define SPICLOCKPORT PORTCbits.RC3
#define SPIINPORT PORTCbits.RC4
#define SPIOUTPORT PORTCbits.RC5
#define SPIENABLE SSPCON1bits.SSPEN
#define SPI_INTERRUPT_FLAG_ASM PIR1, 3
// Will generate an error if the clock speed is too low to interface to the card
#if (GetSystemClock() < 400000)
#error System clock speed must exceed 400 kHz
#endif while (!MDD_MediaDetect());
// Initialize the library
while (!FSInit());Las SDHC soportan SPI ? Me parece que no, como máximo siempre se trabajó con memorias hasta 2Gb
hola amigo donde puedo bajar la libreria fat16 1.8 y tambien las mosificaciones de low speed y high speed producen error
donde agrego esas funciones saludos
Saludos!
La verdad es que en proteus todo funciona bien, pero en el rpotoboard nada anda..
Omix, gracias por tu repuesta.
Algo de eso pensé que podría ser, pero ya a estas alturas estoy super mareado :5].
He leído en varios lados y las SD /MMC soportan modos 0 y 3. Tengo en el CCS el MODE=0, pero cuando mido en el osciloscopio, el clock posee un cero para el idle. Cuando pruebo el MODE=3, el clock posee un idle de uno. Buscando en internet, las tablas dicen lo contrario, justo al revés. Entonces, me podrías aclarar, si no es molestia, cómo debería estar el clock y en qué flanco se leería?? Porque de ser esto que está mal, por qué sale todo OK, menos los datos??
Suky, no se cómo me serviría esa prueba ya que, para iniciar el FAT, es necesario leer el primer sector de la SD. Si yo trato de escribir y luego leer lo que escribí, no gano nada. Seguiría sin poder leer la 0x00000000.
/**********************************************
* ANDRE L. V. SILVA
* andreluizeng@yahoo.com.br
*
* change the strings to your own language if you want (it is in portuguese br)
*
* Example of use:
*
*
int main (void)
{
pic initialization....
InicializaSPI ();
InicializaMMC ();
InicializaFAT32 ();
While (TRUE)
{
your code ....
}
return 0;
}
**********************************************/
#include "MMCFat32.h"
#include "string.h"
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
// Funções do cartão MMC
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
int32 FATTable[128];
int32 gFirstEmptyCluster;
FAT32Vars gFAT32Vars;
diskinforec DiskInfo;
FILE gFiles[MAXFILES];
#byte MMCAddressL = gFAT32Vars
#byte MMCAddressH = gFAT32Vars+1
#byte MMCAddressHL = gFAT32Vars+2
#byte MMCAddressHH = gFAT32Vars+3
#byte gStartSectorL = gFAT32Vars+8
#byte gStartSectorH = gFAT32Vars+9
#byte gStartSectorHL = gFAT32Vars+10
//-------------------------------------------------------------------------
// Detecção do MMC
//-------------------------------------------------------------------------
char DetectaMMC (void)
{
char Resp;
TRIS_DETECTA_MMC = ENTRADA;
printf ("\r\nDetectando MMC...");
if (MMC_DETECT)
{
printf ("Nao Conectado !");
printf ("\r\nAguardando Conexao... ");
while (MMC_DETECT);
}
TRIS_DETECTA_MMC = ENTRADA;
MMC_DETECT = SAIDA;
MMC_DETECT = FALSE;
printf ("OK");
return Resp;
}
//-------------------------------------------------------------------------
// Configuração da SPI
//-------------------------------------------------------------------------
void InicializaSPI (char Tipo)
{
TRIS_SPI_SCK = SAIDA;
TRIS_SPI_SDI = ENTRADA;
TRIS_SPI_SDO = SAIDA;
TRIS_SPI_MMC_CS = SAIDA;
MMC_CS = TRUE;
SPI_SCK = TRUE;
SPI_DI = TRUE;
SPI_DO = FALSE;
if (Tipo == MAXIMO)
{
printf ("\r\nAjustando SPI: ");
printf ("5 MHz...");
SSPEN = FALSE;
SSPCON1 = SPI_MASTER_SCK_DIV_4;
SMP = TRUE;
CKE = FALSE;
CKP = TRUE;
SSPEN = TRUE;
}
else if (Tipo == MEDIO)
{
printf ("\r\nAjustando SPI: ");
printf ("1.25 MHz...");
SSPEN = FALSE;
SSPCON1 = SPI_MASTER_SCK_DIV_16;
SMP = TRUE;
CKE = FALSE;
CKP = TRUE;
SSPEN = TRUE;
}
else if (Tipo == MINIMO)
{
printf ("\r\nInicializando SPI: ");
printf ("312.5 KHz...");
SSPEN = FALSE;
SSPCON1 = SPI_MASTER_SCK_DIV_64;
SMP = TRUE;
CKE = FALSE;
CKP = TRUE;
SSPEN = TRUE;
}
printf ("OK");
delay_ms (10);
return;
}
//-------------------------------------------------------------------------
// Função de Seleção do CS do MMC
//-------------------------------------------------------------------------
void SelecionaMMC (boolean Flag)
{
if (Flag)
{
MMC_CS = FALSE;
}
else
{
MMC_CS = TRUE;
}
}
//-------------------------------------------------------------------------
// Função para enviar um dado via SPI
//-------------------------------------------------------------------------
void EnviaMMC (char a)
{
char b;
BF = FALSE;
SSPBUF = a;
while (! BF);
b = SSPBUF;
return;
}
//-------------------------------------------------------------------------
// Função para receber um dado via SPI
//-------------------------------------------------------------------------
char RecebeMMC (void)
{
char b;
BF = FALSE;
SSPBUF = 0xff;
while (! BF);
b = SSPBUF;
return b;
}
//-------------------------------------------------------------------------
// 8 pulsos de clock dummy
//-------------------------------------------------------------------------
void MMC8Clock (void)
{
EnviaMMC (0xff);
return;
}
//-------------------------------------------------------------------------
// Comando de Reset
//-------------------------------------------------------------------------
void ExecutaCMD0 (void)
{
char Resp;
long TimeOut;
char i;
// comando CMD0 - Reset
printf ("\r\n\tResposta ao CMD0...");
do
{
SelecionaMMC (FALSE);
Resp = 0xff;
TimeOut = 100;
// envia pelo pulsos de clock para inicialização
for (i = 0; i < 10; i++) MMC8Clock ();
// envia CMD0 -> Idle state
SelecionaMMC (TRUE);
output_high(PIN_B0);
EnviaMMC (0x40); // CMD0
EnviaMMC (0x00);
EnviaMMC (0x00);
EnviaMMC (0x00);
EnviaMMC (0x00);
EnviaMMC (0x95); // CRC - OK
MMC8Clock ();
// espera pela resposta = 0x01 - caso contrário = falha
while ((Resp != 0x01) && (TimeOut))
{
Resp = RecebeMMC ();
TimeOut--;
}
SelecionaMMC (FALSE);
MMC8Clock ();
// roda enquanto der timeout
} while ((! TimeOut) && Resp!=0x00);
printf ("OK");
return;
}
//-------------------------------------------------------------------------
// Modo SPI
//-------------------------------------------------------------------------
void ExecutaCMD1 (void)
{
char Resp;
long TimeOut;
// comando CMD1 - Modo SPI
printf ("\r\n\tResposta ao CMD1...");
do
{
Resp = 0xff;
TimeOut = 100;
// envia CMD1 -> Modo SPI
SelecionaMMC (TRUE);
EnviaMMC (0x41); // CMD1
EnviaMMC (0x00);
EnviaMMC (0x00);
EnviaMMC (0x00);
EnviaMMC (0x00);
EnviaMMC (0x01); // CRC - OK
MMC8Clock ();
// espera pela resposta = 0x00 - caso contrário = falha
while (Resp && TimeOut)
{
Resp = RecebeMMC ();
TimeOut--;
}
SelecionaMMC (FALSE);
MMC8Clock ();
// roda enquanto der timeout
} while ((! TimeOut) && Resp!=0x00);
printf ("OK");
return;
}
//-------------------------------------------------------------------------
// Ajusta o tamanho do bloco - 512 bytes
//-------------------------------------------------------------------------
void ExecutaCMD16 (void)
{
char Resp;
long TimeOut;
// comando CMD16 - Bloco de 512 bytes
printf ("\r\n\tResposta ao CMD16...");
do
{
Resp = 0xff;
TimeOut = 100;
// envia CMD16 -> block lenght
SelecionaMMC (TRUE);
EnviaMMC (0x50); // CMD16
EnviaMMC (0x00);
EnviaMMC (0x00);
EnviaMMC (0x02);
EnviaMMC (0x00);
EnviaMMC (0x01); // CRC - OK
MMC8Clock ();
// espera pela resposta = 0x00 - caso contrário = falha
while (Resp && TimeOut)
{
Resp = RecebeMMC ();
TimeOut--;
}
SelecionaMMC (FALSE);
MMC8Clock ();
// roda enquanto der timeout
} while ((! TimeOut) && Resp!=0x00);
printf ("OK");
return;
}
//-------------------------------------------------------------------------
// Lê a identificação do cartão - CID
//-------------------------------------------------------------------------
void ExecutaCMD10 (void)
{
char Resp;
long TimeOut;
char i;
char Ano;
char Mes;
char HW;
char FW;
// comando CMD10 - Lê a identificação do cartão
printf ("\r\n\tResposta ao CMD10...");
do
{
Resp = 0xff;
TimeOut = 100;
SelecionaMMC (TRUE);
EnviaMMC (0x4A); //CMD10 - Le CID
EnviaMMC (0x00);
EnviaMMC (0x00);
EnviaMMC (0x00);
EnviaMMC (0x00);
EnviaMMC (0x01);
MMC8Clock ();
// espera pela resposta = 0x00 - caso contrário = falha
while (Resp && TimeOut)
{
Resp = RecebeMMC ();
TimeOut--;
}
// dummy
MMC8Clock ();
// respondeu
if (TimeOut)
{
// // recebe a identificação - binário (8bits)
// printf ("\r\n\r\n\tID do Fabricante: 0x%x", RecebeMMC ()); // identificação para MMCA
//
// // recebe a id de aplicação - binário (16bits)
// printf ("\r\n\tID da Aplicação: 0x");
// for (i = 0; i < 2; i++)
// {
// printf ("%x", RecebeMMC ()); // identificação para MMCA
// }
//
// printf ("\r\n\r\n\tProduto: ");
// for (i = 0; i < 6; i++)
// {
// printf ("%c", RecebeMMC ()); // 6 próximos bytes - Nome do Produto
// }
//
// // revisão do produto - 8bits - BCD
// printf ("\r\n\r\n\tRevisão do Produto: %02d", RecebeMMC ());
//
// printf ("\r\n\tSerial: 0x");
//
// for (i = 0; i < 4; i++)
// {
// printf ("%x", RecebeMMC ()); // 4 próximos bytes - Serial do Produto
// }
//
//
//
//
// FW = Resp & 0x0f; // Firmware = 4bits menos significativos
// HW = (Resp >> 4) & 0x0f; // Hardware = 4bits mais significativos
// printf ("\r\n\tFirmware: %2d", FW);
// printf ("\r\n\tHardware: %02d", HW);
// printf ("\r\n\tFW+HW: 0x%x", Resp);
//
//
//
// Resp = RecebeMMC (); // Mes + Ano;
// Ano = Resp & 0x0f; // Ano = 4bits menos significativos
// Mes = (Resp >> 4) & 0x0f; // Ano = 4bits mais significativos
//
// printf ("\r\n\tAno: %02d", Ano);
// printf ("\r\n\tMes: %02d", Mes);
// printf ("\r\n\tAno+Mes: 0x%x\r\n", Resp);
}
SelecionaMMC (FALSE);
// roda enquanto der timeout
} while (! TimeOut);
printf ("OK");
return;
}
//-------------------------------------------------------------------------
// Lê o formato do cartão - CSD
//-------------------------------------------------------------------------
void ExecutaCMD9 (void)
{
char Resp;
long TimeOut;
// comando CMD9 - Lê o formato do cartão
printf ("\r\n\tResposta ao CMD9...");
do
{
Resp = 0xff;
TimeOut = 100;
SelecionaMMC (TRUE);
EnviaMMC (0x49); //CMD9 - Le CSD
EnviaMMC (0x00);
EnviaMMC (0x00);
EnviaMMC (0x00);
EnviaMMC (0x00);
EnviaMMC (0x01);
MMC8Clock ();
// espera pela resposta = 0x00 - caso contrário = falha
while (Resp && TimeOut)
{
Resp = RecebeMMC ();
TimeOut--;
}
// Respondeu
if (TimeOut)
{
}
SelecionaMMC (FALSE);
// roda enquanto der timeout
} while (! TimeOut);
printf ("OK");
return;
}
//-------------------------------------------------------------------------
// Muda para o modo de high-speed
//-------------------------------------------------------------------------
void ExecutaCMD6 (void)
{
char Resp;
long TimeOut;
// comando CMD6 - high speed (manual mmc plus)
printf ("\r\n\tResposta ao CMD6...");
do
{
Resp = 0xff;
TimeOut = 100;
SelecionaMMC (TRUE);
EnviaMMC (0x46); // CMD6
EnviaMMC (0x03);
EnviaMMC (0xb9);
EnviaMMC (0x01);
EnviaMMC (0x00);
EnviaMMC (0x01); // CRC - OK
MMC8Clock ();
// espera pela resposta = 0x00 - caso contrário = falha
while (Resp && TimeOut)
{
Resp = RecebeMMC ();
TimeOut--;
}
SelecionaMMC (FALSE);
// roda enquanto der timeout
} while (! TimeOut);
printf ("OK");
return;
}
//-------------------------------------------------------------------------
// Inicialização do MMC
//-------------------------------------------------------------------------
void InicializaMMC (void)
{
printf ("\r\nInicializando MMC...");
ExecutaCMD0 ();
ExecutaCMD1 ();
ExecutaCMD16 ();
//ExecutaCMD10 ();
//ExecutaCMD9 ();
printf ("\r\nInicializando MMC...OK");
return;
}
//-------------------------------------------------------------------------
// Le um setor da memória - FAT32
//-------------------------------------------------------------------------
void ReadSector(int32 sector, char *buffer)
{
char errs,response;
char cnt2,cnt3;
#byte sectorL = sector
#byte sectorH = sector+1
#byte sectorHL = sector+2
// if (input(CardInserted)) return;
// Disable_interrupts(GLOBAL);
Restart_wdt();
MMCAddressL = 0;
MMCAddressH = sectorL;
MMCAddressHL = sectorH;
MMCAddressHH = sectorHL;
gFAT32Vars.MMCAddress <<= 1;
SelecionaMMC (TRUE);
EnviaMMC (0x51);
EnviaMMC (MMCAddressHH);
EnviaMMC (MMCAddressHL);
EnviaMMC (MMCAddressH & 0xFE);
EnviaMMC (0);
EnviaMMC (0x01);
errs = 8;
do
{
response = RecebeMMC ();
} while ((--errs) && (response == 0xFF));
errs = 50;
do
{
response = RecebeMMC ();
if (response == 0xFE) break;
delay_ms(1);
} while (--errs);
*0xFE9 = (int16) buffer;
cnt3 = 2;
cnt2 = 0;
do
{
do
{
SSPBUF = 0xFF;
while (!BF);
*0xFEE = SSPBUF;
} while (--cnt2);
} while (--cnt3);
response = RecebeMMC ();
response = RecebeMMC ();
SelecionaMMC (FALSE);
// enable_interrupts(GLOBAL);
}
//-------------------------------------------------------------------------
// Escreve em um setor da memória - FAT32
//-------------------------------------------------------------------------
void WriteSector (int32 sector, char *buffer)
{
char errs;
char response;
char cnt2;
char cnt3;
#byte sectorL = sector
#byte sectorH = sector+1
#byte sectorHL = sector+2
// if (input (CardInserted)) return;
// disable_interrupts(GLOBAL);
// restart_wdt();
MMCAddressL = 0;
MMCAddressH = sectorL;
MMCAddressHL = sectorH;
MMCAddressHH = sectorHL;
gFAT32Vars.MMCAddress <<= 1;
response = 0;
SelecionaMMC (TRUE);
EnviaMMC (0x58);
EnviaMMC (MMCAddressHH);
EnviaMMC (MMCAddressHL);
EnviaMMC (MMCAddressH & 0xFE);
EnviaMMC (0);
EnviaMMC (0x01);
MMC8Clock ();
errs = 8;
do
{
response = RecebeMMC ();
} while (--errs && response==0xFF);
if (response)
{
SelecionaMMC (FALSE);
MMC8Clock();
// enable_interrupts(GLOBAL);
return;
}
MMC8Clock ();
EnviaMMC (0xFE);
*0xFE9 = (int16)buffer;
cnt3 = 2;
cnt2 = 0;
do
{
do
{
SSPBUF = *0xFEE;
while (!BF);
response = SSPBUF;
} while (--cnt2);
} while (--cnt3);
EnviaMMC (0x00);
EnviaMMC (0x01);
response = RecebeMMC ();
response ^= 0xE5;
if (response)
{
goto endwr3;
}
do
{
response = RecebeMMC ();
} while (response == 0);
response = 0;
endwr3:
SelecionaMMC (FALSE);
MMC8Clock();
// enable_interrupts (GLOBAL);
}
//-------------------------------------------------------------------------
// mostra um determinado setor - FAT32
//-------------------------------------------------------------------------
void MostraSetor (int32 setor, char *dados, long tamanho)
{
long i;
long j;
long k;
printf ("\r\n\r\nLendo setor: %lx\r\n\r\n", setor);
ReadSector (setor, dados);
j = 0;
for (i = 0; i < tamanho; i++)
{
printf ("%02X ", dados[i]);
if (j >= 15)
{
printf (" ");
for (k = (i - 15); k < i; k++)
{
if (! isalnum (dados[k])) printf (".");
else printf ("%c", dados[k]);
}
printf ("\r\n");
j = 0;
}
else
{
j++;
}
delay_ms (1);
}
}
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
// Funções da FAT32
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
char IsSelfDir (char *be)
{
if (be[0] == '.' && be[1] == '.') return 0xFF;
else return 0;
}
int16 GetCurrentDOSDate ()
{
int16 retval;
retval = myrec.tm_year - 1980;
retval <<= 9;
retval |= ((int16)myrec.tm_mon << 5);
retval |= (int16)myrec.tm_mday;
return retval;
}
int16 GetCurrentDOSTime ()
{
int16 retval;
retval = myrec.tm_hour;
retval <<= 11;
retval |= ((int16)myrec.tm_min << 5);
retval |= (int16)myrec.tm_sec >> 1;
return retval;
}
void InicializaFAT32 (void)
{
int32 actsector;
char i;
gFirstEmptyCluster = 0;
gFAT32Vars.gStartSector = 0;
// limpa o CREN (comunicação contínua)
printf ("\r\nInicializando FAT32...");
ReadSector (gFAT32Vars.gStartSector, gFiles[MAXFILES-1].IOpuffer);
if (gFiles[MAXFILES-1].IOpuffer[0] != 0xEB)
{
gStartSectorL = gFiles[MAXFILES-1].IOpuffer[0x1C6];
gStartSectorH = gFiles[MAXFILES-1].IOpuffer[0x1C7];
gStartSectorHL = gFiles[MAXFILES-1].IOpuffer[0x1C8];
ReadSector (gFAT32Vars.gStartSector, gFiles[MAXFILES-1].IOpuffer);
}
memcpy (&DiskInfo, gFiles[MAXFILES-1].IOpuffer, sizeof(DiskInfo));
actsector = gFAT32Vars.gStartSector + DiskInfo.Reserved1;
ReadSector (actsector, FATTable);
gFAT32Vars.FATstartidx = 0;
gFAT32Vars.gFirstDataSector = gFAT32Vars.gStartSector + DiskInfo.FATCopies * DiskInfo.hSectorsPerFat + DiskInfo.Reserved1 - 2;
SecFAT1=DiskInfo.Reserved1; // Nº 1º Sector FAT1
SecFAT2=DiskInfo.Reserved1+DiskInfo.holdSectorsPerFat; // Nº 1º Sector FAT2
FirstRootDirSecNum=(unsigned int16)(DiskInfo.Reserved1+(DiskInfo.FATCopies*DiskInfo.holdSectorsPerFat)); // Nº 1º Sector de Directorio Raiz
RootDirSecNum=((unsigned int16)(DiskInfo.hMaxRootEntries/DiskInfo.hBytesPerSector)*32); // Cant. de sectores utilizados por Directorio Raiz.
BytesPerClus=((unsigned int32)DiskInfo.hBytesPerSector*DiskInfo.bSectorsPerCluster); // Nº de Bytes por Cluster.-
for (i = 0; i < MAXFILES; i++)
gFiles[i].Free = TRUE;
printf ("OK");
return;
}
int32 GetNextCluster (int32 curcluster)
{
int32 actsector;
int32 clpage;
char clpos;
clpage = curcluster >> 7;
clpos = curcluster & 0x7F;
if (clpage != gFAT32Vars.FATstartidx)
{
// read in the requested page
actsector = gFAT32Vars.gStartSector+DiskInfo.Reserved1 + clpage;
ReadSector (actsector, FATTable);
gFAT32Vars.FATstartidx = clpage;
}
return (FATTable[clpos]);
}
void SetClusterEntry (int32 curcluster, int32 value)
{
int32 actsector;
int32 clpage;
char clpos;
clpage = curcluster >> 7;
clpos = curcluster & 0x7F;
actsector = gFAT32Vars.gStartSector + DiskInfo.Reserved1 + clpage;
if (clpage != gFAT32Vars.FATstartidx)
{
ReadSector (actsector, FATTable);
gFAT32Vars.FATstartidx = clpage;
}
FATTable[clpos] = value;
WriteSector (actsector, FATTable);
actsector += DiskInfo.hSectorsPerFat;
WriteSector (actsector,FATTable);
}
void ClearClusterEntry (int32 curcluster)
{
int32 actsector;
int32 clpage;
char clpos;
clpage = curcluster >> 7;
clpos = curcluster & 0x7F;
if (clpage != gFAT32Vars.FATstartidx)
{
actsector = gFAT32Vars.gStartSector + DiskInfo.Reserved1 + gFAT32Vars.FATstartidx;
WriteSector (actsector, FATTable);
actsector += DiskInfo.hSectorsPerFat;
WriteSector (actsector,FATTable);
actsector = gFAT32Vars.gStartSector + DiskInfo.Reserved1 + clpage;
ReadSector (actsector,FATTable);
gFAT32Vars.FATstartidx = clpage;
}
FATTable[clpos] = 0;
}
int32 FindFirstFreeCluster ()
{
int32 i;
int32 st;
int32 actsector;
int32 retval;
char j;
st = gFirstEmptyCluster;
for (i = st; i < DiskInfo.hSectorsPerFat; i++)
{
if (i != gFAT32Vars.FATstartidx)
{
actsector = gFAT32Vars.gStartSector + DiskInfo.Reserved1 + i;
ReadSector (actsector, FATTable);
gFAT32Vars.FATstartidx = gFirstEmptyCluster = i;
}
for (j=0;j<128;j++)
{
if (FATTable[j] == 0)
{
retval = i;
retval <<= 7;
retval |= j;
return retval;
}
}
}
return 0x0FFFFFFF;
}
void ConvertFilename (DIR *beDir, char *name)
{
char i;
char j;
char c;
j = 0;
name[0] = 0;
for (i = 0; i < 8; i++)
{
c = beDir->sName[i];
if (c == ' ') break;
name[j++] = c;
}
for (i = 0; i < 3; i++)
{
c = beDir->spam[i];
if ((c == ' ') || (c == 0)) break;
if (!i) name[j++] = '.';
name[j++] = c;
}
name[j++] = 0;
}
void GetDOSName (DIR *pDir, char *fname)
{
char i;
char j;
char leng;
char c;
char toext;
toext = FALSE;
j = 0;
leng = strlen(fname);
for (i = 0; i < 8; i++)
pDir->sName[i] = ' ';
for (i = 0; i < 3; i++)
pDir->spam[i] = ' ';
for (i = 0; i < leng; i++)
{
c = fname[i];
c = toupper(c);
if (c == '.')
{
toext = TRUE;
continue;
}
if (toext) pDir->spam[j++] = c;
else pDir->sName[i] = c;
}
}
void ReadRootDirectory (char fil)
{
int32 actsector;
if (fil > (MAXFILES-1)) return;
actsector = gFAT32Vars.gStartSector + (DiskInfo.FATCopies * DiskInfo.hSectorsPerFat) + DiskInfo.Reserved1;
ReadSector (actsector, gFiles[fil].IOpuffer);
gFAT32Vars.gDirEntrySector = actsector;
gFiles[fil].dirSector = actsector;
gFiles[fil].dirIdx = 0;
memcpy (&(gFiles[fil].DirEntry), gFiles[fil].IOpuffer,32);
gFiles[fil].CurrentCluster = DiskInfo.hRootStartCluster;
}
char FindDirEntry (char *fname, char f)
{
DIR *pDir;
int16 i;
char filename[16];
int32 nextcluster;
int32 actsector;
if (f > (MAXFILES-1)) return FALSE;
gFAT32Vars.gFirstEmptyDirEntry = 0xFFFF;
gFAT32Vars.gFirstDirEntryCluster = 0x0FFFFFFF;
do
{
pDir = (DIR*)(gFiles[f].IOpuffer);
for (i = 0; i < 16; i++)
{
if (((pDir->sName[0] == 0xE5) || (pDir->sName[0] == 0)) && (gFAT32Vars.gFirstEmptyDirEntry == 0xFFFF))
{
// store first free
gFAT32Vars.gFirstEmptyDirEntry = i;
gFAT32Vars.gFirstDirEntryCluster = gFiles[f].CurrentCluster;
}
if (pDir->sName[0] == 0) return FALSE;
ConvertFilename (pDir,filename);
if (!strcmp (filename, fname))
{
memcpy(&(gFiles[f].DirEntry), pDir, 32);
gFiles[f].dirIdx = i;
gFAT32Vars.gDirEntryIdx = i;
return TRUE;
}
pDir++;
}
nextcluster = GetNextCluster (gFiles[f].CurrentCluster);
if ((nextcluster != 0x0FFFFFFF) && (nextcluster != 0))
{
actsector = nextcluster + gFAT32Vars.gFirstDataSector;
ReadSector (actsector, gFiles[f].IOpuffer);
gFAT32Vars.gDirEntrySector = actsector;
gFiles[f].dirSector = actsector;
gFiles[f].CurrentCluster = nextcluster;
}
} while ((nextcluster != 0x0FFFFFFF) && (nextcluster != 0));
return FALSE;
}
// file I/O routines
char *TryFile(char *fname, char *f)
{
char i;
char leng;
char *filename;
(*f) = 0xFF;
for (i = 0; i < MAXFILES; i++)
{
if (gFiles[i].Free)
{
(*f) = i;
break;
}
}
if ((*f) == 0xFF) return 0;
ReadRootDirectory (*f);
filename = fname;
leng = strlen (fname);
for (i = 0; i < leng; i++)
{
if (fname[i] == '/')
{
fname[i] = 0;
if (! cwd (filename,(*f)))
{
gFiles[(*f)].Free = TRUE;
return 0;
}
filename = fname + i + 1;
}
}
return filename;
}
char fcreate (char f, char *fname)
{
DIR *pDir;
int32 actsector;
char actcl;
int16 i;
if (f > (MAXFILES-1)) return FALSE;
if (gFAT32Vars.gFirstDirEntryCluster == 0x0FFFFFFF)
{
// extend the directory file !!!
gFAT32Vars.gFirstDirEntryCluster = FindFirstFreeCluster ();
gFAT32Vars.gFirstEmptyDirEntry = 0;
SetClusterEntry(gFiles[f].CurrentCluster, gFAT32Vars.gFirstDirEntryCluster);
SetClusterEntry(gFAT32Vars.gFirstDirEntryCluster, 0x0FFFFFFF);
actsector = gFAT32Vars.gFirstDirEntryCluster + gFAT32Vars.gFirstDataSector;
for (i = 0; i < 512; i++)
{
gFiles[f].IOpuffer[i] = 0;
}
WriteSector(actsector, gFiles[f].IOpuffer);
}
actsector = gFAT32Vars.gFirstDirEntryCluster + gFAT32Vars.gFirstDataSector;
ReadSector (actsector, gFiles[f].IOpuffer);
pDir = (DIR*)(&(gFiles[f].IOpuffer[32 * gFAT32Vars.gFirstEmptyDirEntry]));
gFiles[f].dirSector = actsector;
gFiles[f].dirIdx = gFAT32Vars.gFirstEmptyDirEntry;
GetDOSName (pDir, fname);
pDir->bAttr = 0;
actcl = FindFirstFreeCluster ();
pDir->hCluster = actcl & 0xFFFF;
pDir->hClusterH = actcl >> 16;
SetClusterEntry (actcl, 0x0FFFFFFF);
pDir->wSize = 0;
gFiles[f].position = 0;
pDir->hDate = GetCurrentDOSDate ();
pDir->hTime = GetCurrentDOSTime ();
WriteSector (actsector, gFiles[f].IOpuffer);
memcpy (&(gFiles[f].DirEntry), pDir,32);
return TRUE;
}
int32 ComposeCluster (char f)
{
int32 retval;
retval = gFiles[f].DirEntry.hClusterH;
retval <<= 16;
retval |= gFiles[f].DirEntry.hCluster;
return retval;
}
char fopen (char *fname, char mode)
{
char found;
char f;
int32 actsector;
int32 actcluster;
int32 nextcluster;
char *filename;
//if (input(CardInserted)) return 0xFF;
filename = TryFile (fname, &f);
if (filename == 0) return 0xFF;
found = FALSE;
found = FindDirEntry (filename,f);
if (!found)
{
if (mode == 'r')
{
gFiles[f].Free = TRUE;
return 0xFF;
}
else
{
if (! fcreate(f, filename)) return 0xFF;
found = TRUE;
}
}
if (found)
{
gFiles[f].Free = FALSE;
gFiles[f].mode = mode;
if (mode == 'a') // com problemas
{
gFiles[f].position = gFiles[f].DirEntry.wSize;
actcluster = ComposeCluster(f);
while ((actcluster != 0x0FFFFFFF) && (nextcluster != 0))
{
nextcluster = GetNextCluster(actcluster);
if ((nextcluster == 0x0FFFFFFF) || (nextcluster == 0)) break;
actcluster = nextcluster;
}
actsector = actcluster + gFAT32Vars.gFirstDataSector;
ReadSector (actsector, gFiles[f].IOpuffer);
gFiles[f].CurrentCluster = actcluster;
gFiles[f].posinsector = gFiles[f].position & 0x01FF;
if ((gFiles[f].posinsector == 0) && (gFiles[f].position != 0))
{
gFiles[f].posinsector = 512;
}
}
else
{
gFiles[f].position = 0;
actsector = ComposeCluster (f);
actsector += gFAT32Vars.gFirstDataSector;
ReadSector(actsector,gFiles[f].IOpuffer);
gFiles[f].CurrentCluster = ComposeCluster (f);
gFiles[f].posinsector = 0;
}
}
return f;
}
void fclose (char f)
{
if (f > (MAXFILES-1)) return;
if ((gFiles[f].mode == 'a') || (gFiles[f].mode == 'w')) fflush(f);
gFiles[f].Free = TRUE;
}
void fflush (char f)
{
int32 actsector;
DIR *pDir;
if (f > (MAXFILES-1)) return;
actsector = gFiles[f].CurrentCluster + gFAT32Vars.gFirstDataSector;
WriteSector (actsector, gFiles[f].IOpuffer);
ReadSector(gFiles[f].dirSector, gFiles[f].IOpuffer);
pDir = (DIR*)(&(gFiles[f].IOpuffer[32 * gFiles[f].dirIdx]));
if (gFiles[f].DirEntry.bAttr & 0x10) pDir->wSize = 0; // if it is a directory
else pDir->wSize = gFiles[f].position;
pDir->hDate = GetCurrentDOSDate ();
pDir->hTime = GetCurrentDOSTime ();
WriteSector(gFiles[f].dirSector,gFiles[f].IOpuffer);
ReadSector(actsector, gFiles[f].IOpuffer);
}
char cwd (char *fname, char f)
{
int32 actsector;
if (f > (MAXFILES-1))
{
return FALSE; // just in case of overaddressing
}
if (IsSelfDir(fname))
{
return TRUE; // already in Root dir
}
if (!FindDirEntry(fname,f))
{
return FALSE; // not found
}
actsector = ComposeCluster (f);
actsector += gFAT32Vars.gFirstDataSector; // read current dir
ReadSector (actsector, gFiles[f].IOpuffer);
gFAT32Vars.gDirEntrySector = actsector;
gFiles[f].dirSector = actsector;
gFiles[f].CurrentCluster = ComposeCluster (f);
return TRUE;
}
void fputch (char be, char f)
{
int32 nextcluster;
int32 actsector;
if (f > (MAXFILES-1)) return;
if (gFiles[f].posinsector == 512)
{
actsector = gFiles[f].CurrentCluster + gFAT32Vars.gFirstDataSector;
WriteSector (actsector,gFiles[f].IOpuffer);
nextcluster = FindFirstFreeCluster ();
if ((nextcluster != 0x0FFFFFFF) && (nextcluster != 0))
{
SetClusterEntry (gFiles[f].CurrentCluster, nextcluster);
SetClusterEntry (nextcluster, 0x0FFFFFFF);
actsector = nextcluster + gFAT32Vars.gFirstDataSector;
//ReadSector (actsector,gFiles[f].IOpuffer); //-- nao tem a necessidade de ler o setor toda vez que for gravar um bloco
gFiles[f].CurrentCluster = nextcluster;
gFiles[f].posinsector = 0;
}
}
gFiles[f].IOpuffer[gFiles[f].posinsector] = be;
gFiles[f].posinsector++;
gFiles[f].position++;
return;
}
void fputstring (char *be, char f)
{
int16 leng;
int16 i;
if (f > (MAXFILES-1)) return;
leng = strlen (be);
for (i = 0; i < leng; i++)
fputch (be[i], f);
}
int16 fread (char *buffer, int16 leng, char f)
{
int16 i;
int16 retv;
char c;
char v;
if (f > (MAXFILES-1)) return 0;
retv = 0;
for (i = 0; i < leng; i++)
{
v = fgetch (&c, f);
if (v)
{
buffer[i] = c;
retv++;
}
else break;
}
return retv;
}
void fwrite (char *buffer, int16 leng, char f)
{
int16 i;
if (f > (MAXFILES-1)) return;
for (i = 0; i < leng; i++)
fputch (buffer[i],f);
}
char fgetch (char *ki, char f)
{
int32 nextcluster;
int32 actsector;
if (f > (MAXFILES-1)) return FALSE;
if (gFiles[f].position >= gFiles[f].DirEntry.wSize) return FALSE;
*ki = gFiles[f].IOpuffer[gFiles[f].posinsector];
gFiles[f].posinsector++;
gFiles[f].position++;
if (gFiles[f].posinsector == 512)
{
nextcluster = GetNextCluster (gFiles[f].CurrentCluster);
if ((nextcluster != 0x0FFFFFFF) && (nextcluster != 0))
{
actsector = nextcluster + gFAT32Vars.gFirstDataSector;
ReadSector (actsector,gFiles[f].IOpuffer);
gFiles[f].CurrentCluster = nextcluster;
gFiles[f].posinsector = 0;
}
}
return TRUE;
}
char remove (char *fname)
{
char i;
char found;
char f;
DIR *pDir;
int32 nextcluster;
int32 currentcluster;
char *filename;
filename = TryFile (fname, &f);
if (filename == 0) return FALSE;
found = FindDirEntry (filename,f);
if (!found)
{
gFiles[f].Free = TRUE;
printf ("Arquivo não encontrado...\r\n");
return FALSE;
}
pDir = (DIR*)(&(gFiles[f].IOpuffer[32 * gFAT32Vars.gDirEntryIdx]));
pDir->sName[0] = 0xE5;
for (i = 1; i < 8; i++)
pDir->sName[i] = ' ';
for (i = 0; i < 3; i++)
pDir->spam[i] = ' ';
WriteSector (gFAT32Vars.gDirEntrySector, gFiles[f].IOpuffer);
currentcluster = ComposeCluster (f);
while ((currentcluster != 0x0FFFFFFF) && (nextcluster != 0))
{
nextcluster = GetNextCluster (currentcluster);
ClearClusterEntry (currentcluster);
currentcluster = nextcluster;
}
ClearClusterEntry (currentcluster);
SetClusterEntry (currentcluster, 0);
currentcluster = gFAT32Vars.gStartSector + DiskInfo.Reserved1 + gFAT32Vars.FATstartidx;
WriteSector (currentcluster, FATTable);
currentcluster += DiskInfo.hSectorsPerFat;
WriteSector (currentcluster, FATTable);
gFiles[f].Free = TRUE;
return TRUE;
}
char getfsize (char *fname, int32 *fsiz)
{
char found;
char f;
DIR *pDir;
char *filename;
filename = TryFile (fname, &f);
if (filename == 0) return FALSE;
found = FindDirEntry (filename, f);
if (!found)
{
gFiles[f].Free = TRUE;
return FALSE;
}
pDir = (DIR*)(&(gFiles[f].IOpuffer[32 * gFAT32Vars.gDirEntryIdx]));
gFiles[f].Free = TRUE;
*fsiz = pDir->wSize;
return TRUE;
}Suky, no se cómo me serviría esa prueba ya que, para iniciar el FAT, es necesario leer el primer sector de la SD. Si yo trato de escribir y luego leer lo que escribí, no gano nada. Seguiría sin poder leer la 0x00000000.
Bueno, ya estando todo OK y funcionando, subo el aporte final.
Me autocorrijo, en el archivo wav está lo que busco
tenía una pregunta para Suky, sí voy cargando todos los bloques de 512bytes en la ram, uno detrás de otro y llego a el último bloque de la tarjeta, sí intento cargar el siguiente, cosa que no es posible por que ya no hay más bloques, la función SDCard_read_block me devolverá un 0 como que ha habido un error?
Lo que quisiera saber es si debo ocupar cualquier pin, o tengo que respetar los pines que me salen en el protocolo SPI de la hoja de datos de mi microcontrolador.
Si alguien tiene un ejemplo asencillo seria genial.
Bueno yo poco se de C, lo estoy haciendo en assembler y ya casi... Bueno le pregunto, En que parte trata de almacenar la variable?
si es en la RAM le sugiero revisar a donde la direcciona la librería ya que el 18F4550 se dispone de 7 bancos de 256 bytes, en tanto el que Ud. menciona solo tiene 5, y puede por tanto estar enviando a alguno que no este implementado para ese pic