This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

ADC help



I have written the following code. Can someone point out how to use the ADC to automatically load all the samples into the array "reg" and why isn't the adc interrupt firing?

#include <msp430.h>

const int period = 200;
const int dutyCycleScaler = 4;

unsigned int reg[10];
unsigned int avg=0;
unsigned char state = 0; //used as boolean (false = 0, true = 1)
unsigned char change = 0; //used as boolean
unsigned char i = 0;
unsigned char adcFlag = 0;

int getAverage(){ //calculates average of current adc values
int runningAverage = 0;
for(i = 0; i < 10; i++){
runningAverage = (runningAverage + reg[i])/2;
}
return runningAverage;
}

int main(void) {
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
BCSCTL1 = CALBC1_8MHZ;
DCOCTL = CALDCO_8MHZ;


//port settings
P1DIR |= BIT0;

//ADC setup
ADC10CTL0 |= ADC10SHT_2 + ADC10IE + ADC10ON;
ADC10CTL1 |= INCH_2 + ADC10DIV_7 + CONSEQ_2 + SHS_2;
ADC10DTC1 = 10;

//PWM timer settings
//TA0CCR0 = period; //period (clock ticks)
//TA0CCR1 = period/dutyCycleScaler; //25% PWM (duty cycle)
//TA0CCTL1 = OUTMOD_7; //up-down mode
//TA0CTL = TASSEL_2 + MC_1; //select master clock

//ADC Timer Settings
CCTL0 = OUTMOD_4; // CCR0toggle mode
CCR0 = 3000;
TACTL = TASSEL_2 + MC_3; // SMCLK, up-downmode


while(1){
//Run ADC
P1OUT |= 0x01;
ADC10CTL0 &= ~ENC;
while (ADC10CTL1 & BUSY); // Wait if ADC10 core is active
ADC10SA = 0x200; // Data buffer start
ADC10CTL0 |= ENC; // Sampling and conversion ready
reg[i] = ADC10MEM;
P1OUT &= ~0x01;

__bis_SR_register(GIE); //enable interrupts


if(adcFlag == 1){

avg=getAverage();

}
}
}
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR(void)
{
adcFlag = 1; //set adc
__bic_SR_register_on_exit(LPM0_bits); // Clear LPM3 bits from 0(SR)
}

#pragma vector = TIMER0_A0_VECTOR
__interrupt void TIMER0_A0_ISR(void){

__bic_SR_register_on_exit(LPM0_bits);
}

  • Stuart Miller said:
    how to use the ADC to automatically load all the samples into the array "reg"

    By giving the DTC the address of your data array:
    ADC10SA = 0x200; // Data buffer start
    ADC10SA = (unsigned int)reg;

    Stuart Miller said:
    why isn't the adc interrupt firing?

    because once the DTC is active, the ADC10IFG bit is set when teh DTC is done with the specified number of transfers, not when a signel transfer is done.
    Since you only launch one sequence from INCH2 to INCH0, the ADC will only do 3 conversions and the DTC is waiting for 7 more which never come, before calling the ISR.

  • That doesn't seem to work either. It looks like it is taking the right number of samples, but writing all of them to the same address in memory: reg[0].

    Also, I am not sampling through multiple channels. It should be sampling the same channel repeatedly.

  • Stuart Miller said:
    Also, I am not sampling through multiple channels. It should be sampling the same channel repeatedly.

    You're right, it's CONSEQ_2 not OCNSEC_3. Yes. same channel.

    You didn't write which MSP you're using, but from the BCSCTL register usage I assume it is a 2x family device.

    Your code has some more faults. I was fooled by the apparently wrong target address for the DTC and didn't dig deeper. However, I wasn't completely wrong with why the interrupt isn't firing.

    2nd try...

    You do not set the ADC for multiple sample and conversion (MSC bit) . So it requires a separate trigger for each individual sample.
    You only trigger once per while loop.
    You write a new destination address to the DTC on each loop, which will restart the DTC.
    When the DTC is active, the interrupt will only be triggered after the DTC has done the programmed number of transfers. Which never happens because you reset the DTC after each transfer.

    It makes no sense to use the DTC for auto-transferring your results when you at the same time manually move the results. In your ase, you are mixing up two different methods of reading the ADC, and the two interfere with each other.

**Attention** This is a public forum