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.

internal temp sensor enable

Other Parts Discussed in Thread: MSP430F5338, MSPWARE

Hi all,

I am using MSP430F5338. In this i am trying to read the internal temperature sensor value from ADC channel number 10 (A10). In this uC 12bit ADC is available sine i take a decision to disable the REFMSTR bit of REFCTL0. To enable the Temperature sensor enabled ADC12REFON bit of  ADC12CTL0 register. Apart from this i am reading ADC channel 0 to 7 (A0-A7) with the external reference volatage 3.3V. As per the data sheet " Setting the ADC12REFON bit enables the REFGEN subsystem which includes the bandgap, the bandgap bias circuitry, and the 1.5-V, 2.0-V, 2.5-V buffer. Setting this bit causes the ADC12REFON REFGEN subsystem to remain enabled regardless if any module has requested it. Clearing this bit disables the REFGEN subsystem only when there are no pending requests for REFGEN from all modules."  I have quite confusion here "if i enable the ADC12REFON for the temperature channel alone the internal reference will enabled whether is it affect the renaining channel whichever using external reference voltage". Also after modifying the REFMSTR bit 0 none of the code except REFMSTR bit 0 made code is not running on the controller, why? Is the REFMSTR will affect any default settings of uC? Also if the following BSP code run means the count for temp value received as around 2000.

int i;
long temp;
volatile long IntDegF;
volatile long IntDegC;

int main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
  REFCTL0 &= ~REFMSTR;                      // Reset REFMSTR to hand over control to 
                                            // ADC12_A ref control registers  
  ADC12CTL0 = ADC12SHT0_8 + ADC12REFON + ADC12ON;
                                            // Internal ref = 1.5V
  ADC12CTL1 = ADC12SHP;                     // enable sample timer
  ADC12MCTL0 = ADC12SREF_1 + ADC12INCH_10;  // ADC i/p ch A10 = temp sense i/p
  ADC12IE = 0x001;                          // ADC_IFG upon conv result-ADCMEMO
  for(i=0;i<30;i++)                         // Delay to allow Ref to settle
  ADC12CTL0 |= ADC12ENC;

  while(1)
  {
    ADC12CTL0 |= ADC12SC;                   // Sampling and conversion start

    __bis_SR_register(LPM4_bits + GIE);     // LPM0 with interrupts enabled
    __no_operation();

    // Temperature in Celsius
    // ((A10/4096*1500mV) - 894mV)*(1/3.66mV) = (A10/4096*410) - 244
    // = (A10 - 2438) * (410 / 4096)
    IntDegC = ((temp - 2438) * 410) / 4096;

    // Temperature in Fahrenheit
    // ((A10/4096*1500mV) - 829mV)*(1/2.033mV) = (A10/4096*738) - 408
    // = (A10 - 2264) * (738 / 4096)
    IntDegF = ((temp - 2264) * 738) / 4096;
    __no_operation();                       // SET BREAKPOINT HERE
  }
}

#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:                                  // Vector  6:  ADC12IFG0
    temp = ADC12MEM0;                       // Move results, IFG is cleared
    __bic_SR_register_on_exit(LPM4_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;
  }
}

If i run the code which developed by me means the count for temp value is come around 1400 only. I am not able to get the reason. The pseudocode of the my code as below

ADC12CTL0 &= ~(0xFF80);
ADC12CTL1 |= 0x0C1E;
ADC12CTL1 &= ~(0x03E0)
ADC12CTL2 |= 0x0020;
ADC12CTL0 |= 0x0010;
// Channel number is up to temp sensor channel
for (ix = 0; ix <= 10; ++ix)
{
    ADC12MCTLX[ix] = 0x00;
    // Select reference
    if(ix == 10)
    {
        REFCTL0 &= ~REFMSTR;
        ADC12CTL0 |= 0x0020;
        // 001b = V(R+) = VREF+ and V(R-) = AVSS
        ADC12MCTLX[ix] &= 0x9F;
    } else
    {
        // 000b = V(R+) = AVCC and V(R-) = AVSS or
        ADC12MCTLX[ix] &= 0x8F;
    }

// ADC12INCHx - Input channel select
ADC12MCTLX[ix] |= ix;
} 

// Set EOS to memory control register.
ADC12MCTLX[10] |= 0x80;

ADC12CTL0 |= 0x0002;
ix = 0;
while (ix != adc_ptr->eosChanNo))
{
    // Interrupt flag check
    while (ADC12IFG == 0x0000)
    {
    } 

    // Selecting the channel number based on interrupt flag
    for (ix = 0; ix < 10; ++ix)
    {
        if ((ADC12IFG >> ix) & 0x01)
        {
        break;
        }
    } // closing of for loop
    // Reset only particular channel flag
    adcReg_ptr->ADC12IFG &= ~(0x01 << ix);
    // Store the ADC converted value from the ADC memory register.
    *ptr[ix]) = ADC12MEMX[ix];
    ++ptr[ix];
}


have anyone face such a kind of issue.

 

  • Hello Prakash,

    The REFMSTR bit determines whether the reference system is controlled by the ADC12_A module or the REFCTL register. As you are controlling the reference through the ADC12 it is necessary to clear the REFMSTR bit. Your code is exactly the same as the TI msp430f66xx_adc_10.c example code without the inclusion of the device descriptor table settings. Can you further explain why you believe your first code insert does not work correctly?

    Can you further explain your second code insert and how it is not working as expected? You shouldn't need a timer trigger for repeat-sequence-of-channels mode and in this mode an interrupt flag will signify that all channels have been converted and are available to be read. Please reference msp430f66xx_adc_09.c of the MSP430F563x, MSP430F663x Code Examples: www.ti.com/.../slac417

    Regards,
    Ryan
  • Hi Ryan,

    Thanks for your reply. I am trying to use the the following code to read the temperature sensor chennael count. I am using REFMSTR bit  and REFOUT bit REFCTL0 register is set. And i am using Vcc as a refrence for all the channels except the A10. For A10 i am using internal 1.5v as reference. For this code i am always receiving the constant value as a count. But if i run the BSP code from TI (adc12_a_ex8_tempSensor) i can see the variation in ADC count. I am not able to found the root cause for this ia ma debugging this issue more than a week, still i am struggling. Could you please help me this.

        // ADC12SHSx - Sample-and-Hold Source selection (Timer source - B0)
        // ADC12SSELx - Set clock Source (SMCLK)
        // ADC12CONSEQx - Repeat-sequence-of-channels mode select 
    ADC12CTL1 |= 0x0C1E;
        // ADC12TCOFF = 0 to enable Temperature sensor
        // ADC12RES 12 bit conversion result resolution
    ADC12CTL2 |= 0x0020;
        // ADC12ON = ADC12_A on in bit 4
    ADC12CTL0 |= 0x0010;
    
        // Channel number is up to temp sensor channel
    for (ix = 0; ix <= 10; ++ix)
    {
            // clear all modulation control registers
        ADC12MCTLX[ix] = 0x00;
            // Select reference for each channel
        if(ix == 10)
        {
                // set the ref module with ref enable bit
                // for temp sensor channel alone
            REFCTL0 |= 0x0081;
                // 001b = V(R+) = AVCC and V(R-) = AVSS
                // set ADC12SREFx = 001 to set 1.5V internal voltage as reference
            ADC12MCTLX[ix] |= 0x10;
        } else
        {
                // 000b = V(R+) = AVCC and V(R-) = AVSS
                // set ADC12SREFx = 000 to set 3.3V Vcc as reference
            ADC12MCTLX[ix] &= 0x8F;
        }
    
        // ADC12INCHx - Input channel select as per the channel input value
    ADC12MCTLX[ix] |= ix;
    } 
    
        // Set EOS to memory control register.
    ADC12MCTLX[10] |= 0x80;
    
        // ADC12ENC ADC12_A enable conversion in bit 1
    ADC12CTL0 |= 0x0002;
    
    ix = 0;
        // This loop will run till read all the channels
    while (ix != adc_ptr->eosChanNo))
    {
            // Interrupt flag check for each channel
        while (ADC12IFG == 0x0000)
        {
        } 
    
            // Check which channel interrupt flag is set
        for (ix = 0; ix < 10; ++ix)
        {
            if ((ADC12IFG >> ix) & 0x01)
            {
                break;
            }
        } 
            // Reset only particular channel flag
        adcReg_ptr->ADC12IFG &= ~(0x01 << ix);
        
            // Store the ADC converted value from the ADC memory register.
        *ptr[ix]) = ADC12MEMX[ix];
        ++ptr[ix];
    } 

     

  • Prakash,

    you already have another thread here:

    Dennis

  • Prakash,

    You have not followed the suggestions from your previous thread where Leo notes that the ADC sampling time must be at least 30us. Since you only bit set ADC12CTL0 to 0x10 to turn on the ADC I doubt that your sample-and-hold time is above the default 4 ADC12CLK cycles, which sampling from SMCLK assumed to be set to the default 1 MHz leaves you with a 4 us sampling time. This is not near enough time and could explain why you are seeing a constant value. Please increase the ADC12SHT1x value inside of the ADC12CTL0 register (assuming A10 conversions are stored somewhere in ADC12MEM8-15) to at least 0x04 assuming you have no need for small sample-and-hold times.

    Since you have example code that you know works the best course of action is to use the debugger to compare the register values in your code against that of the example code. This can usually give you some clues as to what your code is missing.

    Regards,
    Ryan
  • Ryan & Leo

    I have made the changes as per the sample code in my code also i am polling the interrupt flag instead of interrupt method  its working fine. In sample code they are using the MCTL0 register by setting  ADC12INCHx as

    1010b = Temperature diode

    and  ADC12MEM0 register to store the read value. In the same code i have changed the MCTL0 to MCTL10 and the ADCTL1 register bit from 15 to 12 as 1010 to set conversion start address as channel 10 and i am expecting the converted value to be stored in ADC12MEM10. For this case i am always receiving the value is 0x0FFF;

    The code as below

        // ADC12ENC bit should be cleared before initializing the ADC12_A
        // Reset the ADC Control registers & Clear Interrupt Registers
    ADC12CTL0 = 0x0000;
    ADC12CTL1 = 0x0000;
    ADC12CTL2 = 0x0000;
    ADC12IFG  = 0x0000;
    ADC12IE   = 0x0000;
    
        // clear  memory control register.
    //ADC12MCTLX[0] |= 0x00;
    ADC12MCTLX[10] |= 0x00;
    
        // ADC core ON
    ADC12CTL0 = ADC12ON;
        // using ADC12OSC as a clock
    ADC12CTL1 = ADC12SHP;
    ADC12CTL0 |= ADC12SHT0_8;
    
        // 001b = V(R+) = AVCC and V(R-) = AVSS
    ADC12MCTLX[0] = ADC12SREF0 | ADC12INCH_0;
    ADC12MCTLX[10] = ADC12SREF0 | ADC12INCH_10;
    
        // To set the channel start address
        // This is used to set the start channel as 10
    ADC12CTL1 |= ADC12CSTARTADD3  | ADC12CSTARTADD1;
    
    REFCTL0 = REFGENACT | REFON;
    __delay_cycles(75);
    
        // Enable repeat single channel
    ADC12CTL1 |= ADC12CONSEQ0;
    
    ADC12CTL0 |= ADC12ENC;
    ADC12CTL0 |= ADC12SC;
    
    //while (!(ADC12IFG == 0x0000))
    while (!(ADC12IFG & 0x0400))
    {
    } 
    
    //temp = ADC12MEM0;

    temp = ADC12MEM10;

  • RYAN and LEO

    I have modified my code as per the sample code in that instead of interrupt i am using polling method. In sample code they are using MCTL0 with MEM0 memory register. I have slightly modified the to read the channel 10 value by setting MCTL10 and MEM10 and changed the ataring adress in ADCTL0 as 0101 (bit 15 -12). For this case i am always receiving the valua as 0x0FFF. Could you please guide me. The code as below

        // ADC12ENC bit should be cleared before initializing the ADC12_A
        // Reset the ADC Control registers & Clear Interrupt Registers
    ADC12CTL0 = 0x0000;
    ADC12CTL1 = 0x0000;
    ADC12CTL2 = 0x0000;
    ADC12IFG  = 0x0000;
    ADC12IE   = 0x0000;
    
        // clear  memory control register.
    //ADC12MCTLX[0] |= 0x00;
    ADC12MCTLX[10] |= 0x00;
    
        // ADC core ON
    ADC12CTL0 = ADC12ON;
        // using ADC12OSC as a clock
    ADC12CTL1 = ADC12SHP;
    ADC12CTL0 |= ADC12SHT0_8;
    
        // 001b = V(R+) = AVCC and V(R-) = AVSS
    ADC12MCTLX[0] = ADC12SREF0 | ADC12INCH_0;
    ADC12MCTLX[10] = ADC12SREF0 | ADC12INCH_10;
    
        // To set the channel start address
        // This is used to set the start channel as 10
    ADC12CTL1 |= ADC12CSTARTADD3  | ADC12CSTARTADD1;
    
    REFCTL0 = REFGENACT | REFON;
    __delay_cycles(75);
    
        // Enable repeat single channel
    ADC12CTL1 |= ADC12CONSEQ0;
    
    ADC12CTL0 |= ADC12ENC;
    ADC12CTL0 |= ADC12SC;
    
    //while (!(adcReg_ptr->adc12Ifg == 0x0000))
    while (!(ADC12IFG & 0x0400))
    {
    } 
    
    //temp = ADC12MEM0;
    temp = ADC12MEM10;

  • Leo is not copied on this forum thread, the only other person who has replied to this one so far has been Dennis...

    1) You cannot write to the REFGENACT bit inside of the REFCTL0 register as it is read only.

    2) Why are you initializing ADC12MCTLX0 if you are not using it? It doesn't affect the code any but I'm curious as to your intent for it.

    3) Although you intend to store your conversion inside of ADC12MEM10 you are still altering the sample-and-hold time for ADC12MEM0-7. This means you are once again only allowing for the default sample-and-hold time of 4 ADC12CLK cycles. You should be altering the ADC12SHT1 bits instead of ADC12SHT0.

    Regards,
    Ryan
  • Thanks for your reply I have modified the ADC12SHT0 t0 ADC12SHT1 in ADCCTL0 and its working fine. And i have the following queries please clarify

    1. How do we calculate the sampling time if we are using timer as a trigger source. (SMCLK of 20MHz is used as a ADC clock and the sampling rate is 100000).

    2. Is there any sample code/application document available for timer trigger based ADC implementation in repeated sequence mode to read temperature sensor value too? I am developing the code for this application as i shared in my first discussion. If i get any document it will be useful

    Thanks in advance

  • The Sampling time is not part of the (Timer) Trigger source interval time nor the ADC clock frequency, but in reverse the Trigger interval time depends on the Sampling time.

    The User’s Guide describes under “Sample and Conversion Timing” exactly how this must be organized and calculated.

    If you would search, for example in MSPWare, you will find some examples, but the configuration depends very much on your hardware and needs.
  • hi
    Thanks for your reply. I already have the driver library and looked in that but there is no sample codes using timer trigger as source for ADC, since i have raised this query. If it is there any application note it will be more useful. Also i have developed the code with 100000 sampling rate and set timer B0 as trigger source. In that i have calculated the trigger interval based on the minimum sampling time as 4us(3.64 is given in data sheet). But if am using this setting i am always receiving constant value for temperature sensor channel alone. Can you help me to understand the reason for this.

    Thanks in adavance
  • You need to read carefully the User’s Guide about the working of the ADC.
    The chapter “Sample and Conversion Timing” explains that the ADC needs to charge his internal capacitor before a conversion can start.
    You also will discover that a sequence can be split up into two parts which each a different Sampling time.
  • Leo Bosch said:
    You also will discover that a sequence can be split up into two parts which each a different Sampling time

    means "from channel 0 to 7 different sampling rtae and for channel 10 diffferent sampling rate". Is my undersatnding correct. Also i need to read the channel 0 to 10 in repeated sequence mode for timining consideration is it possible or not? Thanks in advance

  • Leo Bosch said:
    You also will discover that a sequence can be split up into two parts which each a different Sampling time.

    From that i have understood the sampling time is differ for temperature channel from th remaining channel? Am i wright? If, not please help me to understand correctly.

  • I think Leo is commenting on how ADC12SHT0x selects the sampling time for ADC12MCTL0 to ADC12MCTL7 and ADC12SHT1x selects the sampling time for ADC12MCTL8 to ADC12MCTL15. The internal temperature sensor can be selected for any of these conversion memory register locations.

    Regards,
    Ryan

**Attention** This is a public forum