El PIC no posee una controladora de SD.
Asi que lo mas seguro es que te comuniques a traves del SPI. El SPI segun el diagrama puede tener la misma frecuencia que el Fcy, es decir Fosc/4 , si tenes 20 Mhz , tendrias 5Mhz, crei en primer momento que era lo que realmente te esta limitando.
Ya que tenes que tiene que abrir todo el sistema (seguro que FAT 16 o 32 )
Abrir el archivo. (Nuevamente si esta con un sistema de archivos)
Guardar todo por SPI. y mas cosas.
Lo cual son 512 bytes * 2, Estas guardando 1 MB en la tarjeta cada ves que lo haces. por SPI a 5Mhz, hice los numeros y no son muy desalentadores, son apenas 2ms para todo eso en solo datos todos seguidos como si tuviera un buffer de envio gigante.
Esto si fuera muy directo y se guardara en binario, y ahora comienzo a encontrar problemas:
Esto lo haces 8 veces ( que esto no es el problema ), pero lo que es peor es que esta realizado en una interrupcion., Bueno estas retrasando las interrupciones, no es nada... o tal ves si ?
Esto implica que tengas que esperar que terminen las conversiones!!!!. Si! tu micro puede ir a 20Mhz/40MHz, ejecutar instrucciones muy rapidamente, y vos estas haciendo que lo espere perdiendo en el proceso hacer unas 500 instrucciones por ejemplo.
Otra implicacion, suponiendo que es un aparato medico ECG, en el que luego vas a recrear la onda con los datos obtenidos, es que deneria ocurrir el muestreo en intervalos de tiempo conocidos, tu programa no cumple eso en parte por lo que dije 2 lineas atras.
Ademas de eso, en la SD, si no me equivoco tambien hay tiempos de espera, respuestas proveninentes desde la SD, etc etc etc etc etc y muchos mas etc. que van a hacer de tu programa algo lento de lo que ya es.
Ademas hay otras cosas que me dan dudas (Que estoy seguro que es asi), no tengo idea como esta configurado el buffer, si de 16 o 8 bits. Pero hay otras cosas que me parecen que estan mal. Como que para leer el resultado del ADC AN5 estas leyendo justamente la posicion del buffer 5. Voy a quotear algo:
"That's not how it works... that's not how any of this works!"
Te dejo un documento que provee Microchip explicando el ADC
http://ww1.microchip.com/downloads/en/DeviceDoc/70046E.pdf(El ejemplo 17.15.6 te va a ser de GRAN ayuda)
En resumen, va llenando desde 0 hasta 15, solo vuelve a comenzar cuando DONE se pone a 1, es decir ahi comienza nuevamente desde buffer0, si vos haces SAMP esperas y DONE=0 (forma manual), siempre deberias leer el buffer 0.
Ahora para que tu codigo realmente funcione deberia leer las 10 entradas ANx para que estuvieran en los lugares que queres. aun asi hacer que convierta 4 lecturas mas de las que debe es un gran retraso en el tiempo.
Tambien veo que usas 2 buffer de 512 bytes, pero solo usas algunos, ya que estas aumentando i cada 8, y solo tenes 6 lecturas, es decir que de cada 8 posiciones del array, 2 son desperdiciadas, o que de esas 1024 bytes, 256 bytes son desperdiciados.
De todas formas hay muchos errores ahi. Considero prudente buscar un ejemplo de como hacer las cosas con el ADC/SPI + interrupciones.
Solo por curiosidad intente hacer lo mismo que tenes con punteros, no tengo ni idea si funciona pero solo por curiosidad, para ver si podia hacerlo
:
int Buffer_AD[256];
const int ADCValue[6] = {
ADC_CH0_POS_SAMPLEA_AN4,
ADC_CH0_POS_SAMPLEA_AN5,
ADC_CH0_POS_SAMPLEA_AN3,
ADC_CH0_POS_SAMPLEA_AN8,
ADC_CH0_POS_SAMPLEA_AN9,
ADC_CH0_POS_SAMPLEA_AN10
}
void __attribute__((__interrupt__,no_auto_psv)) _ADCInterrupt(void)
{
int *ptr,*ptrv,k;
*ptr = ADCValue; // Pointer a la base del array
for(k=0;k<8;k++)
{
for(*ptrv=Buffer_AD;*ptrv<=&Buffer_AD[255];*ptrv++)
{
SetChanADC12(*ptr++ & ADC_CH0_NEG_SAMPLEA_NVREF); // Apuntamos al primer valor, y luego aumentamos al siguiente
_SAMP=1;
while(BusyADC12());
*ptrv = ADCBUF0;
if(ptr>&ADCValue[5]){*ptr = ADCValue;}
_DONE=0;
}
ADCON1bits.ADON = 0;
FILEIO_SD_SectorWrite(&sdCardMediaParameters,sector+4*k,Buffer_LSB,false);// 17.910u //// ACA SE PRESENTA EL GRAN RETRASO CREO YO /////
FILEIO_SD_SectorWrite(&sdCardMediaParameters,sector+(4*k)+2,Buffer_MSB,false);// 17.910
ADCON1bits.ADON = 1; // aqui encenderlos
}
}
sector+=32;
WriteUART2('F');
}
De todas formas el codigo esta mal en muchos aspectos, ahi ya dije anteriormente, cuales son los errores que existen.
Tambien asignas a tu puntero el mismo valor una y otra ves, a pesar que creaste 6 punteros ( que si observas y los valores es guardan en el buffer desde 0 a 5, solo necesitas 1)
Esto no deberia ser TAN complejo asi como lo ves, tu codigo si llegas a configurar bien tu ADC seria extremadamente simple.
Tenes que averiguar bien bien bien como trabajar con el ADC, si no mal recuerdo se puede configurar para que lea todos los canales que quieras y que se levante una interrupcion por ejemplo cuando llegaron 12 o la mitad de valores. O cuando termina la conversion. Eso hace que entra una ves a la interrupcion para guardar los valores y sale de la interrupcion, y en tu programa pincipal esperas hasta que termine de juntar todo ( o la mitad, asi el ADC sigue llenando la otra mitad ) y recien ahi guardas en la SD. Esto fuera de la interrupcion. En las interrupciones deberia estar prohibido poner un while a la espera de un valor, o loops muy grandes, o delays.
Espero no haberme equivocado en nada de lo que dije, el codigo que puse nuevamente es por que tenia ganas de ver si se podia hacer nada mas.
En fin, soluciones, como dije:
- Configurar correctamente el ADC, si es time-based vas a necesitar ademas de un timer, para que este dispare la conversion de todos los canales del ADC ( todos me refiero unicamente a los que te interesan)
- En la interrupcion solo guardar el valor obtenido desde el ADC. Es interesante hacerte notar que es posible configurar el ADC para que en ves de poner todo en un registro de 16bits lo haga en 2 de 8, aunque esto signifique poder tomar la mitad de las medidas (Pero menos codigo, menos trabajo en separarlos en 8 bits cada uno,menos intrucciones,mas velocidad,mas tiempo a escribir la SD). Supongamos que tenes 2 buffers (o 1 de 512 que separas virtualmente en 256-256). Cuando completa el primer buffer de datos, procede a llenar el segundo buffer y avisa que esta completo el primero (un flag a 1). Lo mismo cuando se llena el segundo, comienza a llenar el primero y avisa que se completo el segundo. Aca tenes opciones, si aun nada leyo,grabo,etc los valores a la SD podrias detectarlo y parar de tomar muestras del ADC, o enviar un error de que algo esta ocurriendo.
- En el programa principal, solo inicializas la tarjeta, el Media (imagino que es el sistema de archivos), y dentro de tu while solo preguntas por si algun buffer esta completo, cuando detectas que esta completo, simplemente escribis todo ese buffer a la SD y cuando termino avisas por medio de una bandera ( de la misma forma como cuando esta completo ) que ya ese buffer esta grabado ( una solucion simple es poner a 0 el flag de que el buffer esta completo).
No se exactamente de cuanto son los sectores, creo que eso es formateable ya que debe depender del tamaño de los mismos, y la otra es que tenes que tener cuidado con no pasarte, en tu programa no hay limitante en cantidad de "sectores" sino que sigue y sigue aumentando 4 en cada pasada.
Tambien imagino que debe haber un tiempo de adquisicion de datos. Lo cual te va a acotar la cantidad de muestras. O directamente llenara hasta que se canse y llene una tarjeta de memoria.
No creo que nadie quiera trabajar con 1Gb de informacion, es demasiado engorroso,lento,etc.
PD: tu nombre aparece en el screenshot, no se si queres borrarlo o tenes problemas de privacidad, solo hacertelo notar por si se te habia pasado por alto