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.

MSP430FR5872: On Chip Temperature Sensor

Part Number: MSP430FR5872

Hi all,

I am using MSP430F5872. In this, I am trying to read the internal temperature sensor value from ADC12 channel 30 

Queries:

1)My first query is whether this channel number is right?. If No then which is correct channel number to read internal temperature value.

2)On what basis we should select Internal Voltage Reference and with respect to it what should be the calibration value?

3)I am not able to read the correct value from this channel. Apart from this, I am reading ADC channel 12  with the external reference voltage 3.3V which is providing me correct value.

 

Below is my code.

 

#define CALADC12_12V_30C *((unsigned int *)0x1A1A) // Temperature Sensor Calibration-30 C

#define CALADC12_12V_85C *((unsigned int *)0x1A1C) // Temperature Sensor Calibration-85 C

void ADC_config()

{

ADC12CTL0 &= (~ADC12ENC); // disable ADC conversion

while(REFCTL0 & REFGENBUSY); // If ref generator busy, WAIT


REFCTL0 |= REFVSEL_0 | REFON; // Select internal ref = AVcc & Internal Reference ON

ADC12MEM0 = 0;

ADC12CTL0 = ADC12SHT0_2 | ADC12ON;

ADC12CTL1 = ADC12SHP; // ADCCLK = MODOSC; sampling timer

ADC12CTL2 |= ADC12RES_2; // conversion results will in 12-bit

ADC12IER0 |= ADC12IE0;

ADC12CTL3 = ADC12TCMAP;

          ADC12MCTL0 = ADC12VRSEL_1 + ADC12INCH_30;

ADC12MCTL0_H |= 0x00;

while(!(REFCTL0 & REFGENRDY)); // Wait for reference generator to settle
ADC12CTL0 |= ADC12ENC | ADC12SC; // Sampling and conversion start

__bis_SR_register(LPM0_bits + GIE) ; // LPM0, ADC10_ISR

}

void start_adc()
{
     do
  {
        ADC12CTL0 |= ADC12ENC | ADC12SC; // Sampling and conversion start
   }while(0);
}

 

uint32_t read_temp(void)
{

     start_adc();

     temperatureDegC = (u32AdcValue- CALADC12_12V_30C) * (85 - 30)) /(CALADC12_12V_85C - CALADC12_12V_30C) + 30;

 return temperatureDegC;

}

 

/*******************************ADC Interrupt(ISR)*****************************/

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = ADC12_VECTOR
__interrupt void ADC12_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(ADC12_VECTOR))) ADC12_ISR (void)
#else
#error Compiler not supported!
#endif
{
switch (__even_in_range(ADC12IV, ADC12IV_ADC12RDYIFG))
{
case ADC12IV_NONE: break; // Vector 0: No interrupt
case ADC12IV_ADC12OVIFG: break; // Vector 2: ADC12MEMx Overflow
case ADC12IV_ADC12TOVIFG: break; // Vector 4: Conversion time overflow
case ADC12IV_ADC12HIIFG: break; // Vector 6: ADC12BHI
case ADC12IV_ADC12LOIFG: break; // Vector 8: ADC12BLO
case ADC12IV_ADC12INIFG: break; // Vector 10: ADC12BIN
case ADC12IV_ADC12IFG0: // Vector 12: ADC12MEM0 Interrupt

/***************Action on ADC********************/
u8adcconversiondone_g=TRUE;


u32AdcValue = ADC12MEM0;

__bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
break; // Clear CPUOFF bit from 0(SR)

case ADC12IV_ADC12RDYIFG: break; // Vector 76: ADC12RDY

default: break;
}
}

Please suggest a solution to my problem.

Thanks In Advance.

  • Hi
    1.Yes , you can refer to the datasheet:www.ti.com/.../msp430fr5872.pdf Table 6-17
    2Temperaturecalibration values are available for use in the TLV descriptors (see the device-specific data sheet for locations) for more information you can refer to the use's guide: www.ti.com/.../slau367o.pdf (34.2.11 Using the Integrated Temperature Sensor)
    3 what's the adc row data you have got in the channel 30?
  • Thanks for your reply.

    Adc raw value is same as the value which I am receiving for ADC channel 12.

  • > ADC12CTL0 = ADC12SHT0_2 | ADC12ON;

    Per SLAU367O section 34.2.11, the temperature sensor requires at least 30usec sampling time, while SHT0=2 (with MODCLK=5MHz) is only about 3usec. Try:

    > ADC12CTL0 = ADC12SHT0_7 | ADC12ON; // sample time 192 MODCLKs (~38us) for temperature sensor.

    Also, read_temp() starts the ADC but doesn't wait for it to complete. Depending on how fast your CPU is running, you may fetch a stale value from u32AdcValue. This probably doesn't matter much if you're only reading from channel 30, but you mentioned switching between channels 12 and 30 (I don't see that code here).
  • Now I have switched off other ADC channels and I have tried with the only temp. sensor channel enabled with the sampling time as suggested above. Now I am receiving raw ADC value around 2560.

    Is this value is correct?

  • > REFCTL0 |= REFVSEL_0 | REFON; // Select internal ref = AVcc & Internal Reference ON
    > ADC12MCTL0 = ADC12VRSEL_1 + ADC12INCH_30;

    REFVSEL=0 (notwithstanding the "|") means VREF=1.2V [SLAU367O Table 33-2]. My calculator says 2560/4096=0.625*1.2V=0.750V. SLAU367O Figure 34-12 says 0.750V is 20C (Typical). Does that sound about right?
  • According to your calculation it should be 20C but if I use this adcraw value in below formula

    "temperatureDegC = (float)(((long)temp - CALADC12_12V_30C) * (85 - 30)) /(CALADC12_12V_85C - CALADC12_12V_30C) + 30.0f;"

    then my value come in range between 30-34 degreeC.

    Even I have tried measuring temperature using Infrared Thermometer.The value shows 25degreeC.
  • My first guess is that you're encountering integer truncation. It would take me some time to quantify from first principles, so a shortcut is: What happens if you change "(85 - 30)" to "(85.0-30.0)"?
  • I don't have a FR5872, so I tried example msp430fr69xx_adc12_10.c on a FR6989 Launchpad, and I get 22C, which is about right for where I am. I notice that that example uses ADC12SHT0_8 (47us at MODCLK=5.4MHz), rather than my guess of SHT0_7.

    The arithmetic looks right -- "long" has higher rank than "unsigned int" so the arithmetic should happen in (signed)long, then float. (Curiously, the FR5994 example uses "float" instead of "long" there.)

    Looking at the expression (and supposing that CAL_85C is always greater than CAL_30C) the only way to get >30C is for your reading to be greater than CAL_30C. What value do you have at 0x1a1a? (I have decimal 2555.)
  • Value at 0x1A1A is 2592.

    Value at 0x1A1C is 3073.

    After disabling off other ADC channels and only enabling ADC temp channel I am getting the correct value.

    Can you guide how to configure multiple ADC channels in continuous mode?

  • Short answer: If you truly want to sample multiple channels Continuously ("as fast as it can"), use CONSEQ=3 [Ref SLAU367O sec 34.2.8.4; there's a lot of information in Fig 34-11].

    I hesitate to recommend CONSEQ=3 since (1) "as fast as it can" is pretty fast for sensing temperature (2) you'll have to code carefully to keep up with the ADC (not much time for the ISR) (3) in my world, no one wants "as fast as it can", rather they want sampling at a fixed (publishable!) rate, which means pacing using a timer.

    In addition to setting CONSEQ=3, you need to set MSC=1, and set  MCTL1 with INCH=<other channel: 12?> and EOS.

    I know of no reason why you shouldn't be able to sample the temperature sensor along with other channels, but I haven't seen how you are (were) combining the two.

    [Edit: Forgot MSC]

**Attention** This is a public forum