6.2 Measuring Temperature
The code snippet below shows how to measure temperature using the internal
temperature
sensor.
#define F_CPU 3333333ul #include <avr/io.h> #include <math.h> #include <util/delay.h> #define TIMEBASE_VALUE ((uint8_t) ceil(F_CPU*0.000001)) #define TEMPSENSE_SAMPDUR ((uint8_t) ceil(F_CPU*0.000032/2)) /* SAMPDUR for TEMPSENSE must be >= 32 µs * f_ADC ~= 32 µs * 1.67 MHz ~= 54 */ /* Volatile variables to improve debug experience */ static volatile uint16_t adc_reading; static volatile uint16_t temperature_in_K; static volatile int16_t temperature_in_degC; /********************************************************************************* ADC initialization **********************************************************************************/ void adc_init() { ADC0.CTRLA = ADC_ENABLE_bm; ADC0.CTRLB = ADC_PRESC_DIV2_gc; /* fCLK_ADC = 3.333333/2 MHz */ ADC0.CTRLC = ADC_REFSEL_1024MV_gc | (TIMEBASE_VALUE << ADC_TIMEBASE_gp); ADC0.CTRLE = TEMPSENSE_SAMPDUR; ADC0.MUXPOS = ADC_MUXPOS_TEMPSENSE_gc; /* ADC Internal Temperature Sensor */ ADC0.COMMAND = ADC_MODE_SINGLE_12BIT_gc; /* Single 12-bit mode */ } int main(void) { adc_init(); int8_t sigrow_offset = SIGROW.TEMPSENSE1; /* Read signed offset from signature row */ uint8_t sigrow_gain = SIGROW.TEMPSENSE0; /* Read unsigned gain/slope from signature row */ while(1) { ADC0.COMMAND |= ADC_START_IMMEDIATE_gc; /* Start ADC conversion */ while(!(ADC0.INTFLAGS & ADC_RESRDY_bm)); /* Wait until conversion is done */ /* Calibration compensation as explained in the data sheet */ adc_reading = ADC0.RESULT >> 2; /* 10-bit MSb of ADC result with 1.024V internal reference */ uint32_t temp = adc_reading - sigrow_offset; temp *= sigrow_gain; /* Result might overflow 16-bit variable (10-bit + 8-bit) */ temp += 0x80; /* Add 256/2 to get correct integer rounding on division below */ temp >>= 8; /* Divide result by 256 to get processed temperature in Kelvin */ temperature_in_K = temp; temperature_in_degC = temperature_in_K - 273; _delay_ms(500); } }