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.

MSP430F5529 ADC12_A

Hello

I have 2 questions about the following code which works normally. The purpose of the code is to turn the LED connected to pin 1.0 if the photo resistor connected to the ADC12_A input (pin 6.0) is completely covered, otherwise it turns the LED OFF.

the questions are:

1- what is the default resolution of ADC12_A? According to the datasheet, the resolution is defined using bits ADC12RES in ADC12CTL2 register. It can be either 8, 10, 0r 12. In the following code, ADC12RES=0 which means the resolution is 8 bits,  but the resolution is 12 instead of 8?

2- In this code the result of the conversion is available in ADC12MEM0 memory register. Is pin 6.0 connected to this register by default? I thought we need to explicitly configure ADC12MEM0 memory register  to read data from one of the ADC12 input pins using  ADC12MCTL0 control register. Is my understanding correct?

the code is bellow:

----------------------------------------------------------------------------------------------------------------------------------------------

#include <msp430.h>

int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
ADC12CTL0 = ADC12SHT00 + ADC12ON; // Sampling time, ADC12 on
ADC12CTL1 = ADC12SHP+ADC12SSEL1; // Use sampling timer+ timer clock is ACLK
ADC12IE = ADC12IE0; // Enable interrupt, you can use 0x01 as well
ADC12CTL0 |= ADC12ENC;
P6SEL |= BIT0; // P6.0 ADC option select
P1DIR |= BIT0; // P1.0 output
P1OUT &= ~BIT0;
while (1)
{
ADC12CTL0 |= ADC12SC; // Start sampling/conversion

__bis_SR_register(LPM0_bits + GIE); // LPM0, ADC12_ISR will force exit

}
}

#pragma vector = ADC12_VECTOR
__interrupt void ADC12_ISR(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: // Vector 6: ADC12IFG0
if (ADC12MEM0 < 0x7ff) // ADC12MEM = A0 < 0.5AVcc?
P1OUT &= ~BIT0; // P1.0 = 1
else
P1OUT |= BIT0; // P1.0 = 0
__bic_SR_register_on_exit(LPM0_bits); // Exit active CPU

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: break; // Vector 20: ADC12IFG7
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;
}
}

----------------------------------------------------------------------------------------

Thanks

Mahmoud

  • 1) ADC12RES=2 at reset, so if you don't change it the resolution is 12 bits. [Ref User Guide (SLAU208Q) Table 28-6.] This code appears to expect 12-bit.

    2) The An for MEM0 is set using ADC12MCTL0:ADC12INCH. ADC12MCTL=0 at reset, so if you don't change it it refers to A0 (INCH=0). [Ref User Guide Table 28-8]. You're using (by omission) CONSEQ=0, which uses MCTL0/MEM0 (unless you change that with ADC12CTL1:ADC12CSTARTADD).

    Unsolicited:

    > ADC12CTL1 = ADC12SHP+ADC12SSEL1; // Use sampling timer+ timer clock is ACLK

    ADC12SSEL1 is a bit name, not a field value, so this actually sets SSEL=2. To get SSEL=1 use ADC12SSEL_1. 

  • Dear Bruce,

          I hope you had a safe and happy thanksgiving holiday. Thank you very much for your very detailed reply.

    I am still struggling with your last comment, would you please explain more why ACD12SSEL1 sets SSEL=2? what is the difference between bit name and field name?

    Thanks

    MAhmoud

  • ADC12SSEL1 is just bit 1 (not bit 0) of the field ADC12SSEL. ADC12SSEL_1 is a value of 1 in the field ADC12SSEL. Your comment said you wanted ACLK, which is a value of 1 in the field ADC12SSEL.

    #define ADC12SSEL0 (0x0008) /* ADC12 Clock Source Select Bit: 0 */
    #define ADC12SSEL1 (0x0010) /* ADC12 Clock Source Select Bit: 1 */
    [...]
    #define ADC12SSEL_0 (0*8u) /* ADC12 Clock Source Select: 0 */
    #define ADC12SSEL_1 (1*8u) /* ADC12 Clock Source Select: 1 */     
    #define ADC12SSEL_2  (2*8u)   /* ADC12 Clock Source Select: 2 */
    

    In practice, I almost never use the bit names, but I imagine they're supposed to be defined since they're in the User Guide.

    [Edit: Added SSEL_2 for comparison.]

  • Thank you Bruce for your response.

    I have another question regarding multichannel ADC. The following code converts the analog inputs from A0 (6.0) and A1(6.1). It flash the onboard LEDs according to the input voltage. Unfortunately it did not work. Would you please let me know if I made a configuration error.

    #include <msp430.h>

    int main(void)
    {
    WDTCTL = WDTPW + WDTHOLD; // Stop WDT
    ADC12CTL0 |= ADC12SHT0_0 + ADC12ON; // Sampling time, ADC12 on
    ADC12CTL1 |= ADC12SHP+ADC12SSEL_1+ADC12CONSEQ_1; // Use sampling timer+ timer clock is ACLK+ sequence of channels
    ADC12MCTL0|=ADC12INCH_0; // A0=6.0
    ADC12MCTL1|=ADC12INCH_1+ADC12EOS; // A1=6.1, End of sequence
    ADC12IE = ADC12IE0+ADC12IE1; // Enable interrupt from both MEM0 and MEM1,
    ADC12CTL0 |= ADC12ENC;
    P6SEL |= BIT0+BIT1; // P6.0 ADC option select
    P1DIR |= BIT0; // P1.0 output
    P1OUT &= ~BIT0;
    P4DIR |= BIT7; // P4.7 output
    P4OUT &= ~BIT7;
    while (1)
    {
    ADC12CTL0 |= ADC12SC; // Start sampling/conversion

    __bis_SR_register(LPM0_bits + GIE); // LPM0, ADC12_ISR will force exit

    }
    }

    #pragma vector = ADC12_VECTOR
    __interrupt void ADC12_ISR(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: // Vector 6: ADC12IFG0
    if (ADC12MEM0 < 0x7ff) // ADC12MEM0 = A0 < 0.5AVcc?
    P1OUT &= ~BIT0; // P1.0 = 1
    else
    P1OUT |= BIT0; // P1.0 = 0
    __bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
    break;
    case 8:
    if (ADC12MEM1 < 0x2ff) // ADC12MEM1 = A1 < 0.5AVcc?
    P4OUT &= ~BIT7; // P4.7 = 1
    else
    P4OUT |= BIT7; // P4.7 = 0
    __bic_SR_register_on_exit(LPM0_bits); // Exit active CPU

    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: break; // Vector 20: ADC12IFG7
    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;
    }
    }

  • Per User Guide (SLAU208Q) Sec 28.2.7.2, you have to explicitly clear ADC12SC (before setting it again) with CONSEQ=1. This is non-obvious, in fact I forgot it myself. The sentence refers to "sequence", but since you have MSC=0 it's actually after every conversion. 

    So just add this just before setting ADC12SC:

    >  ADC12CTL0 &= ~ADC12SC;   // Clear for next conversion

  • Thank you Bruce, I have tried your suggestion. It works partially, as I am currently only able to see indication that ADC12 places data in MEM1. No response from MEM0. So in the following code only LED 4.7 is turned OFF and ON. Would you please advise.

    #include <msp430.h>

    int main(void)
    {
    WDTCTL = WDTPW + WDTHOLD; // Stop WDT
    ADC12CTL0 |= ADC12SHT0_8 + ADC12ON; // Sampling time, ADC12 on
    ADC12CTL1 |= ADC12SHP+ADC12SSEL_1+ADC12CONSEQ_1; // Use sampling timer+ timer clock is ACLK+sequence of channels
    ADC12MCTL0|=ADC12INCH_0; // A0=6.0
    ADC12MCTL1|=ADC12INCH_1+ADC12EOS; // A1=6.1, End of sequence
    ADC12IE = ADC12IE0+ADC12IE1; // Enable interrupt from both MEM0 and MEM1,
    ADC12CTL0 |= ADC12ENC;
    P6SEL |= BIT0+BIT1; // P6.0 ADC option select
    P1DIR |= BIT0; // P1.0 output
    P1OUT &= ~BIT0;
    P4DIR |= BIT7; // P4.7 output
    P4OUT &= ~BIT7;
    while (1)
    {
    ADC12CTL0 &= ~ADC12SC;
    ADC12CTL0 |= ADC12SC; // Start sampling/conversion

    __bis_SR_register(LPM0_bits + GIE); // LPM0, ADC12_ISR will force exit

    }
    }

    #pragma vector = ADC12_VECTOR
    __interrupt void ADC12_ISR(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: // Vector 6: ADC12IFG0
    if (ADC12MEM0 < 0x2ff) // ADC12MEM0 = A0 < 0.5AVcc?
    P1OUT &= ~BIT0; // P1.0 = 1
    else
    P1OUT |= BIT0; // P1.0 = 0
    __bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
    break;
    case 8:
    if (ADC12MEM1 < 0x2ff) // ADC12MEM1 = A1 < 0.5AVcc?
    P4OUT &= ~BIT7; // P4.7 = 1
    else
    P4OUT |= BIT7; // P4.7 = 0
    __bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
    // 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: break; // Vector 20: ADC12IFG7
    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;
    }
    }

  • When I run this code on a Launchpad, I get a response from both P6.0 and P6.1. My test case is quite primitive -- I just jumper the pin to GND or 3V3. 

    What do you have connected to those pins?

  • Hi Bruce,

         Thank you, the issue is from my side, I have pin 6.0 not working. Thank you and happy holidays.

**Attention** This is a public forum