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.

exp-msp430FR5739 accelerometer issue with dma

Hi, everyone!

I have a nice board exp-msp430FR5739 where I have a deal with analog accelerometer adxl330. I want to read 3 values from axis (A12, A13, A14 channels) through the DMA-unit. I based my code on the TI example. And my issue is incorrect values which I'm getting during measurements, because they are random and don't depends from accelerometer movements.  I think I must to turn off temp sensor, LoBatt sensor and Vref channels. But how? That's my code: 

#include "io430.h"

unsigned char ADC_Result[3];                // 8-bit ADC conversion result array

int main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
  
  ADC10CTL0 &= ~ADC10ENC;
  // Configure ADC pins  
  P3DIR &= ~(BIT0 + BIT1 + BIT2);
  P3SEL0 |= BIT0 + BIT1 + BIT2;
  P3SEL1 |= BIT0 + BIT1 + BIT2;
  // Configure ADC10
  ADC10CTL0 = ADC10SHT_2 + ADC10MSC + ADC10ON;// 16ADCclks, MSC, ADC ON
  ADC10CTL1 = ADC10SHP + ADC10CONSEQ_1;     // sampling timer, s/w trig.,single sequence
  ADC10CTL2 &= ~ADC10RES;                   // 8-bit resolution
  ADC10MCTL0 = ADC10INCH_14;                 // A12,A13,A14, AVCC reference
  
  // Configure DMA0 (ADC10IFG trigger)
  DMACTL0 = DMA0TSEL__ADC10IFG;             // ADC10IFG trigger
  __data16_write_addr((unsigned short) &DMA0SA,(unsigned long) &ADC10MEM0);
                                            // Source single address  
  __data16_write_addr((unsigned short) &DMA0DA,(unsigned long) &ADC_Result[0]);
                                            // Destination array address  
  DMA0SZ = 0x03;                            // 3 conversions 
  DMA0CTL = DMADT_4 + DMADSTINCR_3 + DMASRCBYTE + DMADSTBYTE + DMAEN + DMAIE; 
                                            // Rpt, inc dest, byte access, 
                                            // enable int after seq of convs   
  while(1)
  {
    
    while (ADC10CTL1 & BUSY);               // Wait if ADC10 core is active
    ADC10CTL0 |= ADC10ENC + ADC10SC;        // Sampling and conversion start
    __bis_SR_register(CPUOFF + GIE);        // LPM0, ADC10_ISR will force exit
    __delay_cycles(25000);                   // Delay between sequence convs    
    __no_operation();                       // BREAKPOINT; check ADC_Result
  }
}

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=DMA_VECTOR
__interrupt void DMA0_ISR (void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(DMA_VECTOR))) DMA0_ISR (void)
#else
#error Compiler not supported!
#endif
{
  switch(__even_in_range(DMAIV,16))
  {
    case  0: break;                          // No interrupt
    case  2: 
      // sequence of conversions complete
      __bic_SR_register_on_exit(CPUOFF);     // exit LPM
      break;                                 // DMA0IFG
    case  4: break;                          // DMA1IFG
    case  6: break;                          // DMA2IFG
    case  8: break;                          // Reserved
    case 10: break;                          // Reserved
    case 12: break;                          // Reserved
    case 14: break;                          // Reserved
    case 16: break;                          // Reserved
    default: break; 
  }   
}

I tied Vcc pin of adxl330 with Vcc of board and I think that hard part is ok. I can see correct values and their changes trough an oscilloscope. 

I'll appreciate any help! Thanks!

  • Hi Kirill,

    It appears to me that you have properly altered the demo code for your application. The ADC12-14 pins (P3.0-P3.2) have been configured correctly and the input channel select was changed such that sequence of channel mode will begin with ADC14 and decrements down past ADC12. The DMA has been left alone so that the first 3 conversions(ADC14, ADC13, ADC12) are stored in ADC_Result[0-2] and creates an interrupt to exit LPM after the conversions are complete.

    You are not required to turn off the temp sensor, LoBatt sensor and Vref channels. Why do you think the values stored in ADC_Result[] are incorrect? Don't forget that you are using VCC as a reference and 8-bit resolution so the value will be in the range of 0 to 256, where result = Vinput*256/Vcc.

    Regards,
    Ryan
  • The values from accelerometer are correct only when I use direct single conversion from each channel in cycle. I have for example: X - 128, Y - 127, Z - 155 in default position of accelerometer. When I try to use DMA that values, for example, are: X - 171, Y - 193, Z - 175. When I rotate board that values lefts the same or changes little bit and that's why I'm thinking for fault values.

    After reading user guide I thought that analog channel increments up to A14. Thank you for clarification.

  • The ADC starts at the highest analog channel and decrements to zero in sequence-of-channels mode. Therefore ADC14 is stored in ADC_Result[0], ADC13 in ADC_Result[1], and ADC12 in ADC_Result[2]. Have you tried storing the sequence-of-channels values using the ADC10 ISR instead of the DMA? Then do you get the correct expected values?

    Regards,
    Ryan
  • Yes, I did. Without DMA the values correct.

    Now, I have no idea what to do, if the all init-routins right.

  • Remove DMADT_4 or replace it with DMADT_0. DMAEN should be automatically cleared when the DMAxSZ transfers have been made. Keeping the DMA active is allowing the following ADC12 conversions to trigger more DMA transfers, which are overwriting the values you need. In the sample code the error doesn't exist because it intentionally counts down to A0, in which case there are no more ADC flags to trigger extra DMA transfers.

    Regards,
    Ryan
  • Thanks a lot! It works! I should be more careful when reading user guide=)

**Attention** This is a public forum