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:

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 */ 
}
I want to set it to 60kHz. I set ADC_FSAMP = 60000, and calculate ADCS.

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:

Code:
#define ADCON3VAL 0x002F
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.