• AVR Freaks

12-bit ADC with DMA channel scanning

Author
johntwenty
New Member
  • Total Posts : 4
  • Reward points : 0
  • Joined: 2009/05/26 06:21:36
  • Location: 0
  • Status: offline
2009/05/26 06:43:25 (permalink)
0

12-bit ADC with DMA channel scanning

hello,
I am using the dsPIC33FJ128GP802 and I am trying to set up the ADC in the 12-bit mode using DMA. I would like to scan sequentially 5 channels (AIN0-AIN4), thus I took the example code (example 16-4) in the 33F manual. This code there is written for 4 ADC channels (AIN0-AIN3) and so I thought I could easy do some adapatations and then it works also with 5 channels... but it does not and I have no idea why it does not wok. I am at a loss.. here is my code. Best thanks for yout help.

When I only scan 4 channels (AIN0-AIN3) it works fine. When I scan 4 channels that are not one to another, for example AIN0, AIN2-AIN4 then it does not work. It also does not work when I scan all five channels. I output the ADC values on the screen and it seems that something is shifted but I have no idea why it should be shifted. thanks.


#include "p33FJ128GP802.h"
#include "adc12BitMode.h"
#include "gyroscope.h"
#include "led.h"

// Linker will allocate these buffers from the bottom of DMA RAM.
struct
{
unsigned int Adc1Ch0[4];
unsigned int Adc1Ch1[4];
unsigned int Adc1Ch2[4];
unsigned int Adc1Ch3[4];
unsigned int Adc1Ch4[4];
} BufferA __attribute__((space(dma)));

struct
{
unsigned int Adc1Ch0[4];
unsigned int Adc1Ch1[4];
unsigned int Adc1Ch2[4];
unsigned int Adc1Ch3[4];
unsigned int Adc1Ch4[4];
} BufferB __attribute__((space(dma)));

/*========================================================================================
_DMA0Interrupt(): ISR name is chosen from the device linker script.
========================================================================================*/
unsigned int DmaBuffer = 0;
void __attribute__((__interrupt__)) _DMA0Interrupt(void)
{
if(DmaBuffer == 0){
gyro.xMsb = (unsigned char)(BufferA.Adc1Ch0[0] >> 8);
gyro.xLsb = (unsigned char)(BufferA.Adc1Ch0[0] & 0xFF);
gyro.yMsb = (unsigned char)(BufferA.Adc1Ch1[0] >> 8);
gyro.yLsb = (unsigned char)(BufferA.Adc1Ch1[0] & 0xFF);
gyro.vrefMsb = (unsigned char)(BufferA.Adc1Ch2[0] >> 8);
gyro.vrefLsb = (unsigned char)(BufferA.Adc1Ch2[0] & 0xFF);
gyro.temperatureMsb = (unsigned char)(BufferA.Adc1Ch3[0] >> 8);
gyro.temperatureLsb = (unsigned char)(BufferA.Adc1Ch3[0] & 0xFF);
gyro.zMsb = (unsigned char)(BufferA.Adc1Ch4[0] >> 8);
gyro.zLsb = (unsigned char)(BufferA.Adc1Ch4[0] & 0xFF);

}
else
{
gyro.xMsb = (unsigned char)(BufferB.Adc1Ch0[0] >> 8);
gyro.xLsb = (unsigned char)(BufferB.Adc1Ch0[0] & 0xFF);
gyro.yMsb = (unsigned char)(BufferB.Adc1Ch1[0] >> 8);
gyro.yLsb = (unsigned char)(BufferB.Adc1Ch1[0] & 0xFF);
gyro.vrefMsb = (unsigned char)(BufferB.Adc1Ch2[0] >> 8);
gyro.vrefLsb = (unsigned char)(BufferB.Adc1Ch2[0] & 0xFF);
gyro.temperatureMsb = (unsigned char)(BufferB.Adc1Ch3[0] >> 8);
gyro.temperatureLsb = (unsigned char)(BufferB.Adc1Ch3[0] & 0xFF);
gyro.zMsb = (unsigned char)(BufferB.Adc1Ch4[0] >> 8);
gyro.zLsb = (unsigned char)(BufferB.Adc1Ch4[0] & 0xFF);
}

DmaBuffer ^= 1;
IFS0bits.DMA0IF = 0; //Clear the DMA0 Interrupt Flag
}


/*==========================================================================================
ADC Initialization for Channel Scan
===========================================================================================*/
void adcInit(void){

ADPCFG = 0b1111111111100000; // AN0-AN4 configured as analog input

AD1CON1bits.FORM0 = 0; // Data Output Format: Signed Fraction (Q15 format)
AD1CON1bits.FORM1 = 0;
AD1CON1bits.SSRC = 2; // Sample Clock Source: GP Timer starts conversion
AD1CON1bits.ASAM = 1; // ADC Sample Control: Sampling begins immediately after conversion
AD1CON1bits.AD12B = 1; // 12-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
//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
//AD1CSSL: A/D Input Scan Selection Register
AD1CSSL = 0x001F; // Scan AIN0, AIN1, AIN2, AIN3, AIN4 inputs
AD1CON1bits.ADDMABM = 0; // DMA buffers are built in scatter/gather mode
AD1CON2bits.SMPI = 4; // 5 ADC buffers
AD1CON4bits.DMABL = 2; // Each buffer contains 4 words
IFS0bits.AD1IF = 0; // Clear the A/D interrupt flag bit
IEC0bits.AD1IE = 0; // Do Not Enable A/D interrupt

initDma0();
AD1CON1bits.ADON = 1; // Turn on the A/D converter
initTmr3();
}
/*======================================================================================
Timer 3 is setup 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(void)
{
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
}

// 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 = (volatile unsigned int) &ADC1BUF0; // Point DMA to ADC1BUF0
DMA0CNT = 19; // 20 DMA request (5 buffers, each with 4 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
}

post edited by johntwenty - 2009/05/26 06:46:28
#1

7 Replies Related Threads

    deantomlinson
    New Member
    • Total Posts : 22
    • Reward points : 0
    • Joined: 2008/01/25 14:38:43
    • Location: 0
    • Status: offline
    RE: 12-bit ADC with DMA channel scanning 2009/05/26 06:57:52 (permalink)
    0
    The ADC of the dsPIC33 has only 4 channels(CH0-CH3) of used in the 10-bit mode and just sample/hold channel if used in the 12-bit mode.  CH0 can be used to scan through all five of the inputs that you have.
    #2
    johntwenty
    New Member
    • Total Posts : 4
    • Reward points : 0
    • Joined: 2009/05/26 06:21:36
    • Location: 0
    • Status: offline
    RE: 12-bit ADC with DMA channel scanning 2009/05/26 07:03:39 (permalink)
    0
    yes I know, but scanning through all 5 inputs in the 12-bit mode is exactly this what I do! Have a look at the code!
    #3
    johntwenty
    New Member
    • Total Posts : 4
    • Reward points : 0
    • Joined: 2009/05/26 06:21:36
    • Location: 0
    • Status: offline
    RE: 12-bit ADC with DMA channel scanning 2009/05/27 06:12:27 (permalink)
    0
    ok, when nobody can help me here in this forum, maybe somebody knows where I can get help? Any other forums that are more frequently visited?
    #4
    Neiwiertz
    Super Member
    • Total Posts : 2094
    • Reward points : 0
    • Joined: 2004/09/01 02:58:52
    • Status: offline
    RE: 12-bit ADC with DMA channel scanning 2009/05/27 13:38:10 (permalink)
    0
    Give it a look here E16 Bunch of links: ADC maybe you find something about this, additional give it a look at Microchip reference manual(s), Futhermore let know here, or maybe Microchip's code example to check.

    Flying With --|Explorer 16|HardWare|SoftWare|-- Fav(s) Gallery Lists
    #5
    Mike017
    Super Member
    • Total Posts : 2698
    • Reward points : 0
    • Joined: 2007/08/25 08:11:31
    • Location: Lincoln, RI, USA
    • Status: offline
    RE: 12-bit ADC with DMA channel scanning 2009/05/27 17:39:32 (permalink)
    0
    Hi,

    When I only scan 4 channels (AIN0-AIN3) it works fine.
    I'm not sure if you mean it works AND is accurate but the example uses...  
    AD1CON3bits.ADCS = 63; // ADC Conversion Clock
    ... asking for a 10 bit result and does not state the clock Fcy. You're looking for a 12 bit result (more TADs) and may have a different Fcy.

    Also, taking this setting.....
    AD1CON1bits.FORM0 = 0; // Data Output Format: Signed Fraction (Q15 format)
    .....in combination with bit shifting in the gyro ISR function (not in the example), it may not produce a correct result unless you're handling it somewhere else in code . Check  DS70183A-page 16-51 for assorted equivalent result codes. Maybe signed integer better suits your shift code.

    Good Luck,
    Mike
    post edited by Mike017 - 2009/05/27 17:40:38
    #6
    johntwenty
    New Member
    • Total Posts : 4
    • Reward points : 0
    • Joined: 2009/05/26 06:21:36
    • Location: 0
    • Status: offline
    RE: 12-bit ADC with DMA channel scanning 2009/05/28 02:22:29 (permalink)
    0
    SOLUTION:

    AMODE = 0;

    I don't know why, but it works like this. Can somebody explain me why?
    #7
    Abutaha
    New Member
    • Total Posts : 18
    • Reward points : 0
    • Joined: 2009/03/10 05:29:29
    • Location: 0
    • Status: offline
    RE: 12-bit ADC with DMA channel scanning 2009/10/20 01:25:32 (permalink)
    0
    Hi johntwenty
    I am facing the same problem ..
    But i think it is a bit difrence ... How?
    I think i couldn't manage to read the data from the right buffer ..
    can you help me to sort this?
    many thanks
     
    #8
    Jump to:
    © 2019 APG vNext Commercial Version 4.5