PUBLIC MeasureTemperature // 1 typedef unsigned int uint16_t; // 2 typedef int int16_t; // 3 typedef unsigned char uint8_t; // 4 // 5 #define MINIMUM_ADC_COUNT 220 // 6 #define MAXIMUM_ADC_COUNT 468 // 7 #define SPACING 8 // 8 #define TEMPERATURE_TABLE_NUM_ENTRIES 32 // 9 // 10 //---------------------------------------------------------------------- // 11 // MeasureTemperature // 12 // // 13 // Calculates the temperature in §C given the ADC count by lookup // 14 // table and linear interpolation of the diode circuit characteristic. // 15 // // 16 // Parameters: // 17 // AdcCount Raw ADC count. // 18 // // 19 // Returns: // 20 // Temperature in degC x 10. INVALID_TEMPERATURE if out of range. // 21 //--------------------------------------------------------------------- } SECTION `.text`:CODE:NOROOT(1) THUMB // 22 uint16_t MeasureTemperature(uint16_t AdcCount) // 23 { // 24 uint8_t Index; // 25 uint16_t InterpolationDistance; // 26 uint16_t TempDiff; // 27 uint16_t Temperature; // 28 static const int16_t Table[] = // 29 { // 30 1171, 1116, 1061, 1006, 952, 899, 846, 793, 741, 689, 638, // 31 588, 537, 488, 438, 389, 341, 293, 246, 199, 152, 106, // 32 61, 16, -29, -73, -116, -160, -202, -244, -286, -327 // 33 }; // 34 // 35 // 36 // Index is the index into the table. Each table entry is 8 ADC // 37 // counts higher than the last one, so subtract the offset and // 38 // divide by 8 to find the table index. InterpolationDistance // 39 // is the linear distance between the the table entry ADC count // 40 // and the actual ADC count. // 41 // Check range of AdcCount and saturate index if out of range. // 42 // 43 if (AdcCount < MINIMUM_ADC_COUNT) MeasureTemperature: CMP R0,#+220 BCS.N ??MeasureTemperature_0 // 44 { // 45 // Underflow of ADC - saturate at minimum value // 46 Index = 0; MOVS R1,#+0 B.N ??MeasureTemperature_1 // 47 } // 48 else if (AdcCount > MAXIMUM_ADC_COUNT) ??MeasureTemperature_0: CMP R0,#+468 BLS.N ??MeasureTemperature_2 // 49 { // 50 // Overflow of ADC - saturate at maximum value // 51 Index = TEMPERATURE_TABLE_NUM_ENTRIES - 1; MOVS R1,#+31 B.N ??MeasureTemperature_1 // 52 } // 53 else // 54 { // 55 // Find the index of the table entry just below th e ADC value // 56 Index = (AdcCount - MINIMUM_ADC_COUNT) / SPACING; ??MeasureTemperature_2: SUBS R1,R0,#+220 LSRS R1,R1,#+3 // 57 } // 58 // 59 // Calculate the interpolation between the table entries either side of // 60 // the ADC value. This is the remainder of the difference between the // 61 // ADC count and the minimum temperature ADC count divided by the // 62 // spacing between table entries. Since the spacing is a power of 2, // 63 // this can be achieved by simply masking all but the bottom 3 bits. // 64 // 65 InterpolationDistance = (AdcCount - MINIMUM_ADC_COUNT) & (SPACING - 1); ??MeasureTemperature_1: SUBS R0,R0,#+220 ANDS R0,R0,#0x7 // 66 TempDiff = (Table[Index] - Table[Index+1]); LDR.N R2,??DataTable0 UXTB R1,R1 ;; ZeroExt R1,R1,#+24,#+24 LDR R2,[R2, R1, LSL #+2] LDR.N R3,??DataTable0 UXTB R1,R1 ;; ZeroExt R1,R1,#+24,#+24 ADDS R3,R3,R1, LSL #+2 LDR R3,[R3, #+4] SUBS R2,R2,R3 // 67 // 68 // The temperature is then the base temperature minus the amount // 69 // calculated by linear interpolation. The compiler is clever enough // 70 // to know that dividing by 8 is a right shift of three bits. // 71 Temperature = Table[Index] - ((TempDiff * InterpolationDistance) / SPACING); LDR.N R3,??DataTable0 UXTB R1,R1 ;; ZeroExt R1,R1,#+24,#+24 LDR R1,[R3, R1, LSL #+2] MUL R0,R0,R2 SUBS R0,R1,R0, LSR #+3 // 72 // 73 return Temperature; BX LR ;; return // 74 } SECTION `.text`:CODE:NOROOT(2) SECTION_TYPE SHT_PROGBITS, 0 DATA ??DataTable0: DC32 ??Table SECTION `.rodata`:CONST:REORDER:NOROOT(2) ??Table: DATA DC32 1171, 1116, 1061, 1006, 952, 899, 846, 793, 741, 689, 638, 588 DC32 537, 488, 438, 389, 341, 293, 246, 199, 152, 106, 61, 16, -29, -73 DC32 -116, -160, -202, -244, -286, -327 SECTION `.text`:CODE:NOROOT(1) THUMB END