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.

MSP430 ADC

Other Parts Discussed in Thread: MSP430F5438A, MSP430F5438

Hello,

I'm still in the learning stages of the msp430 processor. Right now I'm working with the msp430F5438A. I read through the user guide and now I have some questions. Can I used the ADC_10 to take multiple measurements of a circuit? I need to measure the input voltage 28 (volts) going into the device as well as the  28 (volts) voltage leaving the device. I know that the ADC_10 as multiple memory storage registers , but wouldn't that effect the ISR? I also was thinking about the analog input pins that I would used on the msp430F5438A.

Any help is appreciate.

  • Hello, I am workin with MSP430F5438A too. I hope my answer help you, if you watch something wrong, tell me please.

    Can I used the ADC_10 to take multiple measurements of a circuit?

    You also may consul the device datasheet (MSP430F5438) because the User's Guide corresponds to a device family, so there is some modules that appears in the guide, but they are not avaliable in your device. Reading the datasheet, ADC_10 is not avaliable in 5438A, only ADC_12. And yes, you can take multiple measurments of a circuit.

    I need to measure the input voltage 28 (volts)

    Page 62 of F5438A datasheet, "Analog input voltage range" between 0 and Vcc, Vcc is the powered voltage whose maximiun value is 3.6 V ( datasheet info again ). So, initially, you can not measure this input voltage value.

    I know that the ADC_10 as multiple memory storage registers , but wouldn't that effect the ISR? I also was thinking about the analog input pins that I would used on the msp430F5438A.

    Read carefully the ADC_12 section in Users' Guide. It is the better place where you find a clear explanation. If you come from other uC ( in my case 8051 ), it is some different the ADC functionality in this uC, but writing some testing code and debugging you will understand.

    Good luck.

  • Travis Pace said:
    Can I used the ADC_10 to take multiple measurements of a circuit?

    No. Becasue the 5438A has an ADC12, not an ADC10.
    But you can use the ADC12 to do it :)

    Basically, the ADC (both, ADC10 and ADC12) converts voltages relative to GND. And of course the input voltage must not exceed VCC (or, if you use one of the internal references, the reference voltage). Exceeding the reference resulty ins 0x0fff readings, exceeding VCC results in possible destruction of the MSP.

    Travis Pace said:
    I know that the ADC_10 as multiple memory storage registers , but wouldn't that effect the ISR?

    No and yes. The ADC10 has only one storage register. It msu tbe read once a conversion is done. This may happen interrupt-based or by DTC (specific type of DMA).

    The ADC12 has 16 independent storage registers which can be used to sample any combination and sequence of one of its 16 analog inputs. Interrupt can be triggered on any register update There are 16 independent IFG and IE bits, so you can trigger an interrupt after first half of conversions (double-buffering algorithm) or after a sequence is through. Just as you like. Or you can use (general purpose) DMA to move the results.

    On the 5438A, you can sample up to 12 external voltages (and 4 internal ones, including VCC and temperature), each by a different pin. However, sampling takes place one-after-another and not simultaneously.

  • For measuring  28V may be you can use voltage divider to bring it close to reference for ADC unit.

  • I did some more research on the ADC_12 in the user's guide. Since I will be measuring the 28 volts DC using a voltage divider, I assume that I need to select the appropriate  reference voltage.  Would 2.5 Volts be an appropriate reference voltage? I know if all elses fails I can just add a voltage from the AVcc pin.

     

    Also, for the  ADC12CONSEQx, I was thinking of  just doing  a single channel single conversion for each of the three analog inputs by changing the channels after each conversion is stored in memory. All of the measurements should give me the same voltage measurement anyway. I guess my question would be about the sequence of channels. Does the sequence of channels allow me to do multiple ADC conversions at the same time? I figure this can make more efficient coding as well as save more time by just calling one interrupt.

  • Travis Pace said:

    Also, for the  ADC12CONSEQx, I was thinking of  just doing  a single channel single conversion for each of the three analog inputs by changing the channels after each conversion is stored in memory. All of the measurements should give me the same voltage measurement anyway. I guess my question would be about the sequence of channels. Does the sequence of channels allow me to do multiple ADC conversions at the same time? I figure this can make more efficient coding as well as save more time by just calling one interrupt.

    If you use a sequence of channel mode, in the ISR you obtain all data conversions (that you have enabled) in the ISR. I could give you a little explanation because this ADC module has some characteristics that are different compared to 8051 for example ( I do not know with what uC you have worked before), but I am sure that it is better explained in the Users' Guide than I can do it. After reading it and writing some code, if you have any doubt, post here again, and we will try to help you again.

  • Travis Pace said:
    Would 2.5 Volts be an appropriate reference voltage?

    Depends on the voltage divider you use. YOu can use VCC or 2.5V or 1.5V. Just ensure that the divided voltage is below the reference you choose.

    Travis Pace said:
    Does the sequence of channels allow me to do multiple ADC conversions at the same time?

    Not at the same time. You set the first ADC12MCTLx register, anmd in sequence mode, teh ADC12 will perform the conversion configured in this register, then set the associated IFG bit and proceed to the next register adn perform teh conversion configured there, and so on, until it has done the conversion where the end-of-seqience bit was set.

    You can wait for the sequence to be complete by watching the ADC12IFG register for the final IFG bit popping up, or configure the interrupt to be triggered at the last conversion (or even for each single one, if you like). The results of all conversions are then waiting in the proper ADCMEMx registers.

  • Okay I've tooking all of the advice I've received and started coding. I have a small code that sends 2 Volts into the ADC_12 converter. The value that is being store from the memory register is bigger than 2 volts in hexadecimal format I believe. Is their any conversion that I need to get a reading of 2 volt? I tried dividing by 4096 but it isn't working.

  • Please, next time you post, include the ADC configuration and ADCMEMX register at least, by this way is easier find a solution.

    First, when you say "a code that sends 2 V into ...", I suppose you are meaning  connect  a 2 volts supply at a uC pin.

    The value you obtain in the register depends on the voltage reference and and uC voltage supply, hence, if we do not know the ADC configuration and power supplied to uC, it is difficult to resolve your question. In users' guide, page 602, it appears the conversion formula : N = 4095 * ( ( Vinput - Vref- ) / ( Vref+ - Vref- ) ). Thereby, the importance of knowing reference voltage and ADC configuration. For example, without enter in details like internal references and similar:

    With Vinput  = 3 and  Vref+ = 3 and Vref- = 0, ADCMEMXX = 4095. If we change the reference to 3.3 volts, ADCMEMXX = 3723. In this uC, if Vinput > Vref+ (between admisible values), the value showed in the register is 4096.

    And finally, it happens sometimes, have you tried to modify the input voltage and check that the memory register changes its value? It is not the first time I mistake with the pins configuration.

  • I’m working with msp430F5438A experimenter board. I’m sending 2 volts DC through the analog pin (A7) P6.7 and trying to store that value in memory register 7. I’m not exactly sure on what the voltage is on Vcc sends I’m connected through USB. I’m assuming the reference voltages could be 1.5 or 2.5 volts depending on the one I enable. Is there a data sheet out there for the experimenter board so I can know the default values or is the default values the same has the msp430F5438A. Below is example code I got off the website. I'm just using one conversion though. P6.7 analog pin (A7) off of the msp430F5438A experimenter board. I'm just trying to find something that I can build off on.

     

    //******************************************************************************

    //  MSP430F543xA Demo - ADC12_A, Sequence of Conversions (non-repeated)

    //

    //  Description: This example shows how to perform A/D conversions on a sequence

    //  of channels. A single sequence of conversions is performed - one conversion

    //  each on channels A0, A1, A2, and A3. Each conversion uses AVcc and AVss for

    //  the references. The conversion results are stored in ADC12MEM0, ADC12MEM1,

    //  ADC12MEM2, and ADC12MEM3 respectively and are moved to 'results[]' upon

    //  completion of the sequence. Test by applying voltages to pins A0, A1, A2,

    //  and A3, then setting and running to a break point at the "_BIC..."

    //  instruction in the ISR. To view the conversion results, open a watch window

    //  in debugger and view 'results' or view ADC12MEM0, ADC12MEM1, ADC12MEM2, and

    //  ADC12MEM3 in an ADC12 SFR window.

    //  This can run even in LPM4 mode as ADC has its own clock

    //  Note that a sequence has no restrictions on which channels are converted.

    //  For example, a valid sequence could be A0, A3, A2, A4, A2, A1, A0, and A7.

    //  See the 5xx User's Guide for instructions on using the ADC12.

    //

    //                MSP430F5438A

    //             -----------------

    //         /|\|                 |

    //          | |                 |

    //          --|RST              |

    //            |                 |

    //    Vin0 -->|P6.0/A0          |

    //    Vin1 -->|P6.1/A1          |

    //    Vin2 -->|P6.2/A2          |

    //    Vin3 -->|P6.3/A3          |

    //            |                 |

    //

    //   M Morales

    //   Texas Instruments Inc.

    //   June 2009

    //   Built with CCE Version: 3.2.2 and IAR Embedded Workbench Version: 4.11B

    //******************************************************************************

     

    #include "msp430x54xA.h"

     

    volatile unsigned int results;           // Needs to be global in this example

                                                // Otherwise, the compiler removes it

                                          // because it is not used for anything.

     

    void main(void)

    {

      WDTCTL = WDTPW+WDTHOLD;                   // Stop watchdog timer

     

      P6SEL = 0x80;                             // Enable A/D channel inputs P6.7

     

     

      /* Initialize ADC12_A */

      ADC12CTL0 = ADC12ON+ADC12MSC+ADC12SHT0_2; // Turn on ADC12, set sampling time

      ADC12CTL1 = ADC12SHP+ADC12CONSEQ_1;       // Use sampling timer, single sequence

      ADC12MCTL6 = ADC12INCH_7+ADC12EOS;                // ref+=AVcc, channel = A7, end of sequence

      ADC12IE = 0x80;                           // Enable ADC12IFG.7

      ADC12CTL0 |= ADC12ENC;                    // Enable conversions

     

      while(1)

      {

        ADC12CTL0 |= ADC12SC;                   // Start convn - software trigger

     

        __bis_SR_register(LPM4_bits + GIE);     // Enter LPM4, Enable interrupts

        __no_operation();                       // For debugger

      }

    }

     

    #pragma vector=ADC12_VECTOR

    __interrupt void ADC12ISR (void)

    {

          

      switch(__even_in_range(ADC12IV,34))

      {

      case  0: break;                           // Vector  0:  No interrupt

      case  2: break;                           // Vector  2:  ADC overflow

      case  4: break;                           // Vector  4:  ADC timing overflow

      case  6: break;                           // Vector  6:  ADC12IFG0

      case  8: break;                           // Vector  8:  ADC12IFG1

      case 10: break;                           // Vector 10:  ADC12IFG2

      case 12: break;                             // Vector 12:  ADC12IFG3

      case 14: break;                           // Vector 14:  ADC12IFG4

      case 16: break;                           // Vector 16:  ADC12IFG5

      case 18: break;                           // Vector 18:  ADC12IFG6

      case 20:                                      // Vector 20:  ADC12IFG7

                                                                                   // Move results, IFG is cleared

         results = ADC12MEM7;                 // Move results, IFG is cleared

      

         __bic_SR_register_on_exit(LPM4_bits);

      case 22: break;                           // Vector 22:  ADC12IFG8

      case 24: break;                           // Vector 24:  ADC12IFG9

      case 26: break;                           // Vector 26:  ADC12IFG10

      case 28: break;                           // Vector 28:  ADC12IFG11

      case 30: break;                           // Vector 30:  ADC12IFG12

      case 32: break;                           // Vector 32:  ADC12IFG13

      case 34: break;                           // Vector 34:  ADC12IFG14

      default: break;

      }

    }

     

     

  • Travis Pace said:
    Is there a data sheet out there for the experimenter board so I can know the default values or is the default values the same has the msp430F5438A.

    Both :) Default values of anything that is code-controlled are of course the same whether the processor in on the EXP board or not. The only parameter in question is VCC, which is likely to be 3.3V

    So if you use VCC ar erefernce, you'll have to know what VCC i. Else you use 2.5 or 1.5V reference and that's it. What you use is configured by software.

    However, to use the internal 1.5 or 2.5V reference, you'll have to enable it. On the 54xx (non-A), this is done in teh ADC12 registers (REFON etc.), bu ton 54xxA devices, this is primarily done in the REF module (see datasheet). You can transfer control back to ADC12 mdoule by clearing the REFMSTR bit in the REF module. Or you use the REF module and have an addiitonal 2.0V reference option.

    The code you posted uses VCC as reference, so you'll need to know it.

    Now the code you posted uses 'single sequence of channels' conversion mode. But you didn't properly configure a sequence. You only configured ADC12MCTL6 (!) to sample A7.  Then when conversion starts, the ADC12 begins the sequence on ADC12MCTL0 , which has an undefine dvalue. Maybe the sequence already ends here. Maybe it continues with ADC12MCTL1 etc. In any case, conversion ends on ADC12MCTL6 (which you configured) and the result is in ADC12MEM6. Since the sequence dfinitely ends on ADC12MCTL6, the interrupt you are waiting for is never triggered, and of course ADC12MEM7 never gets a value assigned. ADC12MEM6 gets the conversion result for A7, relative to VCC, but does nto trigger an interrupt in your configuration.

  • I do not know how the uC works when you configure a sequence of channel, but you only read one of the ADC registers. So if you only want to read one value, I would recommend you to use single channel conversion, I suposse that the nmonic is "ADC12CONSEQ_0", check in the header file and you do not have to use the ADC12EOS bit.

    Moreover, the ISR is related to the storage register ADCMEMXX, not to the pin you use as input. So, with this configuration, the ISR you have to use is :

    " case 18: break;                           // Vector 18:  ADC12IFG6" .

    Another example, related to the ISR, with :

    ADC12MCTL0 = ADC12INCH_2;

    you have to use   "case  6: break;                           // Vector  6:  ADC12IFG0", because the storage register is ADCMEM00 althought you are reading the pin 2.

  • I know its been a while but I finally got a single channel working. Now I'm trying to add a sequence of channels, I know that setting the  ADC12CONSEQx bit will allow for a sequence of channels but is it that simple? I'm starting the conversions at analog input 13 and i'm assumming that I will just add analog input 14 to the ISR as well as set the EOS (End of Sequence) to ADCMCTL14.

     

     

    P.S

    I appreciate all that gave feedback in this forum, my progression is just slower than others.

  • Travis Pace said:
    is it that simple?

    Even more.

    There is no fixed relation between teh ADC12MEMx register and the input channel. Your sequence can begin with ADC12MCTL0 in which you program the first input you want to convert, then continues with ADC12MCTL1 where tyou define the second input you want to read. Not necessarily the next one. YOu can make jumps and patterns or read the same channel twice if you want. The last ADC12MCTLx gets the EOS bit set and ends the sequence. The first ADC12MCTLx register where the sequence starts has to be programmed into the ADC12CTL registers. The interrupt bits are set according to the ADC12MCTLx register that was 'done', not the input channel that was coverted.

  • Thanks for the help

    I have two new questions has I expand on my project. For the repeat "Sequence of channels", do I have to apply a while loop to the ADC12CTL0 |= ADC12SC;

    __bis_SR_register(LPM0_bits + GIE); routine.? The question seems kinda of stupid because their's no way it can continuously take measurements without having the interrupt routine called repeatedly? But at the same time would I have to used the repeat "Sequence of Channels" enable bit, because wouldn't a while loop cause the interrupt routine to continuously run?

    My second question is, is their a way to time how fast the measurements are taken from the Sequence of Channels"? I'm assuming the measurements are taken simultaneously?

  • Thw repeat sequence of channels either runs one sample at a time and you'll need to set ADC12SC for each single sample, or you set the MSC bit and the sequence runs continuously, once started. Over and over again. The ISR is triggered each time the ADC12MEMx is written with a new sample and the IE bit for that result is set. So if the last element of your sequence is ADC12MCTL6 and you did set the IE bit for ADC12MEM6, then the ISR is called each time the sequence was completed. However, you can call teh ISR even more often. E.g. after first half of the sequence and at its end, so the ISR can wotk on one half whiel the other half of the sequence is sampled.

    The ADC12 is a rather complex thing that allows a wide variety of conbinations and actions, but this makes it difficult to explain all possible uses.. It'S easier to recommend a solution for a specific problem rather than give a general explanation.

  • The code I posted above has been change drastically, its reading three sequential channel ADC inputs repeatedly. This code is one piece of the project. After receiving the inputs from the ADC channels,  the code will send this information to UART. Anyways due to the Sequential of Channels  repeatedly bit being set the samples will always be available I just need to call the ISR?

    My last questions about the ADC are has follow?

    How does the sampling timing / frequency bit work? Does the number of samples affect the value being read through the ADC?  I am reading the value from the ADC and its correct but off by a decimal point. Like instead of reading 2.00 volts, I get 1.98, 2.12 etc. Sometimes it spikes to 2.5 or some random number. Does the sampling period effect that ?

  • While this thread is active I would like to ask for help real quick. I am trying to get a 2-channel single sequence of channels to work but the 2nd channel always remains empty. I tested with the interrupt vectors enabled individually and the first channel's interrupt triggers but the 2nd channel does not, so it appears that something is disabling that channel. I am fairly sure I understand 90% of the ADC12 and have checked over all of my register settings. Can someone check my code and see if they see anything wrong? Thanks in advance!

    //in startup

    //Sentry Output, setup for ADC channels
    P2SEL |= BIT1 + BIT2 + BIT3;
    PMAPPWD = 0x02D52; // Get write-access to port mapping regs
    P2MAP1 = 31;//A1, SentryOut1
    P2MAP2 = 31;//A2, SentryOut0
    PMAPPWD = 0; // Lock port mapping registers

    //in adc function

    ADC12CTL0 &= ~ADC12ENC;

    ADC12CTL0 = ADC12ON //Turn ADC On
    + ADC12MSC //Automatic Conversion
    + ADC12SHT0_2 //Sample and Hold Time
    + ADC12REF2_5V //2.5V Reference Voltage
    + ADC12REFON; //Reference Voltage On
    ADC12CTL1 = ADC12SHP //Use sampling timer
    + ADC12CONSEQ_1; //Sequence of Channels 1 and 2
    ADC12MCTL0 = ADC12INCH_1; //channel = A1,sentry 1
    ADC12MCTL1 = ADC12INCH_2 //channel = A2,sentry 2
    + ADC12EOS; //EndOfSeq

    ADC12IFG = 0; //no interrupts
    __delay_cycles(75); // ~75us shared ref. settling time
    ADC12CTL0 |= ADC12ENC; // Enable conversions
    ADC12CTL0 |= ADC12SC; // Start conversion

    while((ADC12CTL1 & ADC12BUSY) == 1){}; //wait until ADC is ready

    ADC12CTL1 &= ~ADC12CONSEQ_1; // Stop conversion immediately
    ADC12CTL0 &= ~ADC12ENC; // disable ADC12 conversion
    ADC12CTL0 = 0; // Switch off ADC12 & ref voltage

    unsigned int ADC_A = ADC12MEM1; // Move results
    unsigned int ADC_B = ADC12MEM2; // Move results (always 0)

     

  • Andrew Thornton said:
    ADC12MCTL0 = ADC12INCH_1; //channel = A1,sentry 1
    ADC12MCTL1 = ADC12INCH_2 //channel = A2,sentry 2
    + ADC12EOS; //EndOfSeq

    With these lines, you are storing the value of input channel 1 in ADC12MEM0, and the input channel 2 in ADC12MEM1, while at the end of your code, you are reading ADC12MEM1 and ADC12MEM2.

    In these uCs, the interrupt and storing is not related to the input channel, it is related to the ADC12MEMXX register whose configuration is in ADC12MCTLXX.

  • Is T da S said:

    With these lines, you are storing the value of input channel 1 in ADC12MEM0, and the input channel 2 in ADC12MEM1, while at the end of your code, you are reading ADC12MEM1 and ADC12MEM2.

    AAH I'm so silly! Thanks!!

  • The code I posted above has been change drastically, its reading three sequential channel ADC inputs repeatedly. This code is one piece of the project. After receiving the inputs from the ADC channels,  the code will send this information to UART. Anyways due to the Sequential of Channels  repeatedly bit being set the samples will always be available I just need to call the ISR?

    My last questions about the ADC are has follow?

    How does the sampling timing / frequency bit work? Does the number of samples affect the value being read through the ADC?  I am reading the value from the ADC and its correct but off by a decimal point. Like instead of reading 2.00 volts, I get 1.98, 2.12 etc. Sometimes it spikes to 2.5 or some random number. Does the sampling period effect that ?

  • Travis Pace said:
    Does the sampling period effect that ?

    Teh samplign period mus tbe lkong enough to allow the sampling capacitor to fully charge (well at least to +-1/2 LSB). How long this takes depends on the capacitor size (different for different MSPs, or at least families), teh resires resistance of th einput multiplexer (~1k) and the output impedance of your signal source.

    However, on a static input voltage, the same smapling time should result in the same reading (+- noise).

    But there is another thing: the ground reference. When current flows through your PCB, this causes a voltage drop on the traces. This includes GND. If total board current consumption vaires, this measn that different parts of the GND trace have different currents at different times and therefore GND ins't the same everywhere and everytime. This can easily cause some 'noise' on the readings. For this reason, some MSPs have a separate analog GND input which only connects points where GND is required as reference and no current is routed through.

    Another possible problem is the reference you use. If you use VCC as reference, voltage ripples on VCC will affect the reading as the voltage reading of the ADC is the relation between reference and signal. If the signal is static but the reference isn't, this is the same as if the reference is static and the signal isn't.
    If you use the regulated references, ensure that you meet all requirements. Some MSPs require external buffering of the internal reference, on some MSPs, the internal reference requires the ADC clock being lower thabn a certain frequency. Check datasheet and errata sheet.

  • Its been a while, but I 've been working on other parts of the project. It turn out that the grounding reference was an issue. I was using one on a breadboard instead of the experimenter board. Even though I now have this part working for the most part my Professor wants me to take about 10 samples every 0.5 msecs for even more accuracy. Could someone provide me with some understanding of taking samples from ADC? I understand samples but its the coding that I've a hard time understanding as far as using timers, frequencies and compare/captures?

**Attention** This is a public forum