Autor Tema: ADC ,muestreando 10 ó mas entradas, p24hj256gp610  (Leído 2875 veces)

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

Desconectado pablolode

  • PIC16
  • ***
  • Mensajes: 123
ADC ,muestreando 10 ó mas entradas, p24hj256gp610
« en: 01 de Noviembre de 2012, 11:18:32 »
Hola ,pase del pic 18f al pic 24h porque este tiene hasta 32 entradas analogicas las cuales quiero hacer funcionar para tomar  muestras simultaneas de 10 ó mas sensores, no es tan sencillo como con los pic18 ya que tiene el plus del DMA para guardar las muestras,pero me le anime¡¡¡¡
y ahora estoy estancado¡¡¡
tengo este ejemplo que toma 8 muestas de cada entrada ( 4 entradas analogicas)y los guarda en el buffer del DMA,pero al agregarle mas entradas ,ya no me guarda los
valores, solo me guarda el de 2 entradas.
¿¿¿estare calculando mal los tiempos????

mi confIguracion (si mis calculos no me fallan) :

XTAL=4MHZ
FCY=FOSC/2=2MHZ
TCY=1/FCY=500uS
TAD=TCY(ADCS+1)= 32uS

estos son los cambios en la configuracion de perifericos que  realise al agregarle 1 entrada mas.


     AD1CSSL = 0x001F; // Scan AIN0, AIN1, AIN2, AIN3  AIN4 inputs
  //AD1CSSL = 0x000F; // Scan AIN0, AIN1, AIN2, AIN3   inputs

     AD1CON2bits.SMPI = 4; // 5 ADC buffers
  //AD1CON2bits.SMPI = 3; // 4 ADC buffers
 

     DMA0CNT = 39; // 40 DMA request (5 buffers, each with 8 words)
  //DMA0CNT = 31; // 32 DMA request (4 buffers, each with 8 words)


Código: [Seleccionar]
//#include <p24hj256gp610.h>

//FileName: adcDrv1.c




void ProcessADCSamples(unsigned int * AdcBuffer);
/*==========================================================================================
ADC Initialization for Channel Scan
===========================================================================================*/
void initAdc1(void)
{
AD1CON1bits.FORM = 1; // Data Output Format: Signed Integer
AD1CON1bits.SSRC = 2; // Sample Clock Source: GP Timer starts conversion
AD1CON1bits.ASAM = 1; // ADC Sample Control: Sampling begins immediately after conversion
AD1CON1bits.AD12B = 0; // 10-bit ADC operation
AD1CON1bits.SIMSAM = 0; // Samples multiple channels individually in sequence

AD1CON2bits.BUFM = 0;
AD1CON2bits.CSCNA = 1; // Scan Input Selections for CH0+ during Sample A bit
AD1CON2bits.CHPS = 0; // Converts CH0

AD1CON3bits.ADRC = 0; // ADC Clock is derived from Systems Clock
AD1CON3bits.ADCS = 63; // ADC Conversion Clock (1/2M) *64=32us

//AD1CHS0: A/D Input Select Register
AD1CHS0bits.CH0SA = 0; // MUXA +ve input selection (AIN0) for CH0
AD1CHS0bits.CH0NA = 0; // MUXA -ve input selection (Vref-) for CH0

//AD1CHS123: A/D Input Select Register
AD1CHS123bits.CH123SA = 0; // MUXA +ve input selection (AIN0) for CH1
AD1CHS123bits.CH123NA = 0; // MUXA -ve input selection (Vref-) for CH1

//AD1CSSH/AD1CSSL: A/D Input Scan Selection Register
AD1CSSH = 0x0000;
AD1CSSL = 0x001F; // Scan AIN0, AIN1, AIN2, AIN3  AIN4 inputs
 //AD1CSSL = 0x000F; // Scan AIN0, AIN1, AIN2, AIN3   inputs

AD1CON1bits.ADDMABM = 0; // DMA buffers are built in scatter/gather mode
AD1CON2bits.SMPI = 4; // 5 ADC buffers
 //AD1CON2bits.SMPI = 3; // 4 ADC buffers
AD1CON4bits.DMABL = 3; // Each buffer contains 8 words

IFS0bits.AD1IF = 0; // Clear the A/D interrupt flag bit
IEC0bits.AD1IE = 0; // Do Not Enable A/D interrupt
AD1CON1bits.ADON = 1; // Turn on the A/D converter
}
/*======================================================================================
Timer 3 is set up to time-out every 125 microseconds (8Khz Rate). As a result, the module
will stop sampling and trigger a conversion on every Timer3 time-out, i.e., Ts=125us.
=======================================================================================*/
void initTmr3()
{
TMR3 = 0x0000;
PR3 = 4999; // Trigger ADC1 every 125usec
IFS0bits.T3IF = 0; // Clear Timer 3 interrupt
IEC0bits.T3IE = 0; // Disable Timer 3 interrupt
T3CONbits.TON = 1; //Start Timer 3
}
// Linker will allocate these buffers from the bottom of DMA RAM.
struct
{
unsigned int Adc1Ch0[8];
unsigned int Adc1Ch1[8];
unsigned int Adc1Ch2[8];
unsigned int Adc1Ch3[8];
unsigned int Adc1Ch4[8];
//unsigned int Adc1Ch5[8];
} BufferA __attribute__((space(dma)));
struct
{
unsigned int Adc1Ch0[8];
unsigned int Adc1Ch1[8];
unsigned int Adc1Ch2[8];
unsigned int Adc1Ch3[8];
unsigned int Adc1Ch4[8];
//unsigned int Adc1Ch5[8];
} BufferB __attribute__((space(dma)));;
// DMA0 configuration
// Direction: Read from peripheral address 0-x300 (ADC1BUF0) and write to DMA RAM
// AMODE: Peripheral Indirect Addressing Mode
// MODE: Continuous, Ping-Pong Mode
// IRQ: ADC Interrupt

void initDma0(void)
{
DMA0CONbits.AMODE = 2; // Configure DMA for Peripheral indirect mode
DMA0CONbits.MODE = 2; // Configure DMA for Continuous Ping-Pong mode
DMA0PAD = 0x0300; // Point DMA to ADC1BUF0

DMA0CNT = 39; // 40 DMA request (4 buffers, each with 8 words)
//DMA0CNT = 31; // 32 DMA request (4 buffers, each with 8 words)

DMA0REQ = 13; // Select ADC1 as DMA Request source
DMA0STA = __builtin_dmaoffset(&BufferA);
DMA0STB = __builtin_dmaoffset(&BufferB);
IFS0bits.DMA0IF = 0; //Clear the DMA interrupt flag bit
IEC0bits.DMA0IE = 1; //Set the DMA interrupt enable bit
DMA0CONbits.CHEN=1; // Enable DMA
}
/*========================================================================================
_DMA0Interrupt(): ISR name is chosen from the device linker script.
========================================================================================*/
unsigned int DmaBuffer = 0;
void __attribute__((__interrupt__)) _DMA0Interrupt(void)
{
if(DmaBuffer == 0)
{
ProcessADCSamples(BufferA.Adc1Ch0);
ProcessADCSamples(BufferA.Adc1Ch1);
ProcessADCSamples(BufferA.Adc1Ch2);
ProcessADCSamples(BufferA.Adc1Ch3);
ProcessADCSamples(BufferA.Adc1Ch4);
}
else
{
ProcessADCSamples(BufferB.Adc1Ch0);
ProcessADCSamples(BufferB.Adc1Ch1);
ProcessADCSamples(BufferB.Adc1Ch2);
ProcessADCSamples(BufferB.Adc1Ch3);
ProcessADCSamples(BufferB.Adc1Ch4);
}
DmaBuffer ^= 1;
IFS0bits.DMA0IF = 0; //Clear the DMA0 Interrupt Flag
}
void ProcessADCSamples(unsigned int * AdcBuffer)
{unsigned int valor_1=0;

putsUART1(valor_1);
 
/* Do something with ADC Samples */
}

Desconectado Suky

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: ADC ,muestreando 10 ó mas entradas, p24hj256gp610
« Respuesta #1 en: 01 de Noviembre de 2012, 11:23:50 »
Hola! Primero que nada, 10 entradas de forma simultanea? Según recuerdo una configuración permite hasta 4 simultaneas, pero no 10.. Sino, si vas eligiendo que canal convertir, es de forma secuencial  ;-)

Luego, para comenzar, puedes no usar DMA y hacerlo de la forma "común", utilizando el CPU para saber cuando termino la conversión y guardando el valor en un registro o buffer.


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

Desconectado pablolode

  • PIC16
  • ***
  • Mensajes: 123
Re: ADC ,muestreando 10 ó mas entradas, p24hj256gp610
« Respuesta #2 en: 01 de Noviembre de 2012, 11:42:46 »
Hola ,si¡¡ claro en la primer hoja del la APP dice hasta 4 simultaneas¡¡¡
entonces deveria hacerlo en forma secuencial.
Deforma "comun" sin dma no se me ocurrio, ¿pero como??

monitoreando el bit AD1CONbits.DONE, guardando su valor y asi repitiendo sucesivamente decis??

Desconectado pablolode

  • PIC16
  • ***
  • Mensajes: 123
Re: ADC ,muestreando 10 ó mas entradas, p24hj256gp610
« Respuesta #3 en: 04 de Noviembre de 2012, 21:50:54 »
Bueno, logre mi cometido sin DMA,claro que lo podria mejorar usando DMA ,esto no es muy velos que digamos podria, agregar interupcion , cuando  pueda dominar  el DMA sigo el hilo..
este es mi codigo:

Código: [Seleccionar]
AD1CHS0bits.CH0SA = 0b0000;//selecciono AN0 a escanear
ADC_Value = Get_Sample();
valor_0 = ADC_Value ;
putsUART1( "\x1b[10;13f");// Position cursor at Line 10, Col 13
printf ("%d\r",valor_0);

AD1CHS0bits.CH0SA = 0b0001;//selecciono  AN1 a escanear, y asi hasta el infinito......
ADC_Value = Get_Sample();
valor_1 = ADC_Value ;
putsUART1( "\x1b[10;13f");// Position cursor at Line 10, Col 13
printf ("%d\r",valor_1);

.......
........


int Get_Sample(void){
      AD1CON1bits.ADON = 1;       //encernder modulo ADc
      AD1CON1bits.SAMP = 1;       // empezar a muestrear
     // espera que transcurran los 31TAD

while (!AD1CON1bits.DONE);  // loop infinito hasta q se termien a conversion   
for(i = 0; i < 1270; i++)// demora  (si no ADC1BUF0 no se actualisa con nuevo valor)
{

}
return ADC1BUF0;          //la funcion retorna el valor almacenado en ADC1BUF0
                                                                                                                                                       
 }


 

anything