Autor Tema: DsPIC30F + uSD  (Leído 5664 veces)

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

Desconectado stecklerdav

  • PIC10
  • *
  • Mensajes: 9
    • Software para simular sistemas opticos
DsPIC30F + uSD
« en: 11 de Septiembre de 2015, 15:32:12 »
Hola a Todos.

Tengo un dsPIC30F6011A trabajando con una micro SD y trato de guardar datos previos a una adquisicion ADC12, se presenta un problema de retraso notable al utilizar librerias MLA (2015).

Estoy utilizando:

MPLABX 3.10
Compilador XC16 Version 1.24
Sniffer Sparkfun uSD (SDHC 4 Gb)
dsPIC30F6011A
MLA libraries 2015

El problema es el siguiente:  Enciendo el ADC12 comienzo la adquisicion, en el momento de guardar el bloque de 512 bytes en la memoria uSD se presenta un retraso considerable en la continuidad de la adquision, parece que tarda mucho tiempo el comando  FILEIO_SD_SectorWrite(&sdCardMediaParameters,sector+0,Buffer_LSB,false) en realizar la tarea de guardar el bloque de informacion.

He utilizado:
HS = 20 MHz
FRC = 7.37 MHz (Interno)

siempre se presenta ese retraso.


aca le anexo parte del codigo que hago en la interrupcion ADC
Código: [Seleccionar]
void ADC_Init()
{   
    //Modulo ADC a 12 Bits~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ADCON1bits.ADON = 0;     
    ConfigIntADC12(ADC_INT_DISABLE);
    #define config1ADC ADC_MODULE_ON & ADC_IDLE_CONTINUE & ADC_FORMAT_INTG & ADC_CLK_AUTO & ADC_AUTO_SAMPLING_ON & ADC_SAMP_OFF
    #define config2ADC ADC_VREF_AVDD_AVSS & ADC_SCAN_OFF & ADC_SAMPLES_PER_INT_12 &  ADC_ALT_BUF_OFF & ADC_ALT_INPUT_OFF
    #define config3ADC ADC_SAMPLE_TIME_1 & ADC_CONV_CLK_INTERNAL_RC & ADC_CONV_CLK_10Tcy
    #define configport ENABLE_AN5_ANA & ENABLE_AN4_ANA & ENABLE_AN3_ANA & ENABLE_AN8_ANA & ENABLE_AN9_ANA & ENABLE_AN10_ANA 
    #define configscan  SCAN_NONE
    OpenADC12(config1ADC,config2ADC,config3ADC,configport,configscan);
    ConfigIntADC12(ADC_INT_PRI_3 & ADC_INT_ENABLE);
    DisableIntADC;
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
}


void __attribute__((__interrupt__,no_auto_psv)) _ADCInterrupt(void)
{
    volatile unsigned int   *ptr,*ptr1,*ptr2,*ptr3,*ptr4,*ptr5;
    k=0;
    while(k<8)
    {
        i=0;
    while(i<512)
            {   
              SetChanADC12(ADC_CH0_POS_SAMPLEA_AN4 & ADC_CH0_NEG_SAMPLEA_NVREF); // Canal A     
              _SAMP=1;           
              while(BusyADC12());                       
              ptr = &ADCBUF4;  //Canal_A  /*(*ptr>>4);*/           
              Buffer_LSB[i]=(( uint8_t) 0x00FF &  *ptr);
              Buffer_MSB[i]=(( uint8_t) 0x00FF & (*ptr >> 8));             
              _DONE=0;
             
              SetChanADC12(ADC_CH0_POS_SAMPLEA_AN5 & ADC_CH0_NEG_SAMPLEA_NVREF); // Canal B
              _SAMP=1;
              while(BusyADC12());                       
              ptr1 = &ADCBUF5;  //Canal_A
              Buffer_LSB[i+1]=( uint8_t) 0x00FF & *ptr1;
              Buffer_MSB[i+1]=( uint8_t) 0x00FF & (*ptr1 >> 8);             
             _DONE=0;
             
              SetChanADC12(ADC_CH0_POS_SAMPLEA_AN3 & ADC_CH0_NEG_SAMPLEA_NVREF);//canal C
              _SAMP=1;
              while(BusyADC12());             
              ptr2 = &ADCBUF3; //Canal_C
              Buffer_LSB[i+2]=( uint8_t) 0x00FF & *ptr2;
              Buffer_MSB[i+2]=( uint8_t) 0x00FF & (*ptr2 >> 8);             
              _DONE=0;
             
              SetChanADC12(ADC_CH0_POS_SAMPLEA_AN8 & ADC_CH0_NEG_SAMPLEA_NVREF); // X
              _SAMP=1;
              while(BusyADC12());             
              ptr3= &ADCBUF8;             
              Buffer_LSB[i+3]=( uint8_t) 0x00FF & *ptr3;
              Buffer_MSB[i+3]=( uint8_t) 0x00FF & (*ptr3 >> 8);             
              _DONE=0;
             
              SetChanADC12(ADC_CH0_POS_SAMPLEA_AN9 & ADC_CH0_NEG_SAMPLEA_NVREF);// Y // 3,799 us
              _SAMP=1;// 542,74 ns
              while(BusyADC12());//             
              ptr4 = &ADCBUF9;// 1,0854 us
              Buffer_LSB[i+4]=( uint8_t) 0x00FF & *ptr4;// 4,8846 us
              Buffer_MSB[i+4]=( uint8_t) 0x00FF & (*ptr4>> 8);// 5,4274 us             
              _DONE=0;// 542,74 ns
             
              SetChanADC12(ADC_CH0_POS_SAMPLEA_AN10 & ADC_CH0_NEG_SAMPLEA_NVREF);// Z
              _SAMP=1;
              while(BusyADC12());             
              ptr5 = &ADCBUFA;
              Buffer_LSB[i+5]=( uint8_t) 0x00FF & *ptr5;
              Buffer_MSB[i+5]=(uint8_t) 0x00FF & (*ptr5 >> 8);               
             _DONE=0;                       
                         
              i+=8;
           }
       
          if(i==512)
          {
           ADCON1bits.ADON = 0;
           FILEIO_SD_SectorWrite(&sdCardMediaParameters,sector+0,Buffer_LSB,false);// 17.910u       //// ACA SE PRESENTA EL GRAN RETRASO CREO YO /////       
           FILEIO_SD_SectorWrite(&sdCardMediaParameters,sector+2,Buffer_MSB,false);// 17.910               
           ADCON1bits.ADON = 1; // aqui encenderlos
           sector+=4;         
           
          }
        k++;
    }
    WriteUART2('F');         
}

int main (void)
{     
    sector=5000;
    bandera=0;
    Bnd=3;
    nosector=5000;
    bloques=0;
    grabacion=0;   
    UART_Init();
    __delay_ms(100);   
    ExtINT123CONFIG();
   __delay_ms(100);     
    PotenciometroInit();
    __delay_ms(100);   
    //I2C_Init();
    __delay_ms(100);   
    ADC_Init();   
    __delay_ms(100);
   
    if (!FILEIO_Initialize()){while(1);}   
    FILEIO_SD_IOInitialize(&sdCardMediaParameters);
    if (FILEIO_SD_MediaDetect(&sdCardMediaParameters) == true)
    {         
     UART_Write_Text("Memoria Detectada");       
     __delay_ms(1);
    }
   FILEIO_SD_MediaDeinitialize(&sdCardMediaParameters);
   FILEIO_SD_MediaInitialize(&sdCardMediaParameters);   
    while(1)
    {       
   
   
    }     
}


Gracias por su tiempo.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: DsPIC30F + uSD
« Respuesta #1 en: 12 de Septiembre de 2015, 04:58:24 »
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:

Citar
"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 :) :

Código: C
  1. int Buffer_AD[256];
  2.  
  3. const int ADCValue[6] = {
  4.         ADC_CH0_POS_SAMPLEA_AN4,
  5.         ADC_CH0_POS_SAMPLEA_AN5,
  6.         ADC_CH0_POS_SAMPLEA_AN3,
  7.         ADC_CH0_POS_SAMPLEA_AN8,
  8.         ADC_CH0_POS_SAMPLEA_AN9,
  9.         ADC_CH0_POS_SAMPLEA_AN10
  10. }
  11.  
  12. void __attribute__((__interrupt__,no_auto_psv)) _ADCInterrupt(void)
  13. {
  14.     int   *ptr,*ptrv,k;
  15.  
  16.     *ptr = ADCValue;            // Pointer a la base del array
  17.  
  18.  
  19.     for(k=0;k<8;k++)
  20.     {
  21.         for(*ptrv=Buffer_AD;*ptrv<=&Buffer_AD[255];*ptrv++)
  22.            {    
  23.               SetChanADC12(*ptr++ & ADC_CH0_NEG_SAMPLEA_NVREF); // Apuntamos al primer valor, y luego aumentamos al siguiente
  24.               _SAMP=1;
  25.               while(BusyADC12());
  26.               *ptrv = ADCBUF0;
  27.               if(ptr>&ADCValue[5]){*ptr = ADCValue;}
  28.               _DONE=0;
  29.            }
  30.        
  31.         ADCON1bits.ADON = 0;
  32.         FILEIO_SD_SectorWrite(&sdCardMediaParameters,sector+4*k,Buffer_LSB,false);// 17.910u       //// ACA SE PRESENTA EL GRAN RETRASO CREO YO /////        
  33.         FILEIO_SD_SectorWrite(&sdCardMediaParameters,sector+(4*k)+2,Buffer_MSB,false);// 17.910                
  34.         ADCON1bits.ADON = 1; // aqui encenderlos
  35.         }
  36.     }
  37.     sector+=32;
  38.     WriteUART2('F');          
  39. }

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
« Última modificación: 13 de Septiembre de 2015, 06:32:33 por KILLERJC »

Desconectado stecklerdav

  • PIC10
  • *
  • Mensajes: 9
    • Software para simular sistemas opticos
Re: DsPIC30F + uSD
« Respuesta #2 en: 26 de Septiembre de 2015, 17:50:58 »
Hola KILLERJC, muchas gracias por la orientacion sobre punteros. Lo que trate fue empezar una biblioteca de funciones desde cero y obtuve resultados semejantes...

Tome algunas funciones sobre comunicaciones SPI y manual de Tarjetas SD (Physical Layer Simplified Specification Version 4.10 January 22, 2013 SD Group Panasonic Corporation), para crear algunas funciones sobre amacenamiento masivo e hice mi propia biblioteca para dsPIC30F.

este link es de donde obtuve las funciones SPI-SD:  http://nerdclub-uk.blogspot.co.uk/2012/11/how-spi-works-with-sd-card.html

A continuacion estan las funciones de la libreria que modifique para mi uso.


Código: C
  1. void ADC_Init(){
  2.     //Modulo ADC a 12 Bits~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3.     ADCON1bits.ADON = 0;    
  4.     //ConfigIntADC12(ADC_INT_DISABLE);
  5.     #define config1ADC ADC_MODULE_OFF & ADC_IDLE_CONTINUE & ADC_FORMAT_INTG & ADC_CLK_AUTO & ADC_AUTO_SAMPLING_OFF & ADC_SAMP_OFF
  6.     #define config2ADC ADC_VREF_AVDD_AVSS & ADC_SCAN_OFF & ADC_SAMPLES_PER_INT_1 &  ADC_ALT_BUF_OFF & ADC_ALT_INPUT_OFF
  7.     #define config3ADC ADC_SAMPLE_TIME_8 & ADC_CONV_CLK_INTERNAL_RC & ADC_CONV_CLK_Tcy
  8.     #define configport ENABLE_AN5_ANA & ENABLE_AN4_ANA & ENABLE_AN3_ANA & ENABLE_AN8_ANA & ENABLE_AN9_ANA & ENABLE_AN10_ANA  
  9.     #define configscan  SCAN_NONE
  10.     OpenADC12(config1ADC,config2ADC,config3ADC,configport,configscan);
  11.     //SetChanADC12(ADC_CH0_POS_SAMPLEA_AN4 & ADC_CH0_NEG_SAMPLEA_NVREF); // Canal A
  12.    // ConfigIntADC12(ADC_INT_PRI_3 & ADC_INT_ENABLE);
  13.    // DisableIntADC;
  14.     //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  15. }
  16.  
  17. void sdSpiInit(unsigned int u){
  18.     CloseSPI1();  
  19.     # define config1SPI FRAME_ENABLE_OFF & FRAME_SYNC_OUTPUT & ENABLE_SDO_PIN & SPI_MODE16_OFF & SPI_SMP_OFF & SPI_CKE_OFF & SLAVE_ENABLE_OFF & CLK_POL_ACTIVE_LOW & MASTER_ENABLE_ON& SEC_PRESCAL_2_1 & u
  20.     # define config2SPI SPI_ENABLE & SPI_IDLE_CON & SPI_RX_OVFLOW_CLR
  21.     OpenSPI1(config1SPI, config2SPI);    
  22. }
  23.  
  24. uint8_t sdSpiByte(uint8_t data){    
  25.     SPI1BUF = data;    
  26.     while(!(SPI1STATbits.SPIRBF));  
  27.     return  SPI1BUF;
  28. }
  29.  
  30. uint8_t sdCrc7(uint8_t* chr,uint8_t cnt,uint8_t crc){
  31.      uint8_t i, a;
  32.      uint8_t Data;
  33.      for(a = 0; a < cnt; a++){          
  34.         Data = chr[a];          
  35.         for(i = 0; i < 8; i++){              
  36.            crc <<= 1;
  37.            if( (Data & 0x80) ^ (crc & 0x80) ) {crc ^= 0x09;}              
  38.            Data <<= 1;
  39.           }
  40.      }    
  41.      return crc & 0x7F;
  42. }
  43.  
  44. bool  sdSendCommand(uint8_t cmd, uint32_t param){    
  45.      uint8_t send[6];    
  46.      send[0] = cmd | 0x40;
  47.      send[1] = param >> 24;
  48.      send[2] = param >> 16;
  49.      send[3] = param >> 8;
  50.      send[4] = param;
  51.      send[5] = (sdCrc7(send, 5, 0) << 1) | 1;    
  52.      for(cmd = 0; cmd < sizeof(send); cmd++){
  53.           sdSpiByte(send[cmd]);
  54.      }
  55.      return true;
  56. }
  57.  
  58. uint8_t  sdReadResp(void){
  59.      uint8_t  v;
  60.      uint16_t i = 0;    
  61.      do{                
  62.           v = sdSpiByte(0xFF);      
  63.        }while((i++ < 128) & (v == 0xFF));    
  64.      return v;
  65. }
  66.  
  67. uint8_t sdCommandAndResponse(uint8_t cmd, uint32_t param){  
  68.      uint8_t ret;          
  69.      sdSpiByte(0xFF);
  70.      sdSendCommand(cmd, param);
  71.      ret = sdReadResp();  
  72.      return ret;
  73. }
  74.  
  75. void sdClockSpeed(bool fast){
  76.      CloseSPI1();            
  77.      if(fast)
  78.      {        
  79.          sdSpiInit(PRI_PRESCAL_1_1);        
  80.      }
  81.      else
  82.      {  
  83.          sdSpiInit(PRI_PRESCAL_64_1);      
  84.      }    
  85. }
  86.  
  87. void sdChipSelect(bool active){
  88.      LATFbits.LATF0 = !active;  
  89. }
  90.  
  91. void fatal(uint8_t val){         // Usado para deteccion de errores
  92.      uint8_t k;    
  93.           for(k = 0; k < val; k++)
  94.           { __delay_ms(100);
  95.             UART_Write_Text("Error");
  96.             WriteUART2(13);
  97.             WriteUART2(10);        
  98.           }      
  99.      while(1)
  100.      {
  101.          Sleep();
  102.      }
  103. }
  104.  
  105. bool sdInit(){        
  106.      uint8_t v =1;  
  107.      sdSpiInit(PRI_PRESCAL_16_1);
  108.      sdSpiByte(0xFF); // Envio basura para mover el reloj    
  109.      sdClockSpeed(false); // slow clock      
  110.      sdChipSelect(0); // CS inactive      
  111.      for(v = 0; v < 20; v++)
  112.      { // 80 ciclos de reloj 20 x 4 ciclos por instruccion = 80 ciclos de reloj
  113.           sdSpiByte(0xFF);     //tren de pulsos de reloj para que inicialice modo SPI        
  114.      }
  115.      sdChipSelect(1); // CS active    
  116.      v = sdCommandAndResponse(0, 0); // reset de la uSD  CMD0    
  117.      if(!v){fatal(2);} // compruebo que haya respondido ok la uSD. si es 0  es error          
  118.      v = sdCommandAndResponse(8, 0x000001AA); // Indico a la SD que trabaje con voltaje entre 2.7 y 3.6 voltios (Tarjetas SDHC y SDXC))
  119.      if(!v){fatal(3);}//Devuelve el valor de 1 si eeta todo bien    
  120.      do{  __delay_ms(50);
  121.           sdCommandAndResponse(55, 0); // activo los comandos alternativos ACMD41
  122.           v = sdCommandAndResponse(41,0x40000000); // reset de la uSD CMD1  (Le asigno el HCS=1) (Tarjetas SDHC y SDXC))            
  123.        }while(v);    
  124.      if(v){fatal(4);}    
  125.      v = sdCommandAndResponse(16, 512);//sec sector size
  126.      if(v){fatal(5);}    
  127.      v = sdCommandAndResponse(59, 0);//crc off
  128.      if(v){fatal(6);}  
  129.      // now set the sd card up for full speed
  130.      sdClockSpeed(true);
  131.    /*  UART_Write_Text("SD Modo SPI");
  132.      WriteUART2(13);
  133.      WriteUART2(10);   */
  134.      return true;
  135. }
  136.  
  137. void sdSecReadStop(){
  138.      uint8_t v;
  139.      // read back the two CRC bytes  
  140.      v = sdSpiByte(0xFF);  
  141.      v = sdSpiByte(0xFF);    
  142.    
  143. }
  144.  
  145. bool sdReadBlock(uint32_t sec, uint8_t *Buff){    
  146.      uint8_t v;
  147.      uint16_t cy=0,cv=0,i=0;    
  148.      v =  sdCommandAndResponse (17, ((uint32_t)sec) << 9);
  149.      if (!v)
  150.          {          
  151.             do{
  152.                 v = sdSpiByte(0xFF);
  153.               }while((v == 0xFF));
  154.              
  155.              
  156.             if (v!=0xFE)
  157.                {              
  158.                     fatal(2);
  159.                     return false;
  160.                }
  161.             else{            
  162.                     do
  163.                      {                      
  164.                         v = sdSpiByte(0xFF);            
  165.                         *Buff++= v;                    
  166.                         cy++;
  167.                     }while(cy<512);
  168.                     sdSecReadStop();                    
  169.                 }
  170.           return true;
  171.          
  172.      }
  173. }
  174.  
  175. bool sdWriteByteToSector(uint8_t b){    
  176.      uint8_t r;    
  177.      r=sdSpiByte(b);          
  178.      bytesWritten++;
  179.      return true;      
  180. }
  181.  
  182. bool sdWriteBlockStart(uint32_t sec,uint8_t *Buff){
  183.      uint8_t v,r;
  184.      uint16_t iy;
  185.      
  186.      v =  sdCommandAndResponse(24, ((uint32_t)sec) << 9);
  187.      if(!v) {    
  188.           // keep track of how many bytes we've written in this sector
  189.           // (when we hit 512 we should expect some extra bytes in the packet data)    
  190.           bytesWritten=0;          
  191.           // send the correct token for CMD17/18/24 (0xFE)
  192.           // REMEMBER the token for CMD25 is 0xFC              
  193.           r=sdSpiByte(0xFE);
  194.              for(iy=0; iy<512; iy++){
  195.                         sdWriteByteToSector(*Buff++);
  196.                     }
  197.                         // send two CRC bytes
  198.                     while(bytesWritten<512){
  199.                              sdSpiByte(0xFF);
  200.                             bytesWritten++;              
  201.                          }        
  202.                    sdSpiByte(0x00);
  203.                    sdSpiByte(0x00);
  204.                    // response should immediately follow
  205.                    // (for writing, we're looking for 0bXXX00101 data accepted)
  206.                    r=sdSpiByte(0x00);
  207.                    //WriteUART2(r);
  208.                    r=(r>>1)&0b00000111;
  209.                    if(r!=2)
  210.                    {
  211.                        fatal(5);
  212.                    }
  213.                    while (r!=0xFF){
  214.                       r=sdSpiByte(0xFF);
  215.                    }                  
  216.                  
  217.                    return true;        
  218.      }
  219.     return false;
  220. }

Me funciono todo muy bien inicialice correctamente la uSD V2.0 luego procedi a utilizarla.


Luego coloque el codigo que utilice en mi programa principal.



Código: C
  1. void Conversion_UART(unsigned long A){        // de Long a Float
  2.  
  3.     Muestreo=0;
  4.     Caracter=' ';
  5.     Muestreo= A * 3300;     // 3.3v = 3300 mV
  6.     Muestreo = (Muestreo / 4095);    // numero de posibles valores en mi caso es una conversion de 12-bit A/D 1023 valores
  7.     Caracter = (Muestreo / 1000);   // de mV a V.    
  8.     WriteUART2(48+Caracter);
  9.     __delay_ms(2);
  10.     WriteUART2('.');
  11.      __delay_ms(2);  
  12.     Caracter = (Muestreo / 100) % 10;    
  13.     WriteUART2(48+Caracter);
  14.      __delay_ms(2);
  15.     Caracter = (Muestreo / 10) % 10;
  16.     WriteUART2(48+Caracter);
  17.      __delay_ms(2);
  18.     Caracter = (Muestreo / 1) % 10;
  19.     WriteUART2(48+Caracter);
  20.      __delay_ms(2);
  21.     WriteUART2(13);
  22.     WriteUART2(10);    
  23. }
  24. void __attribute__((__interrupt__,no_auto_psv)) _INT1Interrupt(void) // esta interrupcion leo bloques de 512 bytes para enviarlos uart
  25. {  
  26.     _ADON=0;
  27.     bloques=1;
  28.     __delay_ms(5000);
  29.     i=0;
  30.     nosector=5000;
  31.     while(nosector<sector)
  32.           {        
  33.                     sdChipSelect(1); // CS inactive            
  34.                     sdReadBlock(nosector+0,Buffer2_LSB);
  35.                     sdChipSelect(0); // CS inactive
  36.                                        
  37.                     sdChipSelect(1); // CS inactive
  38.                     sdReadBlock(nosector+1,Buffer2_MSB);
  39.                     sdChipSelect(0); // CS inactive
  40.                     //__delay_ms(100);
  41.                     nosector+=2 ;
  42.                    
  43.                    // FILEIO_SD_SectorRead(&sdCardMediaParameters,nosector+0,Buffer2_LSB);                  
  44.                   //  FILEIO_SD_SectorRead(&sdCardMediaParameters,nosector+4,Buffer2_MSB);
  45.                    //LATGbits.LATG15=0;                    
  46.                    for(ii=0;ii<512;ii++)// es 512
  47.                    {
  48.                        channel = (uint16_t)(Buffer2_MSB[ii] << 8 | Buffer2_LSB[ii]); // de pruebas                    
  49.                        Conversion_UART(channel);                      
  50.                    }
  51.                    
  52.                    
  53.           }  
  54.     _INT1IF = 0;    
  55. }
  56. void __attribute__((__interrupt__,no_auto_psv)) _INT2Interrupt(void) // esta interrupcion inicia la conversion ADC12
  57. {      
  58.     WriteUART2('I');  
  59.     sector=5000;        
  60.     _ADON=1;
  61.     __delay_ms(2000);
  62.     bloques=0;
  63.     i=0;
  64.     _INT2IF = 0;
  65. }
  66.  
  67. int main (void)
  68. {   TRISFbits.TRISF0 = 0 ;  
  69.     bandera=0;  
  70.     bloques=1;
  71.     sector=5000;
  72.     nosector=5000;
  73.     UART_Init();
  74.     __delay_ms(100);    
  75.     ExtINT123CONFIG();
  76.     __delay_ms(100);    
  77.     PotenciometroInit();
  78.     __delay_ms(100);
  79.     I2C_Init();
  80.     __delay_ms(100);
  81.     ADC_Init();    
  82.     __delay_ms(100);
  83.     sdInit();
  84.     __delay_ms(100);
  85.     //UART_Write_Text("Memoria Detectada");
  86.    
  87.     while(1)
  88.     {
  89.         if (bloques==0)
  90.         {
  91.             if(i<512){
  92.              SetChanADC12(ADC_CH0_POS_SAMPLEA_AN4); // Canal A      
  93.               _SAMP=1;          
  94.               while(!ADCON1bits.DONE);                      
  95.               ptr = &ADCBUF0;  //Canal_A              
  96.               Buffer_LSB[i]=(( uint8_t) 0x00FF &  *ptr);
  97.               Buffer_MSB[i]=(( uint8_t) 0x00FF & (*ptr >> 8));
  98.              
  99.              // Conversion_UART(*ptr);
  100.             _DONE=0;              
  101.               SetChanADC12(ADC_CH0_POS_SAMPLEA_AN5); // Canal B
  102.               _SAMP=1;
  103.               while(!ADCON1bits.DONE);                        
  104.               ptr = &ADCBUF0;  //Canal_A
  105.               Buffer_LSB[i+1]=( uint8_t) 0x00FF & *ptr;
  106.               Buffer_MSB[i+1]=( uint8_t) 0x00FF & (*ptr >> 8);
  107.              // Conversion_UART(*ptr);
  108.             _DONE=0;            
  109.               SetChanADC12(ADC_CH0_POS_SAMPLEA_AN3);//canal C
  110.               _SAMP=1;
  111.               while(!ADCON1bits.DONE);            
  112.               ptr = &ADCBUF0; //Canal_C
  113.               Buffer_LSB[i+2]=( uint8_t) 0x00FF & *ptr;
  114.               Buffer_MSB[i+2]=( uint8_t) 0x00FF & (*ptr >> 8);
  115.              // Conversion_UART(*ptr);
  116.              _DONE=0;            
  117.               SetChanADC12(ADC_CH0_POS_SAMPLEA_AN8); // X
  118.               _SAMP=1;
  119.               while(!ADCON1bits.DONE);            
  120.               ptr= &ADCBUF0;              
  121.               Buffer_LSB[i+3]=( uint8_t) 0x00FF & *ptr;
  122.               Buffer_MSB[i+3]=( uint8_t) 0x00FF & (*ptr >> 8);
  123.              // Conversion_UART(*ptr);
  124.              _DONE=0;          
  125.               SetChanADC12(ADC_CH0_POS_SAMPLEA_AN9);// Y // 3,799 us
  126.               _SAMP=1;// 542,74 ns
  127.               while(!ADCON1bits.DONE);//              
  128.               ptr = &ADCBUF0;// 1,0854 us
  129.               Buffer_LSB[i+4]=( uint8_t) 0x00FF & *ptr;// 4,8846 us
  130.               Buffer_MSB[i+4]=( uint8_t) 0x00FF & (*ptr>> 8);// 5,4274 us
  131.             //  Conversion_UART(*ptr);              
  132.              _DONE=0;          
  133.               SetChanADC12(ADC_CH0_POS_SAMPLEA_AN10);// Z
  134.               _SAMP=1;
  135.               while(!ADCON1bits.DONE);              
  136.               ptr = &ADCBUF0;
  137.               Buffer_LSB[i+5]=( uint8_t) 0x00FF & *ptr;
  138.               Buffer_MSB[i+5]=(uint8_t) 0x00FF & (*ptr >> 8);
  139.              // Conversion_UART(*ptr);              
  140.               _DONE=0;
  141.               Buffer_LSB[i+6]=0;
  142.               Buffer_MSB[i+6]=0;
  143.               Buffer_LSB[i+7]=0;
  144.               Buffer_MSB[i+7]=0;
  145.               i+=8;  
  146.             }          
  147.            
  148.             if (i==512)
  149.             {                
  150.                
  151.                // _ADON=0;
  152.               // sdChipSelect(1); // CS inactive                
  153.                sdWriteBlockStart(sector+0,Buffer_LSB);                
  154.               // sdChipSelect(0); // CS inactive
  155.               // sector++;
  156.                 //__delay_ms(50);
  157.               //  sdChipSelect(1); // CS inactive
  158.                sdWriteBlockStart(sector+1,Buffer_MSB);              
  159.              //  sdChipSelect(0); // CS inactive
  160.                //__delay_ms(5);
  161.                // //__delay_ms(50)
  162.                sector+=2;
  163.                // _ADON=1;              
  164.                
  165.                // WriteUART2('F');
  166.                 i=0;          
  167.             }                      
  168.         }        
  169.     }
  170. }




he probado muchas variantes, siempre con el mismo resultado,debo tener quizas algun problema de optimizacion que no logro ver con la poca experiencia, tambien se que esta el MODO BUS SD el cual utiliza 4 hilos de datos no solo 1 hilo como hace el  protocolo SPI, pero creo que es propietario y el microcontrolador PIC no lo tiene , pienso que tendre que investigar sobre el protocolo DMA creo que es mucho mas rapido que el SPI tendre que cambiarme al dsPIC33EP.

Gracias a todos, saludos.



« Última modificación: 26 de Septiembre de 2015, 20:15:51 por stecklerdav »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: DsPIC30F + uSD
« Respuesta #3 en: 27 de Septiembre de 2015, 00:26:00 »
Creo que al final del mensaje te habia puesto las soluciones a tus problemas.
No tenia nada que ver con la libreria de la SD. Pero bueno si lograste crear tu libreria es mucho mejor.

El principal problema que tenias al principio era un error de concepto, vos no podes hacer cosas que ocupen demasiado tiempo en una interrupcion. Por que estas evitando que esa interrupcion u otras puedan ejecutarse.
El objetivo de la interrupcion es que pueda responder al instante que ocurre y que luego continue con el programa como estaba. Ese fue tu GRAN problema. Si observas:
Código: C
  1. void __attribute__((__interrupt__,no_auto_psv)) _ADCInterrupt(void)
  2. {
  3.     volatile unsigned int   *ptr,*ptr1,*ptr2,*ptr3,*ptr4,*ptr5;
  4.     k=0;
  5.     while(k<8)
  6.     {
  7.         i=0;
  8.     while(i<512)
  9.             {    
  10.               SetChanADC12(ADC_CH0_POS_SAMPLEA_AN4 & ADC_CH0_NEG_SAMPLEA_NVREF); // Canal A      
  11.               _SAMP=1;          
  12.               while(BusyADC12());                      
  13.               ptr = &ADCBUF4;  //Canal_A  /*(*ptr>>4);*/            
  14.               Buffer_LSB[i]=(( uint8_t) 0x00FF &  *ptr);
  15.               Buffer_MSB[i]=(( uint8_t) 0x00FF & (*ptr >> 8));            
  16.               _DONE=0;
  17.              
  18.               SetChanADC12(ADC_CH0_POS_SAMPLEA_AN5 & ADC_CH0_NEG_SAMPLEA_NVREF); // Canal B
  19.               _SAMP=1;
  20.               while(BusyADC12());                        
  21.               ptr1 = &ADCBUF5;  //Canal_A
  22.               Buffer_LSB[i+1]=( uint8_t) 0x00FF & *ptr1;
  23.               Buffer_MSB[i+1]=( uint8_t) 0x00FF & (*ptr1 >> 8);            
  24.              _DONE=0;
  25.              
  26.               SetChanADC12(ADC_CH0_POS_SAMPLEA_AN3 & ADC_CH0_NEG_SAMPLEA_NVREF);//canal C
  27.               _SAMP=1;
  28.               while(BusyADC12());            
  29.               ptr2 = &ADCBUF3; //Canal_C
  30.               Buffer_LSB[i+2]=( uint8_t) 0x00FF & *ptr2;
  31.               Buffer_MSB[i+2]=( uint8_t) 0x00FF & (*ptr2 >> 8);            
  32.               _DONE=0;
  33.              
  34.               SetChanADC12(ADC_CH0_POS_SAMPLEA_AN8 & ADC_CH0_NEG_SAMPLEA_NVREF); // X
  35.               _SAMP=1;
  36.               while(BusyADC12());            
  37.               ptr3= &ADCBUF8;              
  38.               Buffer_LSB[i+3]=( uint8_t) 0x00FF & *ptr3;
  39.               Buffer_MSB[i+3]=( uint8_t) 0x00FF & (*ptr3 >> 8);              
  40.               _DONE=0;
  41.              
  42.               SetChanADC12(ADC_CH0_POS_SAMPLEA_AN9 & ADC_CH0_NEG_SAMPLEA_NVREF);// Y // 3,799 us
  43.               _SAMP=1;// 542,74 ns
  44.               while(BusyADC12());//              
  45.               ptr4 = &ADCBUF9;// 1,0854 us
  46.               Buffer_LSB[i+4]=( uint8_t) 0x00FF & *ptr4;// 4,8846 us
  47.               Buffer_MSB[i+4]=( uint8_t) 0x00FF & (*ptr4>> 8);// 5,4274 us              
  48.               _DONE=0;// 542,74 ns
  49.              
  50.               SetChanADC12(ADC_CH0_POS_SAMPLEA_AN10 & ADC_CH0_NEG_SAMPLEA_NVREF);// Z
  51.               _SAMP=1;
  52.               while(BusyADC12());              
  53.               ptr5 = &ADCBUFA;
  54.               Buffer_LSB[i+5]=( uint8_t) 0x00FF & *ptr5;
  55.               Buffer_MSB[i+5]=(uint8_t) 0x00FF & (*ptr5 >> 8);              
  56.              _DONE=0;                        
  57.                          
  58.               i+=8;
  59.            }
  60.        
  61.           if(i==512)
  62.           {
  63.            ADCON1bits.ADON = 0;
  64.            FILEIO_SD_SectorWrite(&sdCardMediaParameters,sector+0,Buffer_LSB,false);// 17.910u       //// ACA SE PRESENTA EL GRAN RETRASO CREO YO /////        
  65.            FILEIO_SD_SectorWrite(&sdCardMediaParameters,sector+2,Buffer_MSB,false);// 17.910                
  66.            ADCON1bits.ADON = 1; // aqui encenderlos
  67.            sector+=4;          
  68.            
  69.           }
  70.         k++;
  71.     }
  72.     WriteUART2('F');          
  73. }

En la interrupcion estas justamente esperando que te de el resultado del ADC lo cual eso es algo erroneo, vos deberias configurar el ADC para que muestree todos los canales que deseas y que cuando muestree todo recien ahi se ejecute la interrupcion. El cual pasas a guardar los valores.

Tampoco podes poner un while en una interrupcion, por el mismo caso que nombre al comienzo, y mucho menos escribir la SD ahi que tambien es otro proceso lento.
Entonces tu solucion era configurar adecuadamente el ADC, Para que convierta todos los canales que quieras, ( que haga muestre simultaneo ) etc. Y configuras para que produzca la interrupcion en la misma cantida de canales de entrada, ejemplo si tenes 5 canales, entonces cada 5 valores del ADC.

Luego en tu programa principal (fuera de la interrupcion) preguntabas cuando estaba completo el buffer de datos y te ponias a grabar. Mientras estas grabando ocurre que el ADC sigue funcionando y cuando tome nuevamente esas 5 medidas, ocurrira la interrupcion, entonces nunca la SD te "trabaria" la toma de datos. En fin, creo que eso era todo tu problema y creo que repetis un poco en tu segundo codigo, recorda que las interrupciones deberian durar lo menos posible. El codigo tomando el del primer post y "arreglado" solo como para que me entiendas a que me refiero:

Código: C
  1. void ADC_Init()
  2. {    
  3.     //Modulo ADC a 12 Bits~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4.     ADCON1bits.ADON = 0;    
  5.     ConfigIntADC12(ADC_INT_DISABLE);
  6.     #define config1ADC ADC_MODULE_ON & ADC_IDLE_CONTINUE & ADC_FORMAT_INTG & ADC_CLK_AUTO & ADC_AUTO_SAMPLING_ON & ADC_SAMP_OFF
  7.     #define config2ADC ADC_VREF_AVDD_AVSS & ADC_SCAN_OFF & ADC_SAMPLES_PER_INT_12 &  ADC_ALT_BUF_OFF & ADC_ALT_INPUT_OFF
  8.     #define config3ADC ADC_SAMPLE_TIME_1 & ADC_CONV_CLK_INTERNAL_RC & ADC_CONV_CLK_10Tcy
  9.     #define configport ENABLE_AN5_ANA & ENABLE_AN4_ANA & ENABLE_AN3_ANA & ENABLE_AN8_ANA & ENABLE_AN9_ANA & ENABLE_AN10_ANA  
  10.     #define configscan  SCAN_NONE
  11.     OpenADC12(config1ADC,config2ADC,config3ADC,configport,configscan);
  12.     ConfigIntADC12(ADC_INT_PRI_3 & ADC_INT_ENABLE);
  13.     DisableIntADC;
  14.     //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  15. }
  16.  
  17.  
  18.  
  19. int     Buffer_1[512],Buffer_2[512];
  20. int     indicedatos=0;
  21. bool    buffer1completo=0,buffer2completo=1;
  22.  
  23.  
  24.  
  25. void __attribute__((__interrupt__,no_auto_psv)) _ADCInterrupt(void)
  26. {
  27.     volatile unsigned int *ptradc;
  28.     short int i;
  29.     ptr = &ADCBUF0;  //Canal_A  /*(*ptr>>4);*/
  30.     if (!buffer1completo)
  31.     {
  32.         for(i=0;i<6;i++)
  33.                 if (indicedatos<512 && !buffer1completo)
  34.                    Buffer_1[indicedatos++]=*ptr++;      //Copia los 6 valores del buffer del ADC
  35.                 else
  36.                 {
  37.                    buffer1completo=1;
  38.                    indicedatos=0
  39.                    Buffer_2[indicedatos++]=*ptr++;
  40.                 }
  41.     }
  42.  }
  43.  
  44. int main (void)
  45. {
  46.  
  47.     int j;
  48.     short int *ptrdatos;    
  49.     sector=5000;
  50.     bandera=0;
  51.     Bnd=3;
  52.     nosector=5000;
  53.     bloques=0;
  54.     grabacion=0;    
  55.     UART_Init();
  56.     __delay_ms(100);  
  57.     ExtINT123CONFIG();
  58.    __delay_ms(100);    
  59.     PotenciometroInit();
  60.     __delay_ms(100);  
  61.     //I2C_Init();
  62.     __delay_ms(100);  
  63.     ADC_Init();    
  64.     __delay_ms(100);
  65.    
  66.     if (!FILEIO_Initialize()){while(1);}  
  67.     FILEIO_SD_IOInitialize(&sdCardMediaParameters);
  68.     if (FILEIO_SD_MediaDetect(&sdCardMediaParameters) == true)
  69.     {        
  70.      UART_Write_Text("Memoria Detectada");        
  71.      __delay_ms(1);
  72.     }
  73.    FILEIO_SD_MediaDeinitialize(&sdCardMediaParameters);
  74.    FILEIO_SD_MediaInitialize(&sdCardMediaParameters);
  75.     while(1)
  76.     {        
  77.        if (buffer1completo)
  78.        {
  79.            ptrdatos = (short int)Buffer_1;
  80.            for(j=0;j<1024;j++)
  81.                 FILEIO_SD_SectorWrite(&sdCardMediaParameters,sector+0,ptrdatos++,false);// 17.910u
  82.            sector+=4;          
  83.        }
  84.    
  85.     }      
  86. }

Es mas que obvio que el codigo no funciona y tiene muchisimos errores, pero es para que me entiendas a que me referia. Creo que el secreto aca esta en configurar bien el ADC que es un dolor de cabeza con todas las cosas que tiene.
Por que 2 buffers y no 1 ?
Por que eso me permite que cuando se lleno uno, comenzar a grabarlo, y que la rutina del ADC comienze a llenar el segundo buffer, sin afectar a los valores de escritura de la SD

Desconectado stecklerdav

  • PIC10
  • *
  • Mensajes: 9
    • Software para simular sistemas opticos
Re: DsPIC30F + uSD
« Respuesta #4 en: 01 de Octubre de 2015, 02:15:00 »
Hola a todos

Gracias por la direccion que me distes KILLERJC   (((:-))) excelente, a pesar de probar muchas y muchas variantes ya obtuve resultados positivos en lo que buscaba.

aca les dejo a la comunidad la resolucion del doble buffer para guardar datos en una tarjeta microSD.

Hardware:

dsPIC30F6011A.
microSD sniffer sparkfun.
microSD kinstong 4 GB Ver 2.0 Categoria 4 (4 MB/s).
y otros componentes mas.

Software:

XC16 Ver 1.25.
MLA Libraries 2015.

Reloj:

FRC =7.37MHz.
FCY = 7.37 MHz / 4 = 1.825 Mhz ---- 1.825 MIPS.


Código: C
  1. void ADC_Init(){
  2.     //Modulo ADC a 12 Bits~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3.     ADCON1bits.ADON = 0;
  4.     SetChanADC12(ADC_CH0_POS_SAMPLEA_AN4 & ADC_CH0_NEG_SAMPLEA_NVREF); // Canal A    
  5.     ConfigIntADC12(ADC_INT_DISABLE);
  6.     #define config1ADC ADC_MODULE_ON & ADC_IDLE_CONTINUE & ADC_FORMAT_INTG & ADC_CLK_AUTO & ADC_AUTO_SAMPLING_ON & ADC_SAMP_OFF
  7.     #define config2ADC ADC_VREF_AVDD_AVSS & ADC_SCAN_OFF & ADC_SAMPLES_PER_INT_14 &  ADC_ALT_BUF_OFF & ADC_ALT_INPUT_OFF
  8.     #define config3ADC ADC_SAMPLE_TIME_7 & ADC_CONV_CLK_INTERNAL_RC & ADC_CONV_CLK_Tcy
  9.     #define configport ENABLE_AN5_ANA & ENABLE_AN4_ANA & ENABLE_AN3_ANA & ENABLE_AN8_ANA & ENABLE_AN9_ANA & ENABLE_AN10_ANA  
  10.     #define configscan  SCAN_NONE
  11.     OpenADC12(config1ADC,config2ADC,config3ADC,configport,configscan);
  12.     SetChanADC12(ADC_CH0_POS_SAMPLEA_AN4 & ADC_CH0_NEG_SAMPLEA_NVREF); // Canal A
  13.     ConfigIntADC12(ADC_INT_PRI_3 & ADC_INT_ENABLE);
  14.     DisableIntADC;
  15.     //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  16. }
  17.  
  18.  
  19. void __attribute__((__interrupt__,no_auto_psv)) _ADCInterrupt(void)
  20. {
  21.    volatile unsigned int* ptr;
  22.    
  23.    
  24.    if(!buffercompleto){            
  25.        
  26.               SetChanADC12(ADC_CH0_POS_SAMPLEA_AN4); // Canal A              
  27.               while(!ADCON1bits.DONE);              
  28.               ptr = &ADCBUF0;  //Canal_A              
  29.               Buffer_LSB[i]=(( uint8_t) 0xFF &  *ptr);
  30.               Buffer_MSB[i]=(( uint8_t) 0xFF & (*ptr >> 8));            
  31.             _DONE=0;              
  32.              
  33.              SetChanADC12(ADC_CH0_POS_SAMPLEA_AN5); // Canal B
  34.              while(!ADCON1bits.DONE);                        
  35.               ptr = &ADCBUF0;  //Canal_A
  36.               Buffer_LSB[i+1]=( uint8_t) 0xFF & *ptr;
  37.               Buffer_MSB[i+1]=( uint8_t) 0xFF & (*ptr >> 8);          
  38.             _DONE=0;            
  39.              
  40.               i+=8;            
  41.            }
  42.    
  43.    else
  44.           {
  45.               SetChanADC12(ADC_CH0_POS_SAMPLEA_AN4); // Canal A          
  46.               while(!ADCON1bits.DONE);              
  47.               ptr = &ADCBUF0;  //Canal_A              
  48.               Buffer2_LSB[i]=(( uint8_t) 0xFF &  *ptr);
  49.               Buffer2_MSB[i]=(( uint8_t) 0xFF & (*ptr >> 8));          
  50.               _DONE=0;                        
  51.            
  52.               SetChanADC12(ADC_CH0_POS_SAMPLEA_AN5); // Canal B          
  53.               while(!ADCON1bits.DONE);                        
  54.               ptr = &ADCBUF0;  //Canal_A
  55.               Buffer2_LSB[i+1]=( uint8_t) 0xFF & *ptr;
  56.               Buffer2_MSB[i+1]=( uint8_t) 0xFF & (*ptr >> 8);          
  57.             _DONE=0;            
  58.              
  59.            
  60.               i+=8;          
  61.         }  
  62.  
  63.          if ((i==512) )
  64.             {
  65.              _ADON=0;      
  66.             }                
  67.         _ADIF=0;      
  68. }
  69.  
  70. int main (void)
  71. {  
  72.     TRISFbits.TRISF0 = 0 ;  
  73.     buffercompleto=3;
  74.     sector=5000;
  75.     nosector=5000;
  76.     i=0;
  77.     UART_Init();
  78.     __delay_ms(100);
  79.     ADC_Init();    
  80.  
  81.    
  82.    
  83.      //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  84.     if (!FILEIO_Initialize()){while(1);}  
  85.     FILEIO_SD_IOInitialize(&sdCardMediaParameters);
  86.     if (FILEIO_SD_MediaDetect(&sdCardMediaParameters) == true)
  87.     {        
  88.      UART_Write_Text("Memoria Detectada");        
  89.      __delay_ms(1);
  90.     }
  91.    FILEIO_SD_MediaInitialize(&sdCardMediaParameters);
  92.     while(1)
  93.     {
  94.      
  95.         if ((i==512) & (!buffercompleto) )
  96.            {
  97.                buffercompleto=!buffercompleto;
  98.                
  99.                WriteUART2('1'); // 6.51289
  100.                i=0;              
  101.                _ADIF=1;
  102.                _ADON=1;              
  103.                FILEIO_SD_SectorWrite(&sdCardMediaParameters,sector++,Buffer_LSB,false);// 17.910u        
  104.                FILEIO_SD_SectorWrite(&sdCardMediaParameters,sector++,Buffer_MSB,false);// 17.910                
  105.            }
  106.        
  107.       if ((i==512) & (buffercompleto) )
  108.           {  
  109.               buffercompleto=!buffercompleto;
  110.              
  111.                WriteUART2('2'); // 6.51289
  112.                 i=0;
  113.                _ADIF=1;
  114.                _ADON=1;                
  115.                FILEIO_SD_SectorWrite(&sdCardMediaParameters,sector++,Buffer2_LSB,false);// 17.910u        
  116.                FILEIO_SD_SectorWrite(&sdCardMediaParameters,sector++,Buffer2_MSB,false);// 17.910
  117.                
  118.                
  119.        }      
  120.     }
  121. }


Bueno es un codigo bastante resumido.  Funciono la adquisicion de manera positiva sin ningun retraso al guardar datos en la SD.

Saludos a todos.


Anexo:
Le coloque una señal triangular con DC de 2 Hz para observar las discontinuidades.

trato de subir la imagen pero no he podido no me da la opcion.











« Última modificación: 10 de Octubre de 2015, 12:42:11 por stecklerdav »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: DsPIC30F + uSD
« Respuesta #5 en: 01 de Octubre de 2015, 02:37:53 »
Creo que tu codigo se podria mejorar aun mas. Pero vas por buen camino, es decir va mejorando de lo que era.

Estoy mas que seguro que podes configurar el ADC para que te muestree los canales que vos queres, suponete AN1,AN3,AN4,AN5,AN8,AN10, incluso usando 2 canales para dividirlo en 2 y hacer aun mas rapido la conversion. Por eso te apunte en el primer post el PDF que habla sobre el ADC, y la pagina donde muestra como es que muestrea varios canales (ANs) y multiplexados sin estar seleccionando el canal uno mismo en el codigo. Lo hace todo solo el modulo del micro. Solo hay que configurarlo correctamente. Y tal ves eso te lleve a configurarlo registro a registro lo cual puede ser un poco tedioso.

Otra cosa mas. Si estas tratando de obtener una señal seria bueno que lo hagas cada cierto tiempo. Suponete que estas tratando de conseguir la señal de diente de sierra. que posee una frecuencia de 1Khz, asi que necesitas como minimo una sampleo de 2Khz (por la freq de Nyquist para la reconstruccion de la señal ), pero si al idea tuya es verla entonces mejor unos 8 o 10 veces de esa forma ver bien la forma de onda, entonces estoy hablando de unos 10kSa ( k Samples ), otra cosa importante es.. el tiempo entre esas tomas de datos, deberian ser en intervalos exactos de tiempo. con 10kSa/s (10.000 muestras por segundo) es lo mismo que tomar una conversion de la señal cada 0.1ms, hasta ahora yo no veo en tu programa un timer que controle exactamente cuando es que se dispara la conversion del ADC. Sino que esta corriendo libremente.

El por que te digo esto? Por 2 motivos, una es tratar de obtener la señal con la menor deformacion, y la otra que puede que no necesites samplear tan rapidamente la señal y baste con menos valores, lo cual son menos datos a grabar y se podria aprovechar el espacio de la SD

En fin todo esto es una mejora pero implica mayor conocimiento del microcontrolador, mayor conocimiento de la señal a tomar, y seguro que varias cosas mas.
Si esas feliz con lo que tenes podes seguir con eso hasta que aparezca algo que te moleste realmente y tengas que modificarlo. Eso ya queda decision tuya.

Citar
trato de subir la imagen pero no he podido no me da la opcion.

Esto es por que los administradores estan trabajando en el foro, el cual desabilitaron la carga de archivos adjuntos.

Desconectado stecklerdav

  • PIC10
  • *
  • Mensajes: 9
    • Software para simular sistemas opticos
Re: DsPIC30F + uSD
« Respuesta #6 en: 07 de Octubre de 2015, 14:00:27 »
Hola a todos.

Hola KILLERJC.
 
Tome cada canal 512 muestras/s  debido a que una señal ECG posee un ancho de banda de 150 Hz aproximado después de filtros analógicos, debido a esto estoy muestreando a 512 Hz  y mi frecuencia de nyquist es de 300 Hz minimo. a 512 estoy bien.


Mi idea es muestrear 6 canales por segundo, cada canal con 512 muestras. en total debo muestrear 512 muestras x 6 canales= 3072 muestras por segundo. en consecuencia la frecuencia de muestreo es de Fs = 3,072 Khz osea, 325,5 us entre muestreo.
Fs = 3,072 Khz
Ts = 325.5 us

por otro lado estoy configurando el ADC12 para ver si puedo obtener esa velocidad. estoy trabajando a 1.825 MIPS para ahorrar energía debido a que funciona con batería portátil si lo pongo a funcionar a 5 MIPS consumo mucho.

otra detalle que no tengo claro es que en el datasheet dice : debes colocar un numero de muestreo por interrupcion mayor o igual a la cantidad de canales a muestrear porque sino puede quedar un canal por fuera. ok eso lo entiendo. segun mis pruebas si bajo de 14 muestreos por interrupcion existe un retraso significativo en guardar los datos en la uSD se corta el muestreo.

El DSPIC30F6011A posee un solo S&H por eso solo tengo un CH0 no veo poder muestrear mas rapido con esa ventaja que tienen otros DSPIC. quizas con el escaneo de entradas podria tengo que probar.

seguire simulando y cualquier avance que tenga estare por aca de nuevo.

Gracias a todos y a KILLERJC.







 
« Última modificación: 07 de Octubre de 2015, 14:24:20 por stecklerdav »

Desconectado Caryr

  • PIC10
  • *
  • Mensajes: 4
Re:DsPIC30F + uSD
« Respuesta #7 en: 27 de Octubre de 2018, 01:36:51 »
Disculpa crees que puedas pasar tu codigo o fuentes, estoy realizando el mismo proyecto para mi universidad y tengo problemas al querer guardar datos en la SD tengo mas de 2 semanas investigando y no he tenido muchos avances

Desconectado stecklerdav

  • PIC10
  • *
  • Mensajes: 9
    • Software para simular sistemas opticos
Re:DsPIC30F + uSD
« Respuesta #8 en: 27 de Octubre de 2018, 02:11:41 »
Hola Caryr pasame tu correo y te lo envio.

saludos

David Steckler.

Desconectado Caryr

  • PIC10
  • *
  • Mensajes: 4
Re:DsPIC30F + uSD
« Respuesta #9 en: 27 de Octubre de 2018, 19:31:14 »
carlosdanielcg8@hotmail.com muchas gracias

Desconectado Pinolillo16

  • PIC18
  • ****
  • Mensajes: 324
Re:DsPIC30F + uSD
« Respuesta #10 en: 06 de Abril de 2020, 17:17:07 »
Podrias colocar el codigo para que sea referencia?