ADC para DsPIF30F6013A

Buenas,

Estoy diseñando un circuito, quiero entrar por el puerto AN3 una señal analógica y hacer la FFT de esta. Tengo dudas con la configuración del ADC.

Mi ADCInit () es el siguiente:

void ADCInit (){
// 1 Configure the A/D Module

ADPCFG = 0xFFF7; //
ADCON1bits.ASAM = 1; // Sampling begins immediately after last conversion completes. SAMP bit is auto set.
ADCON1bits.SSRC = 7; // 7=111 Internal counter ends sampling and starts conversion
ADCON1bits.FORM = 2; // 11 Signal fractional, 10 Fractional, 01 Signed integer, 00 Integer

ADCON2bits.SMPI = 15; // Interrupció després de 16 mostres en el buffer

ADCON3bits.ADCS=63;// Tad = Tcy*(ADCS+1)/2 = 50ns*(63+1)/2 = 1.6usec Sample time = 15Tad, Tad = internal Tcy/2

//Registre ADCHS
ADCHS = 0x0003; // Connecta RB3/AN3 al canal CH0 d'entrada

ADCSSL = 0 ; //Ja ho controlo amb el CH0SA

ADPCFG = 0xFFF7, // 1111 1111 1111 1011 //Configuro tot el port com digital i AN3 com analògic

//Clear the A/D interrupt flag bit
IFS0bits.ADIF = 0; //

//Set the A/D interrupt enable bit
IEC0bits.ADIE = 1;
ADCON1bits.ADON = 1; //Turn on the A/D converter //This is typically done after configuring other registers// A/D converter module is operating
// T3CON = 0x8010;
}



Y en la interrupción tengo esto:

void __attribute__ ((__interrupt__, no_auto_psv)) _ADCInterrupt(void)
{
/* AD Conversion complete interrupt handler */
IFS0bits.ADIF = 0; /* Clear ADC Interrupt Flag*/
ADResult3 = ADCBUF3; /* Get the conversion result.*/
flagDada = 1;
LED = ~LED;

}


Porqué el LED me baila siempre si no le entro ninguna señal en la entrada?

Yo quiero ponerle una sinusoidal en la entrada de AN3 y que cuando detecte señal salte la interrupción (baile el LED) y me haga la conversión a digital. Si no meto ninguna señal a AN3 porqué entra a la interrupción?

Qué estoy configurando mal?

Gracias,



He pensado que igual tengo configurado el ADC para que me lea todo el rato, lo que hago ahora es que a partir un umbral le hago caso o no a los datos adquiridos.

Ahora toca pelearme con la FFT...
 
Última edición:
Buenas,

Parece que voy progresando. Cuelgo el codigo del TadADC.c que parece que funciona (a parte de guardar los datos en sigCmpx, los mando por la UART y parece que muestra numeros en forma de sinusoidal (los valores suben y bajan):

Código:
void __attribute__ ((__interrupt__, no_auto_psv)) _ADCInterrupt(void)
{
	//AD Conversion complete interrupt handler 
	IFS0bits.ADIF = 0; // Clear ADC Interrupt Flag
	ADResult_3 = ADCBUF3; // Get the conversion result. Només vull del canal 0, sortida 3. No sé quin està bé, si aquest o el de dalt.
	if(m<FFT_BLOCK_LENGTH){ //si encara no he agafat tots els punts
		//guardo
		sigCmpx[m].real = ADResult_3;
	//	sprintf(Txt, "\r\n sigCmpx: %d  \r\n",sigCmpx[m].real );
	//	putsUART1((unsigned int *)Txt);
		m++;	
	}
	if(m==FFT_BLOCK_LENGTH){		//ja he omplert tot el sigComx
		flagDada = 1; //ja puc fer la FFT
	}
}

void ADCInit (){
 // 1 Configure the A/D Module
 
	ADPCFG = 0xFFF7; // primer poso tots els canals a 1 excepte el 3, Digital mode 1111 1111 1111 0111 // v
	ADCON1bits.ASAM = 1; // Sampling begins immediately after last conversion completes. SAMP bit is auto set.
	ADCON1bits.SSRC = 7; // 7=111 Internal counter ends sampling and starts conversion 2=010 General purpose Timer3 compare ends sampling and starts conversion //Timer 3 estableix el temps de mostreig
	ADCON1bits.FORM = 2; // 11 Signal fractional, 10 Fractional, 01 Signed integer, 00 Integer

	ADCON2bits.SMPI = 15; // Interrupció després de 16 mostres en el buffer

	ADCON3bits.ADCS=63;// Tad = Tcy*(ADCS+1)/2 = 50ns*(63+1)/2 = 1.6usec Sample time = 15Tad, Tad = internal Tcy/2
	//ADCON3bits.SAMC = 15; // això no ho tinc declarat
	ADCHS = 0x0003; // Connecta RB3/AN3 al canal CH0 d'entrada

	ADCSSL = 0 ; //Ja ho controlo amb el CH0SA

	ADPCFG = 0xFFF7, // 1111 1111 1111 1011 //Configuro tot el port com  digital i AN3 com analògic
	    //Clear the A/D interrupt flag bit
    IFS0bits.ADIF = 0; //

    //Set the A/D interrupt enable bit
    IEC0bits.ADIE = 1;       
    ADCON1bits.ADON = 1;  //Turn on the A/D converter //This is typically done after configuring other registers//  A/D converter module is operating

	flagDada = 0;
}

Cuando el flagDada vale 1, que representa que ya tengo el buffer lleno, y quiero que haga la FFT, llamo la función de la FFT, envio por la UART el resultado de peakFrequency y no corresponde a la frequencia que le entro desde el osciscopio, sino que siempre da el mismo valor (aunque varie la frequencia del señal de entrada).

Cuelgo la función de la FFT que es tal cual Microchip la pone de ejemplo:

Código:
void FFTRunning (){
//	printf ("estic dins fftrunning \n");
	int i = 0;
		fractional *p_real = &sigCmpx[0].real ;
		fractcomplex *p_cmpx = &sigCmpx[0] ;

	#ifndef FFTTWIDCOEFFS_IN_PROGMEM					// Generate TwiddleFactor Coefficients 
		TwidFactorInit (LOG2_BLOCK_LENGTH, &twiddleFactors[0], 0);	// We need to do this only once at start-up 
	#endif
	
		for ( i = 0; i < FFT_BLOCK_LENGTH; i++ )// The FFT function requires input data 
		{					// to be in the fractional fixed-point range [-0.5, +0.5]
			*p_real = *p_real >>1 ;		// So, we shift all data samples by 1 bit to the right. 
			*p_real++;			// Should you desire to optimize this process, perform 
		}					// data scaling when first obtaining the time samples 
							// Or within the BitReverseComplex function source code 
	
		p_real = &sigCmpx[(FFT_BLOCK_LENGTH/2)-1].real ;	// Set up pointers to convert real array 
		p_cmpx = &sigCmpx[FFT_BLOCK_LENGTH-1] ; // to a complex array. The input array initially has all 
							// the real input samples followed by a series of zeros 
	
	
		for ( i = FFT_BLOCK_LENGTH; i > 0; i-- ) // Convert the Real input sample array 
		{					// to a Complex input sample array  
			(*p_cmpx).real = (*p_real--);	// We will simpy zero out the imaginary  
			(*p_cmpx--).imag = 0x0000;	// part of each data sample 
		}
	
		// Perform FFT operation 
	#ifndef FFTTWIDCOEFFS_IN_PROGMEM
		FFTComplexIP (LOG2_BLOCK_LENGTH, &sigCmpx[0], &twiddleFactors[0], COEFFS_IN_DATA);
	#else
		FFTComplexIP (LOG2_BLOCK_LENGTH, &sigCmpx[0], (fractcomplex *) __builtin_psvoffset(&twiddleFactors[0]), (int) __builtin_psvpage(&twiddleFactors[0]));
	#endif
	
		// Store output samples in bit-reversed order of their addresses 
		BitReverseComplex (LOG2_BLOCK_LENGTH, &sigCmpx[0]);
	
		// Compute the square magnitude of the complex FFT output array so we have a Real output vetor 
		SquareMagnitudeCplx(FFT_BLOCK_LENGTH, &sigCmpx[0], &sigCmpx[0].real);
	
		// Find the frequency Bin ( = index into the sigCmpx[] array) that has the largest energy
		// i.e., the largest spectral component 
		VectorMax(FFT_BLOCK_LENGTH/2, &sigCmpx[0].real, &peakFrequencyBin);
	
		// Compute the frequency (in Hz) of the largest spectral component 
		peakFrequency = peakFrequencyBin*(SAMPLING_RATE/FFT_BLOCK_LENGTH);
		sprintf(uText, "\r\n Frequencia pic: %ld \r\n",peakFrequency);
		putsUART1((unsigned int *)uText);
}

Si que es verdad que no tengo mucho en cuenta los valores de entrada (esto que tiene que ser -0.5 a 0.5), ni como tengo que controlar el Samplerate, etc. Porqué no sé qué tengo que buscar.
Alguien sabe como tengo que relacionar estos valores?

Muchas gracias de antemano,
 
Atrás
Arriba