ritchie888
Newbie level 4
I'm trying to sample from 8 channels using my dspic33fj128gp802 chip. I've had four channels working fine up until now, but trying to use the alternative MUX switch isn't going to plan.
I've tried to change the settings so that the DMA interrupt is polled after each second sample/conversion, in a hope that I can fill an eight word DMA buffer four words at a time, i.e. four words from SampleA (CH0 - AN9, CH123 - AN0,1,2), then four words from SampleB (CH0 - AN10, CH123 - AN3,4,5), then DMA interrupt poll for me to process the data.
My settings are below:
Timer 3 is set up to poll at 8kHz, DMA is set up:
with:
Now this code works to an extent, I do get a response from each of the eight inputs, however for the CH123 inputs I'm getting cross talk. For example if all the lines are at 0V and I put a 3.3V signal to CH1 for SampleA (AN0) I will also get a response on CH1 for SampleB (AN3). It won't be exactly 3.3V but will be around 2.5V or something which it shouldn't. This also happens on the CH0 (SampleA+B) but to a much lesser extent.
What am I missing?
I've tried to change the settings so that the DMA interrupt is polled after each second sample/conversion, in a hope that I can fill an eight word DMA buffer four words at a time, i.e. four words from SampleA (CH0 - AN9, CH123 - AN0,1,2), then four words from SampleB (CH0 - AN10, CH123 - AN3,4,5), then DMA interrupt poll for me to process the data.
My settings are below:
Code:
AD1CON1 = 0; // Set everything to zero to start with.
AD1CON1bits.ADON = 0; // Turn ADC off.
AD1CON1bits.ADSIDL = 1; // Stop module operation in idle mode.
AD1CON1bits.ADDMABM = 1; // DMA buffers are written in the order of conversion.
AD1CON1bits.AD12B = 0; // Set to 10bit mode.
AD1CON1bits.FORM = 3; // Set data output to signed fractional.
AD1CON1bits.SSRC = 2; // use timer3
AD1CON1bits.SIMSAM = 1; // Collect samples from channels 0, 1, 2, 3 simultaneously.
AD1CON1bits.ASAM = 1; // Sampling begins when SAMP bit is set
AD1CON2 = 0; // Set everything to zero to start with.
AD1CON2bits.VCFG = 0; // Converter voltage ref. set to AVdd and AVss.
AD1CON2bits.CSCNA = 0; // Input scan select bit. set to do not scan.
AD1CON2bits.CHPS = 2; // Converts CH0, CH1, CH2, and CH3
AD1CON2bits.BUFS = 0; // Buffer fill status (invalid as BUFM is 0);
AD1CON2bits.SMPI = 1; // ADC interrupt is generated after every second sample/conversion.
AD1CON2bits.BUFM = 0; // Buffer fill mode. set to always start filling from start address.
AD1CON2bits.ALTS = 1; // Alternate input sample mode. set to flip between sample A on first sample and sample B on next sample.
AD1CON3 = 0; // Set everything to zero to start with.
AD1CON3bits.ADRC = 0; // ADC conversion clock derived from system clock.
AD1CON3bits.SAMC = 0; // Auto sample time bits, TAD, set to 0.
AD1CON3bits.ADCS = 4; // ADC conversion clock set to 2. 3 * TCY = TAD.
AD1CON4 = 0; // set everything to zero to start with.
AD1CON4bits.DMABL = 0; // allocates 1 word of buffer to each analogue input.
AD1CHS123 = 0; // everything set to zero to start with.
AD1CHS123bits.CH123NB = 0; // channel 1,2,3 negative input set to VREFL. sample B.
AD1CHS123bits.CH123SB = 1; // channel 1,2,3 positive input set to AN3, AN4, AN5, respectively. Sample B.
AD1CHS123bits.CH123NA = 0; // channel 1,2,3 negative input set to VREFL. sample A.
AD1CHS123bits.CH123SA = 0; // channel 1,2,3 positive input set to AN0, AN1, AN2, respectively. sample A.
AD1CHS0 = 0; // set everything to zero to start with.
AD1CHS0bits.CH0NB = 0; // channel 0 negative input, set by CH0NA. sample B.
AD1CHS0bits.CH0SB = 10; // chanel 0 positive input, AN10 (RB14). sample B.
AD1CHS0bits.CH0NA = 0; // chanel 0 negative input, for sample A. set to VREFL.
AD1CHS0bits.CH0SA = 9; // channel 0 positive input, AN9 (RB15). sample A.
AD1CSSL = 0; // input scan register set to zero as not using it.
AD1PCFGLbits.PCFG0 = 0; // AN0/RA0 set to analogue.
AD1PCFGLbits.PCFG1 = 0; // AN1/RA1 set to analogue.
AD1PCFGLbits.PCFG2 = 0; // AN2/RB0 set to analogue.
AD1PCFGLbits.PCFG3 = 0; // AN3/RB1 set to analogue.
AD1PCFGLbits.PCFG4 = 0; // AN4/RB2 set to analogue.
AD1PCFGLbits.PCFG5 = 0; // AN5/RB3 set to analogue.
AD1PCFGLbits.PCFG9 = 0; // AN9/RB15 set to analogue.
AD1PCFGLbits.PCFG10 = 0; // AN10/RB14 set to analogue.
Timer 3 is set up to poll at 8kHz, DMA is set up:
Code:
DMA0CONbits.AMODE = 0; // Configure DMA for Register indirect with post increment
DMA0CONbits.MODE = 2; // Configure DMA for Continuous Ping-Pong mode
DMA0PAD = (int) &ADC1BUF0; // receive ADC data from ADC buffer
DMA0CNT = (8 - 1); // DMA channel transfer count register
DMA0REQ = 13; // ADC mode
DMA0STA = __builtin_dmaoffset(ADCBufferA); // DMA channel start address reg A
DMA0STB = __builtin_dmaoffset(ADCBufferB); // DMA channel start address reg A
IFS0bits.DMA0IF = 0; // Clear the DMA interrupt flag bit
IEC0bits.DMA0IE = 1; // Set the DMA interrupt enable bit
DMA0CONbits.CHEN = 1; // start DMA
with:
Code:
int ADCBufferA[8] __attribute__((space(dma)));
int ADCBufferB[8] __attribute__((space(dma)));
Now this code works to an extent, I do get a response from each of the eight inputs, however for the CH123 inputs I'm getting cross talk. For example if all the lines are at 0V and I put a 3.3V signal to CH1 for SampleA (AN0) I will also get a response on CH1 for SampleB (AN3). It won't be exactly 3.3V but will be around 2.5V or something which it shouldn't. This also happens on the CH0 (SampleA+B) but to a much lesser extent.
What am I missing?