Hi!
I am using dsPIC Starter Kit which has a dsPIC33fj256gp506. I am trying to modify the ADC sampling rate using the example from Microchip.
Here is the code:
I want to set it to 60kHz. I set ADC_FSAMP = 60000, and calculate ADCS.Code:#ifndef __ADCCHANNELDRV_H__ #define __ADCCHANNELDRV_H__ #define ADC_CHANNEL_FCY 40000000 #define ADC_FSAMP 8000 /* Sampling Frequency */ #define ADC_BUFFER_SIZE 128 /* This is the size of each buffer */ #define ADC_CHANNEL_DMA_BUFSIZE (ADC_BUFFER_SIZE*2) #include "..\h\p33FJ256GP506.h" typedef struct sADCChannelHandle { int * buffer1; int * buffer2; volatile int bufferIndicator; volatile int isReadBusy; }ADCChannelHandle; void ADCChannelInit (ADCChannelHandle * pHandle,int * pBufferInDMA); void ADCChannelStart (ADCChannelHandle * pHandle); void ADCChannelRead (ADCChannelHandle * pHandle,int *buffer,int size); int ADCChannelIsBusy (ADCChannelHandle * pHandle); void ADCChannelStop (ADCChannelHandle * pHandle); #define ADCON1VAL 0x0744 /* 12 bit ADC with signed fractional format * Triggered by Timer 3 and auto start * sampling after conversion complete. */ #define ADCON2VAL 0x0000 /* AVdd and AVss voltage reference, * use channel 0 with no scan */ #define ADCON3VAL 0x0010 /* Tad is 16 Tcy */ #define ADCHSVAL 0x0000 /* AN0 input on channel 0 */ #define ADPCFGVAL 0xFFFE /* AN0 input is Analog */ #define ADCSSLVAL 0x0000 /* No channel scanning */ #endif #include "..\h\ADCChannelDrv.h" static ADCChannelHandle * thisADCChannel; void ADCChannelInit (ADCChannelHandle * pHandle,int * pBufferInDMA) { /* This function will intialize the DMA */ /* DMA0 is used to read from the ADC */ thisADCChannel = pHandle; pHandle->buffer1 = pBufferInDMA; /* Assign the ping pong buffers for the ADC DMA*/ pHandle->buffer2 = (int *)((int)pBufferInDMA + ADC_BUFFER_SIZE); DMA0CONbits.SIZE = 0; /* Word transfers */ DMA0CONbits.DIR = 0; /* From ADC1BUF to DMA */ DMA0CONbits.HALF = 0; /* Interrupt when all the data has been moved */ DMA0CONbits.NULLW = 0; /* No NULL writes - Normal Operation */ DMA0CONbits.AMODE = 0; /* Register Indirect with post-increment mode */ DMA0CONbits.MODE = 2; /* Continuous ping pong mode enabled */ DMA0REQbits.FORCE = 0; /* Automatic transfer */ DMA0REQbits.IRQSEL = 0xD; /* ADC conversion complete */ DMA0STA = (int)(pHandle->buffer1) - (int)&_DMA_BASE; DMA0STB = (int)(pHandle->buffer2) - (int)&_DMA_BASE; DMA0PAD = (int )&ADC1BUF0; DMA0CNT = ADC_BUFFER_SIZE - 1; AD1CON1 = ADCON1VAL; /* Load the ADC registers with value */ AD1CON2 = ADCON2VAL; /* specified in 12bitADCDriver.h */ AD1CON3 = ADCON3VAL; AD1CHS0 = ADCHSVAL; AD1PCFGLbits.PCFG0 = 0; AD1CSSL = ADCSSLVAL; TMR3 = 0; PR3 = (ADC_CHANNEL_FCY/ADC_FSAMP) - 1; } void ADCChannelStart (ADCChannelHandle * pHandle) { pHandle->bufferIndicator = 0; pHandle->isReadBusy = 1; _DMA0IF = 0; _DMA0IE = 1; DMA0CONbits.CHEN = 1; /* Enable the DMA Channel */ AD1CON1bits.ADON = 1; /* Enable ADC module */ T3CONbits.TON = 1; /* Enable Timer 3 */ } void ADCChannelStop(ADCChannelHandle * pHandle) { _DMA0IE = 0; /* Disable the DMA interrupt */ DMA0CONbits.CHEN = 0; /* Disable the DMA Channel */ AD1CON1bits.ADON = 0; /* Disable ADC module */ T3CONbits.TON = 0; /* Disable Timer 3 */ } void ADCChannelRead (ADCChannelHandle * pHandle,int *data,int size) { int *source; int i; /* if the buffer indicator bit is 1, then use buffer 1 else use buffer2 */ /* Since the DMA ping pongs between these buffer, you must know */ /* which one to read. The bufferIndicators keep track of this */ source = (pHandle->bufferIndicator) ? pHandle->buffer1 : pHandle->buffer2; if (size > ADC_BUFFER_SIZE) size = ADC_BUFFER_SIZE; for(i = 0;i < size;i++) { data[i] = source[i]; } __asm__ volatile("disi #0x4"); /* disable interrupts */ pHandle->isReadBusy = 1; __asm__ volatile("disi #0x0"); /* enable interrupts */ } int ADCChannelIsBusy (ADCChannelHandle * pHandle) { return(pHandle->isReadBusy); } void __attribute__((__interrupt__,no_auto_psv)) _DMA0Interrupt(void) { _DMA0IF = 0; thisADCChannel->bufferIndicator ^= 1; /* Flip the indicator bit */ thisADCChannel->isReadBusy = 0; /* New frame is available */ }
Tcy = 25ns (@40MHz)
Tc = 1/60000 = 16.66us = 16666ns (aprox.)
Tad = Tc/14 = 1190ns (aprox.)
ADC Conversion Clock: Tad=Tcy*(ADCS+1) => ADCS = (Tad/Tcy) - 1 = 46,61 = 47 (aprox.).
I set ADCS = 47, so I write:
To test if the ADC is working correctly, I generate a 10kHz signal for the board using my PC sound card (using Visual Analyser 2011). But the ADC won't finish sampling (I use a LED to signal when 128 samples have been acquired - when finished, the LED switches off). Also, if I generate a DC signal, the ADC won't finish sampling. More interesting is the fact that when I generate a 1kHz signal, the ADC works fine!! I used debug to view the samples, exported the values in a file and plotted them in Matlab.Please help in solving this problem. I really need to get this ADC running for a project I am working on.Code:#define ADCON3VAL 0x002F




Bookmarks