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.

MSP430F5329: Reading internal Temperature

Part Number: MSP430F5329

Not sure what I am doing wrong. But I am not reading the internal temperature correctly. 

I am using the 2.5V internal reference and the ADC value I get is 1374. 

Looking at the Device Descriptors and
 
adc_ref15_30_temp 2051

 adc_ref15_85_temp 2435

adc_ref20_30_temp 1547

 adc_ref20_85_temp 1837

adc_ref25_30_temp 1230

 adc_ref25_85_temp 1458

At first glance the measurement seems wrong because it is between 30 and 85 degrees. That can not be right because it feels cool to the touch. So I would guess it is closer to 23-25C.

Doing the math

Temp = (ADC - CAL_ADC_T30) * (((85 - 30)  / (CAL_ADC_T85 - CAL_ADC_T30)) + 30

Temp = (1374 - 1230) * (((55 / (1458 - 1230)) + 30 = 64.73 degrees C. 

That cannot be right. I would be very hot to touch. 

My first thought was the internal reference was wrong, or not set up correctly. But I am measuring the 3.3V with the same reference using the built-in voltage divider (Channel 11) and it works as expected. 

I am reading a sequence off ADC values with one start one time. I am reading , Channels 0, 1, 2, 3, 4, 5 6, 10, and 11. Channels 0-6 use the external reference (3.3V) and 10 and 11 use the internal 2.5V reference. Channels 2, 3, 4, and 11 seem to be working perfectly. Channels 0 and 1, are current measurements and I have not started testing the,, and channels 5 and 6 are temperature sensors which I have not calibrated. And that leaves 10 which I thought would be easy to test with no messing with the HW.

I read the ADC every millisecond. I accumulate 8 samples, then flag a routine to process the ADC values outside the interrupt. 

So the ADC interrupt reads the data and moves it to a results array.

The Timer A0 interrupts every millisecond, takes the data from the results array and adds it to an accumulator array, and starts the next ADC sequence. A counter is incremented.
When the counter reaches 8 the accumulator values are moved to new locations, the accumulators and counter to 8 are cleared, and a flag to indicate data is ready is set.

Seems to be O.K. Except for the value received. Any ideas what I am doing wrong? 


static const ADC12_A_configureMemoryParam cCH_I = {ADC12_A_MEMORY_0,
                                            ADC12_A_INPUT_A0,
                                            ADC12_A_VREFPOS_AVCC,
                                            ADC12_A_VREFNEG_AVSS,
                                            ADC12_A_NOTENDOFSEQUENCE};
static const ADC12_A_configureMemoryParam cDCH_I ={ADC12_A_MEMORY_1,
                                            ADC12_A_INPUT_A1,
                                            ADC12_A_VREFPOS_AVCC,
                                            ADC12_A_VREFNEG_AVSS,
                                            ADC12_A_NOTENDOFSEQUENCE};
static const ADC12_A_configureMemoryParam cCH_M2 = {ADC12_A_MEMORY_2,
                                            ADC12_A_INPUT_A2,
                                            ADC12_A_VREFPOS_AVCC,
                                            ADC12_A_VREFNEG_AVSS,
                                            ADC12_A_NOTENDOFSEQUENCE};
static const ADC12_A_configureMemoryParam cCH_M1 = {ADC12_A_MEMORY_3,
                                            ADC12_A_INPUT_A3,
                                            ADC12_A_VREFPOS_AVCC,
                                            ADC12_A_VREFNEG_AVSS,
                                            ADC12_A_NOTENDOFSEQUENCE};
static const ADC12_A_configureMemoryParam cPK_M = {ADC12_A_MEMORY_4,
                                            ADC12_A_INPUT_A4,
                                            ADC12_A_VREFPOS_AVCC,
                                            ADC12_A_VREFNEG_AVSS,
                                            ADC12_A_NOTENDOFSEQUENCE};
static const ADC12_A_configureMemoryParam cTS_4 = {ADC12_A_MEMORY_5,
                                            ADC12_A_INPUT_A5,
                                            ADC12_A_VREFPOS_AVCC,
                                            ADC12_A_VREFNEG_AVSS,
                                            ADC12_A_NOTENDOFSEQUENCE};
static const ADC12_A_configureMemoryParam cTS_5 = {ADC12_A_MEMORY_6,
                                            ADC12_A_INPUT_A6,
                                            ADC12_A_VREFPOS_AVCC,
                                            ADC12_A_VREFNEG_AVSS,
                                            ADC12_A_NOTENDOFSEQUENCE};
static const ADC12_A_configureMemoryParam cTS_Ch = {ADC12_A_MEMORY_7,
                                            ADC12_A_INPUT_TEMPSENSOR, // 10
                                            ADC12_A_VREFPOS_INT,
                                            ADC12_A_VREFNEG_AVSS,
                                            ADC12_A_NOTENDOFSEQUENCE};
static const ADC12_A_configureMemoryParam cV3_3 = {ADC12_A_MEMORY_8,
                                            ADC12_A_INPUT_BATTERYMONITOR, //11 
                                            ADC12_A_VREFPOS_INT,
                                            ADC12_A_VREFNEG_AVSS,
                                            ADC12_A_ENDOFSEQUENCE};



static const ADC12_A_configureMemoryParam cTS_Sleep = {ADC12_A_MEMORY_10,
                                            ADC12_A_INPUT_TEMPSENSOR,
                                            ADC12_A_VREFPOS_INT,
                                            ADC12_A_VREFNEG_AVSS,
                                            ADC12_A_NOTENDOFSEQUENCE};

static const ADC12_A_configureMemoryParam cV_cal = {ADC12_A_MEMORY_11,
                                            ADC12_A_INPUT_BATTERYMONITOR, // 11
                                            ADC12_A_VREFPOS_INT,
                                            ADC12_A_VREFNEG_AVSS,
                                            ADC12_A_NOTENDOFSEQUENCE};


void ADC_Configuration(void)
{
  // initialize data
  ADC_Data[0] = 0;
  ADC_Data[1] = 0;
  ADC_Data[2] = 0;
  ADC_Data[3] = 0;
  ADC_Data[4] = 0;
  ADC_Data[5] = 0;
  ADC_Data[6] = 0;
  ADC_Data[7] = 0;
  ADC_Data[8] = 0;
  ADC_Data_Counter = 0;
  
  
  // Make sure HW is set right
  P6SEL = 0x7F;                               // Enable A/D channel inputs
  
  ADC12_A_disableConversions(ADC12_A_BASE,true);
  ADC12_A_disable(ADC12_A_BASE); // Disable while we configure it. 
  
  // Initialize the reference to 2.5V
  Ref_setReferenceVoltage(REF_BASE, REF_VREF2_5V);
  // Enable chip temperature sensor
  Ref_enableTempSensor(REF_BASE);
  REFCTL0 |= 1; // Force it on to see if it is different. 
  
  //Initialize the ADC12_A Module
  /*
  * Base Address of ADC12_A Module
  * Use internal ADC12_A bit as sample/hold signal to start conversion
  * USE MCLK as clock source
  * Use default clock divider of 1
  */
  ADC12_A_init(ADC12_A_BASE,
               ADC12_A_SAMPLEHOLDSOURCE_SC,
               ADC12_A_CLOCKSOURCE_ADC12OSC,
               ADC12_A_CLOCKDIVIDER_1);
  
  // 12-bits
  ADC12_A_setResolution(ADC12_A_BASE,ADC12_A_RESOLUTION_12BIT);
  
  /*
  * Base Address of ADC12_A Module
  * For memory buffers 0-7 sample/hold for 768 clock cycles
  * For memory buffers 8-15 sample/hold for 4 clock cycles (default)
  * Disable Multiple Sampling
  * Right now I am thinking we will measure everything including the chip 
  * temperature and the 3.3V rail to see how it changes during operation.   
  *
  * Note: ADC12_A may have a minimum sample rate of 30us or 100us.
  * This example uses a sample time of ~154us to ensure it works.
  * 256 cycles (51.2us) or 512 cycles (100.4us) may be used, but
  * resulting readings may be less accurate.
  *
  * Sampling time is > (Rs + 1800 Ohms) * ln(2^(n+1) * 25 pF  + 800 ns
  *
  * For Charge_mon1 and Charge_mon2 and pack+mon that means 2.005 uS. with maximum 
  * 5.4 MHz 4 clocks are .74 us too small, or 8 clocks is 1.48 us too small, 
  * 16 is 2.96 us which is enough. 
  * So we could do 337 samples in 1 ms. 
  * 32 is 5.9 us which is about 168 in 1 us. 
  * 64 is 11us which is about 84 in 1us best case 0r worst case at 4.2 MHz
  * is 15.23 us which is about 65 samples in 1 ms. It gives us lots of margin
  * for the data to settle and for the ADC to complete the operations in plenty 
  * of time for the 1 ms timer interrupt to process it.  
  */
  ADC12_A_setupSamplingTimer(ADC12_A_BASE,
                             ADC12_A_CYCLEHOLD_64_CYCLES, // Low 0-7 Memory
                             ADC12_A_CYCLEHOLD_64_CYCLES, // high 8-15 Memory
                             ADC12_A_MULTIPLESAMPLESENABLE); // O.K. 
  
  ADC12_A_enableReferenceBurst(ADC12_A_BASE);
  
  //Configure Memory Buffer
  /*
  * Base Addres of ADC12_A Module
  * Configure memory buffer 0
  * Map temp sensor to memory buffer 0
  * Vref+ = Vref+ (int) 2.5V
  * Vref- = AVss
  * Memory buffer 0 is not the end of a sequence
  */
  
  ADC12_A_configureMemory(ADC12_A_BASE ,(ADC12_A_configureMemoryParam *)&cCH_I); // 0x00
  ADC12_A_configureMemory(ADC12_A_BASE ,(ADC12_A_configureMemoryParam *)&cDCH_I); // 0x01
  ADC12_A_configureMemory(ADC12_A_BASE ,(ADC12_A_configureMemoryParam *)&cCH_M2); // 0x02
  ADC12_A_configureMemory(ADC12_A_BASE ,(ADC12_A_configureMemoryParam *)&cCH_M1); // 0x03
  ADC12_A_configureMemory(ADC12_A_BASE ,(ADC12_A_configureMemoryParam *)&cPK_M);  // 0x04
  ADC12_A_configureMemory(ADC12_A_BASE ,(ADC12_A_configureMemoryParam *)&cTS_4);  // 0x05
  ADC12_A_configureMemory(ADC12_A_BASE ,(ADC12_A_configureMemoryParam *)&cTS_5);  // 0x06
  ADC12_A_configureMemory(ADC12_A_BASE ,(ADC12_A_configureMemoryParam *)&cTS_Ch); // 0x1A
  ADC12_A_configureMemory(ADC12_A_BASE ,(ADC12_A_configureMemoryParam *)&cV3_3);  // 0x9B
  
  // This interrupt is used by SLEEP State Do not want it active in this mode
  ADC12_A_disableInterrupt(ADC12_A_BASE,
                           ADC12IFG10);
  
  
  ADC12_A_clearInterrupt(ADC12_A_BASE,
                         ADC12IFG8);
  
  ADC12_A_enableInterrupt(ADC12_A_BASE,
                          ADC12IE8);
  
  
  ADC12_A_enable(ADC12_A_BASE);
  
  ADC12_A_startConversion(ADC12_A_BASE,ADC12_A_MEMORY_0,ADC12_A_SEQOFCHANNELS);
}


#pragma vector=ADC12_VECTOR
__interrupt void ADC12ISR (void)
{
 
  uint16_t temp = ADC12IV;
  add_trace_buf(105);
  __no_operation();
  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  6:                                  //Vector  6:  ADC12IFG0
    //Move results, IFG is cleared
    //temperature_sensor_ADC = ADC12_A_getResults(ADC12_A_BASE,ADC12_A_MEMORY_0); 
    //Exit active CPU
    //__bic_SR_register_on_exit(LPM3_bits);
    break;
  case  8: break;                           // Vector  8:  ADC12IFG1
  case 10: break;                           // Vector 10:  ADC12IFG2
  case 12:                                  // Vector 12:  ADC12IFG3 not used? 
    results[0] = ADC12MEM0;                 // Move results, IFG is cleared
    results[1] = ADC12MEM1;                 // Move results, IFG is cleared
    results[2] = ADC12MEM2;                 // Move results, IFG is cleared
    results[3] = ADC12MEM3;                 // Move results, IFG is cleared
    break;
    
    //  LPM0_EXIT;   // Exit active CPU, SET BREAKPOINT HERE  
  case 14: break;                           // Vector 14:  ADC12IFG4
  
  case 16:                                  // Vector 16:  ADC12IFG5 // Not used? 
    results[0] = ADC12MEM0;                 // Move results, IFG is cleared
    results[1] = ADC12MEM1;                 // Move results, IFG is cleared
    results[2] = ADC12MEM2;                 // Move results, IFG is cleared
    results[3] = ADC12MEM3;                 // Move results, IFG is cleared
    results[4] = ADC12MEM4;                 // Move results, IFG is cleared
    results[5] = ADC12MEM5;                 // Move results, IFG is cleared 
    // P1OUT ^= BIT2;
    
  case 18:                                  // Vector 18:  ADC12IFG6 Not used? 
    results[0] = ADC12MEM0;                 // Move results, IFG is cleared
    results[1] = ADC12MEM1;                 // Move results, IFG is cleared
    results[2] = ADC12MEM2;                 // Move results, IFG is cleared
    results[3] = ADC12MEM3;                 // Move results, IFG is cleared
    results[4] = ADC12MEM4;                 // Move results, IFG is cleared
    results[5] = ADC12MEM5;                 // Move results, IFG is cleared
    results[6] = ADC12MEM6;                 // Move results, IFG is cleared
    LED1_Off;
    break;
    
  case 20: break;                           // Vector 20:  ADC12IFG7
  
  case 22:                                  // Vector 22:  ADC12IFG8
    // this is cirrent interrupt for all states but Sleep.
    adc_data_ready = true;   // for checking
    ADC_interrupt_counter++; // for debugging
    results[0] = ADC12MEM0;                 // Move results, IFG is cleared
    results[1] = ADC12MEM1;                 // Move results, IFG is cleared
    results[2] = ADC12MEM2;                 // Move results, IFG is cleared
    results[3] = ADC12MEM3;                 // Move results, IFG is cleared
    results[4] = ADC12MEM4;                 // Move results, IFG is cleared
    results[5] = ADC12MEM5;                 // Move results, IFG is cleared
    results[6] = ADC12MEM6;                 // Move results, IFG is cleared
    results[7] = ADC12MEM7;                 // Move results, IFG is cleared
    results[8] = ADC12MEM8;                 // Move results, IFG is cleared
    break;                                  
    
  case 24: break;                           // Vector 24:  ADC12IFG9
  case 26:                                  // Vector 26:  ADC12IFG10
    // This is interrupt for Sleep State
    add_trace_buf(99);
    temperature_sensor_ADC = ADC12MEM10;
    
    // we do this only in sleep mode. We have not gotten to LPM3 mode 
    // when this interrupt fires. 
    break;
  case 28:                                  // Vector 28:  ADC12IFG11
   add_trace_buf(98); // Used in calibration of V3_3. 
   {  
     uint16_t x;   // to fix compiler warning about order of volatile evaluation
     x = ADC12MEM10;
     AVcc_ADC[AVcc_ADC_count] = x;
   }
   AVcc_ADC_count++;
   break;
  case 30: break;                           // Vector 30:  ADC12IFG12
  case 32: break;                           // Vector 32:  ADC12IFG13
  case 34: break;                           // Vector 34:  ADC12IFG14
  default: break; 
  }
  
}

// Since Timer A0 and the ADC interrupt are so closely tied together I will 
// put them in the same file. Normally they would be separate


//------------------------------------------------------------------------------
// This interrupt executes every millisecond. 
// Timer A0 interrupt service routine
#pragma vector=TIMER0_A0_VECTOR
__interrupt void TIMER0_A0_ISR(void)
{
  
  //add_trace_buf(101);
  LED1_ON;
  ADC_Data[0] += results[0];                 // Move results, IFG is cleared
  ADC_Data[1] += results[1];               // Move results, IFG is cleared
  ADC_Data[2] += results[2];                 // Move results, IFG is cleared
  ADC_Data[3] += results[3];                 // Move results, IFG is cleared
  ADC_Data[4] += results[4];                 // Move results, IFG is cleared
  ADC_Data[5] += results[5];                // Move results, IFG is cleared
  ADC_Data[6] += results[6];                 // Move results, IFG is cleared
  ADC_Data[7] += results[7];                 // Move results, IFG is cleared
  ADC_Data[8] += results[8];                 // Move results, IFG is cleared
  
// When ADC12SC triggers a sequence, successive sequences can be triggered by 
// the ADC12SC bit. The ADC12SC must be cleared by software after each sequence 
// to trigger another sequence. When any other trigger source is used, ADC12ENC 
// must be toggled between each sequence.
  
// Do we need to turn off and on? Or do we just need to bring ADC12SC low?   
  ADC12CTL0 &= ~ADC12MSC; // Turn off ADC12
  ADC12CTL0 |= ADC12MSC;  // Turn on ADC12
  
  ADC12CTL0 &= ~ADC12SC;
  ADC12CTL0 |= ADC12SC;    // Start convn - software trigger Conversion time 580uS
  
  Timer_interrupt_counter++; // For Debugging to see if we ever lose sequence. 
  ADC_Data_Counter++;
  if (adc_data_ready == false) data_not_ready_error_count++; // Should never happen. For debugging 
  adc_data_ready = false; 
  
  if(ADC_Data_Counter == 8) // Averages 8 reads 
  {
    adc_chg_current8 = ADC_Data[0]; // Start integrating a version that uses all the bits. 
    adc_dsch_current8 = ADC_Data[1];
    adc_charge_mon28 = ADC_Data[2];
    adc_charge_mon18 = ADC_Data[3];
    adc_packv8 = ADC_Data[4];
    adc_ts48 = ADC_Data[5];
    adc_ts58 = ADC_Data[6];
    adc_tschip8 = ADC_Data[7];
    adc_v3_38 = ADC_Data[8];
    adc_new_data_available = true;
    ADC_Data_Counter = 0;
  
    ADC_Data[0] = 0;
    ADC_Data[1] = 0;
    ADC_Data[2] = 0;
    ADC_Data[3] = 0;
    ADC_Data[4] = 0;
    ADC_Data[5] = 0;
    ADC_Data[6] = 0;
    ADC_Data[7] = 0;
    ADC_Data[8] = 0;
     
    ADC_Sample_Counter++;
  }
  
  // Other timing functions based on 1 ms. 

  if(Time_mS_counter != 0) Time_mS_counter--;        // used for 1ms delay function
  if(bq34_CE_Read_ENABLE > 0) bq34_CE_Read_ENABLE--; // used at power up and coming out of sleep
  if(bq769x_Read_ENABLE  > 0) bq769x_Read_ENABLE--;  // used at power up and coming out of sleep
  if(System_Ready  > 0) System_Ready--;              // used at power up and coming out of sleep
  
  if(Time_to_Read_Data_Counter_mS != 0) Time_to_Read_Data_Counter_mS--;
  else
  {    
    Time_to_Read_Data_Counter_mS = 333;     
    {
      si.Ready_Flags.TTRD = true;        //Time_to_Read_Data = TRUE;
      LPM3_EXIT;    
    }
  }  
  LED1_Off;// 100us
}

void init_REF_calvalues(void)
{
  TLV_getInfo(TLV_TAG_REFCAL, 0, &bREFCAL_bytes, (uint16_t **)&pREFCAL);
}


// Put Ref in known state
void Ref_Init(void)
{
  // Must do this before setting up the ADC. 
  ADC12_A_disable(ADC12_A_BASE);
  ADC12_A_disable(ADC12_A_BASE);
  ADC12_A_clearInterrupt(ADC12_A_BASE,0xFF);
  //DAC12_A_disable(ADC12_A_BASE,DAC12_A_SUBMODULE_1);
  
  Ref_disableReferenceVoltage(REF_BASE); 
  while (Ref_isRefGenBusy(REF_BASE));
  Ref_setReferenceVoltage(REF_BASE,REF_VREF2_5V);
  Ref_disableTempSensor(REF_BASE);
  Ref_disableReferenceVoltageOutput(REF_BASE);
  Ref_disableReferenceVoltage(REF_BASE);
}


 

**Attention** This is a public forum