oPossum 1,083 Posted April 9, 2012 Share Posted April 9, 2012 [tipdf]SLAU144[/tipdf] chapter 24 describes the calibration data stored as TLV (tag length value) in info segment A. There are ADC values for 30C and 85C for both 1.5V and 2.5V internal reference voltages. These temperature calibration values can be used to improve the accuracy of the internal temperature sensor. There is no explanation of how to do this, so here is how to do it... Before using calibration data it would be a good idea to validate the info segment checksum. The checksum is stored in the first word and is the negative of the XOR of all of the following words. This function will return 0 for a valid checksum. unsigned verify_info_chk(const unsigned * const begin, const unsigned * const end) { const unsigned *p = begin + 1; // Begin at word after checksum unsigned chk = 0; // Init checksum while(p < end) chk ^= *p++; // XOR all words in segment return chk + *begin; // Add checksum - result will be zero if checksum is valid } Each chunk of calibration data in the info segment has a unique tag. This function will search for a specified tag and return a pointer to it. It will return NULL if the tag is not found. void const *find_tag(const unsigned * const begin, const unsigned * const end, const unsigned tag) { const unsigned *p = begin + 1; // Begin at word after checksum do { // const unsigned d = *p++; // Get a word if((d & 0xFF) == tag) return (void *)p; // Return pointer if tag matches p += (d >> 9); // Point to next tag } while(p < end); // While still within segment return 0; // Not found, return NULL pointer } A structure would be handy for using the ADC/temperature cal data... typedef struct { unsigned adc_gain; // ADC gain unsigned adc_offet; // ADC offset unsigned ref15; // ADC value of 1.5 volt input when using 1.5 volt reference unsigned t3015; // ADC value of 30C when using 1.5 volt reference unsigned t8515; // ADC value of 85C when using 1.5 volt reference unsigned ref25; // ADC value of 2.5 volt input when using 2.5 volt reference unsigned t3025; // ADC value of 30C when using 2.5 volt reference unsigned t8525; // ADC value of 85C when using 2.5 volt reference } TCAL; Find tag 0x08 and setup a pointer to the struct... const TCAL * const cal = (TCAL *)find_tag(info_seg_a, info_seg_a_end, 0x08); Now the scale and offset values for the temperature conversion formulas can be calculated... const long cc_scale = ((85L - 30) << 16) / (cal->t8515 - cal->t3015); const long cc_offset = -(cal->t3015 * cc_scale) + (30L << 16) + (1 << 15); const long ck_offset = cc_offset + (273.15 * (1L << 16)); const long cf_scale = ((185L - 86) << 16) / (cal->t8515 - cal->t3015); const long cf_offset = -(cal->t3015 * cf_scale) + (86L << 16) + (1 << 15); Those formulas show the derivation, they can be simplified and combined with basic error handling. The scale and offset values will be zero if the checksum is invalid or the calibration data is not found. const TCAL * const cal = (TCAL *)(verify_info_chk(info_seg_a, info_seg_a_end) \ ? 0 \ : find_tag(info_seg_a, info_seg_a_end, 0x08)); const long cc_scale = cal ? 3604480L / (cal->t8515 - cal->t3015) : 0; const long cf_scale = cal ? 6488064L / (cal->t8515 - cal->t3015) : 0; const long cc_offset = cal ? 1998848L - (cal->t3015 * cc_scale) : 0; const long cf_offset = cal ? 5668864L - (cal->t3015 * cf_scale) : 0; const long ck_offset = cc_offset + 17901158L; In some cases you may want to default to the uncalibrated values... const TCAL * const cal = (TCAL *)(verify_info_chk(info_seg_a, info_seg_a_end) \ ? 0 \ : find_tag(info_seg_a, info_seg_a_end, 0x08)); const long cc_scale = cal ? 3604480L / (cal->t8515 - cal->t3015) : 27069L; const long cf_scale = cal ? 6488064L / (cal->t8515 - cal->t3015) : 48724L; const long cc_offset = cal ? 1998848L - (cal->t3015 * cc_scale) : -18169625L; const long cf_offset = cal ? 5668864L - (cal->t3015 * cf_scale) : -30634388L; const long ck_offset = cc_offset + 17901158L; Now the actual scaled temperature values can be calculated with the usual scale/offset formulas... dcc = ((cc_scale * adc) + cc_offset) >> 16; // C calibrated dkc = ((cc_scale * adc) + ck_offset) >> 16; // K calibrated dfc = ((cf_scale * adc) + cf_offset) >> 16; // F calibrated Code for Nokia 7110 that will show uncalibrated (left) and calibrated (right) temperature in F, C, and K. main.cpp #include #include #include "nokia7110tl.h" using namespace nokia7110; /* P1.0 Reset P1.3 Temp Sensor (Not used) P2.0 Serial Data P2.1 Backlight P2.2 Chip Select P2.3 Data/Command P2.4 Serial Clock P2.5 Button */ // P1 static const unsigned LCD_RESET = BIT0; static const unsigned RXD = BIT2; static const unsigned SWITCH = BIT3; // P2 static const unsigned LCD_DATA = BIT0; static const unsigned LCD_BACKLIGHT = BIT1; static const unsigned LCD_CE = BIT2; static const unsigned LCD_DC = BIT3; static const unsigned LCD_CLK = BIT4; static const unsigned LCD_BTN = BIT5; Nokia7110 lcd; // Print integer from -999 to 9999 using 12 x 16 font void print_int(int i, unsigned x, const unsigned y) { if(i < -999 || i > 9999) return; const unsigned e = x; x += 48; const unsigned neg = i < 0; if(neg) i = -i; div_t d; d.quot = i; do { d = div(d.quot, 10); lcd.pd12(d.rem, x -= 12, y); } while(d.quot); if(neg) lcd.pd12(14, x -= 12, y); while(x > e) lcd.pd12(10, x -= 12, y); } // Print integer from -999 to 9999 using 6 x 8 font void print_int_small(int i, unsigned x, const unsigned y) { if(i < -999 || i > 9999) return; const unsigned e = x; x += 24; const unsigned neg = i < 0; if(neg) i = -i; div_t d; d.quot = i; do { d = div(d.quot, 10); lcd.print(x -= 6, y, '0' + d.rem); } while(d.quot); if(neg) lcd.print(x -= 6, y, '-'); while(x > e) lcd.print(x -= 6, y, ' '); } #pragma vector = ADC10_VECTOR // ADC conversion complete interrupt __interrupt void ADC10_ISR(void) // { // __bic_SR_register_on_exit(LPM0_bits); // Wakeup main code } // unsigned verify_info_chk(const unsigned * const begin, const unsigned * const end) { const unsigned *p = begin + 1; // Begin at word after checksum unsigned chk = 0; // Init checksum while(p < end) chk ^= *p++; // XOR all words in segment return chk + *begin; // Add checksum - result will be zero if checksum is valid } void const *find_tag(const unsigned * const begin, const unsigned * const end, const unsigned tag) { const unsigned *p = begin + 1; // Begin at word after checksum do { // const unsigned d = *p++; // Get a word if((d & 0xFF) == tag) return (void *)p; // Return pointer if tag matches p += (d >> 9); // Point to next tag } while(p < end); // While still within segment return 0; // Not found, return NULL pointer } typedef struct { unsigned adc_gain; // ADC gain unsigned adc_offet; // ADC offset unsigned ref15; // ADC value of 1.5 volt input when using 1.5 volt reference unsigned t3015; // ADC value of 30C when using 1.5 volt reference unsigned t8515; // ADC value of 85C when using 1.5 volt reference unsigned ref25; // ADC value of 2.5 volt input when using 2.5 volt reference unsigned t3025; // ADC value of 30C when using 2.5 volt reference unsigned t8525; // ADC value of 85C when using 2.5 volt reference } TCAL; int main(void) { unsigned adc; int dc, dk, df; // Temperature in degrees C, K, and F int dcc, dkc, dfc; // Calibrated temperatures const unsigned * const info_seg_a = (unsigned *)0x10C0; // Address of info segement A const unsigned * const info_seg_a_end = info_seg_a + 32; // 32 words in each segment WDTCTL = WDTPW | WDTHOLD; P1REN = RXD | SWITCH; P1DIR = LCD_RESET; P1OUT = RXD | SWITCH | LCD_RESET; P2DIR = LCD_DC | LCD_CE | LCD_CLK | LCD_BACKLIGHT | LCD_DATA; P2REN = LCD_BTN; P2OUT = LCD_CLK | LCD_DC | LCD_CE | LCD_BACKLIGHT | LCD_BTN; ADC10CTL0 = 0; // Configure ADC ADC10CTL1 = INCH_10 | ADC10DIV_3; // ADC10CTL0 = SREF_1 | ADC10SHT_3 | REFON | ADC10ON | ADC10IE; ADC10CTL0 |= ADC10IE; // Enable ADC conversion complete interrupt // _EINT(); // Enable interrupts // const TCAL * const cal = (TCAL *)(verify_info_chk(info_seg_a, info_seg_a_end) \ ? 0 \ : find_tag(info_seg_a, info_seg_a_end, 0x08)); const long cc_scale = cal ? 3604480L / (cal->t8515 - cal->t3015) : 0; const long cf_scale = cal ? 6488064L / (cal->t8515 - cal->t3015) : 0; const long cc_offset = cal ? 1998848L - (cal->t3015 * cc_scale) : 0; const long cf_offset = cal ? 5668864L - (cal->t3015 * cf_scale) : 0; const long ck_offset = cc_offset + 17901158L; lcd.reset(); // lcd.init(); // // lcd.clear(); // // for(; { // for-ever ADC10CTL0 |= (ENC | ADC10SC); // Begin ADC conversion __bis_SR_register(LPM0_bits + GIE); // Sleep until conversion complete adc = ADC10MEM; // Read ADC // // Convert to temperature dc = ((27069L * adc) - 18169625L) >> 16; // C dk = ((27069L * adc) - 268467L) >> 16; // K df = ((48724L * adc) - 30634388L) >> 16; // F // dcc = ((cc_scale * adc) + cc_offset) >> 16; // C calibrated dkc = ((cc_scale * adc) + ck_offset) >> 16; // K calibrated dfc = ((cf_scale * adc) + cf_offset) >> 16; // F calibrated // // Display on LCD print_int(df, 0, 0); // Degrees F print_int(dfc, 48, 0); // Degrees F calibrated print_int(dc, 0, 3); // Degrees C print_int(dcc, 48, 3); // Degrees C calibrated print_int(dk, 0, 6); // Degrees K print_int(dkc, 48, 6); // Degrees K calibrated } // return 0; } nokia7110tl.h namespace nokia7110 { unsigned char PNONE; typedef enum { lcd_command = 0, // Array of one or more commands lcd_data = 1, // Array of one or more bytes of data lcd_data_repeat = 2 // One byte of data repeated } lcd_cmd_type; template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> struct Nokia7110 { void write(const unsigned char *cmd, unsigned len, const lcd_cmd_type type = lcd_data); void reset(void); void init(void); void home(void); void pos(unsigned char x, unsigned char y); void clear(unsigned char x = 0); void fill(unsigned x, unsigned y, unsigned w, unsigned h, unsigned char z); void bitmap(const unsigned char *bmp, signed char x, signed char y, unsigned char w, unsigned char h); inline void bitmap(const unsigned char *bmp, signed char x, signed char y) { bitmap(bmp + 2, x, y, bmp[0], bmp[1]); }; void print(char c); inline void print(unsigned char x, unsigned char y, char c) { pos(x, y); print(c); }; void print(const char *s); inline void print(unsigned char x, unsigned char y, const char *s) { pos(x, y); print(s); }; void print(const char *s, unsigned char m); void printv(unsigned char x, unsigned char y, char *s); void pd12(unsigned n, unsigned x, unsigned y); }; template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::write(const unsigned char *cmd, unsigned len, const lcd_cmd_type type) { register unsigned mask; if(&_EP != &PNONE) _EP &= ~_CE; do { mask = 0x0080; do { if(*cmd & mask) { _SP |= _DATA; _SP &= ~_CLK; } else { _SP &= ~(_CLK | _DATA); } _SP |= _CLK; mask >>= 1; } while(!(mask & 1)); if(!type) { if(&_CP == &PNONE) { __delay_cycles(_DC); } else { _CP &= ~_DC; } } if(*cmd & mask) { _SP |= _DATA; _SP &= ~_CLK; } else { _SP &= ~(_CLK | _DATA); } _SP |= _CLK; if(&_CP != &PNONE) _CP |= _DC; if(!(type & 2)) ++cmd; } while(--len); if(&_EP != &PNONE) _EP |= _CE; } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::reset(void) { if(&_RP == &PNONE) { // --- Set initial state of CLK, DC and CE as needed // * = output used for reset if(&_CP == &PNONE) { if(&_EP != &PNONE) { // CLK*, DATA, CE _EP |= _CE; } // else // CLK*, DATA } else { if(&_EP != &PNONE) { // CLK, DATA, DC*, CE if(&_SP == &_EP) { _SP |= (_CLK | _CE); } else { _SP |= _CLK; _EP |= _CE; } } else { // CLK, DATA, DC* _SP |= _CLK; } } // --- Reset pulse on CLK or DC as needed if(&_CP == &PNONE) { // No DC port, use CLK to reset _SP &= ~_CLK; __delay_cycles(_RD); _SP |= _CLK; } else { // Use DC to reset _CP &= ~_DC; __delay_cycles(_RD); _CP |= _DC; } } else { _RP &= ~_RST; if(&_EP != &PNONE) { if(&_SP == &_EP) { _SP |= (_CLK | _CE); } else { _SP |= _CLK; _EP |= _CE; } } else { _SP |= _CLK; } __delay_cycles(_RD); _RP |= _RST; } __delay_cycles(_RD); } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::init(void) { /* static const unsigned char init[] = { 0x20 | 0x01, // Function set - extended instructions enabled //0x80 | 64, // Set vop (contrast) 0 - 127 0x80 | 70, // Higher contrast improves animation 0x04 | 2, // Temperature control 0x10 | 3, // Set bias system 0x20 | 0x00, // Function set - chip active, horizontal addressing, basic instructions 0x08 | 0x04 // Display control - normal mode }; */ static const unsigned char init[] = { 0xA6, //Display: Normal 0xA3, //LCD Bias Settings: 1/7 0xA1, //ADC Selection: Reverse 0xC0, //Common Output: Normal Direction //0xC8, //Common Output: Upside Down 0x22, //Set the V5 output Voltage 0x81, //Set Electronic Volume Register 0x2E, //Power Controller Set // Booster circuit: ON // Voltage regulator circuit: ON // Voltage follower circuit: OFF 0x2F, //Power Controller Set // Voltage follower circuit: ON 0xE3, //Non-OPeration Command 0x40, //Set the start line 0xAF, //LCD On //0xA5, //Display All Points: ON 0xA4, //Display All Points: NORMAL }; write(init, sizeof(init), lcd_command); } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::home(void) { //static const unsigned char home[] = { 0x40, 0x80 }; static const unsigned char home[] = { 0xB0, 0x11, 0x02 }; write(home, sizeof(home), lcd_command); } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::pos(unsigned char x, unsigned char y) { unsigned char c[3]; /*c[0] = 0x80 | x; c[1] = 0x40 | y;*/ x += 18; c[0] = 0xB0 | y; c[1] = 0x10 | (x >> 4); c[2] = x & 0x0F; write(c, sizeof(c), lcd_command); } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::clear(unsigned char x) { #if 0 home(); write(&x, 504, lcd_data_repeat); home(); #else for(unsigned y = 0; y < 9; ++y) { pos(0, y); write(&x, 96, lcd_data_repeat); } #endif } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::fill(unsigned x, unsigned y, unsigned w, unsigned h, unsigned char z) { #if 0 unsigned yy = y + h; unsigned char c[2]; c[0] = 0x80 | x; for(;y < yy; ++y) { c[1] = 0x40 | y; write(c, sizeof(c), lcd_command); write(&z, w, lcd_data_repeat); } #else unsigned yy = y + h; unsigned char c[3]; x += 18; c[1] = 0x10 | (x >> 4); c[2] = (x & 0x0F); for(;y < yy; ++y) { c[0] = 0xB0 | y; write(c, sizeof(c), lcd_command); write(&z, w, lcd_data_repeat); } #endif } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::bitmap(const unsigned char *bmp, signed char x, signed char y, unsigned char w, unsigned char h) { unsigned char c[3]; unsigned char ww; if(x < 0) { ww = w + x; bmp -= x; x = 0; } else if(x + w >= 96) { ww = (96 - x); } else { ww = w; } /*c[0] = 0x80 | x; c[1] = 0x40 | y;*/ x += 18; c[0] = 0xB0 | y; c[1] = 0x10 | (x >> 4); c[2] = x & 0x0F; while(h--) { write(c, sizeof(c), lcd_command); write(bmp, ww); bmp += w; //++c[1]; ++c[0]; } } static const unsigned char font[96][5] = { 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00, 0x00, 0x5F, 0x00, 0x00, // ! 0x00, 0x07, 0x00, 0x07, 0x00, // " 0x14, 0x7F, 0x14, 0x7F, 0x14, // # 0x24, 0x2A, 0x7F, 0x2A, 0x12, // $ 0x23, 0x13, 0x08, 0x64, 0x62, // % 0x36, 0x49, 0x56, 0x20, 0x50, // & 0x00, 0x08, 0x07, 0x03, 0x00, // ' 0x00, 0x1C, 0x22, 0x41, 0x00, // ( 0x00, 0x41, 0x22, 0x1C, 0x00, // ) 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, // * 0x08, 0x08, 0x3E, 0x08, 0x08, // + 0x00, 0x40, 0x38, 0x18, 0x00, // , 0x08, 0x08, 0x08, 0x08, 0x08, // - 0x00, 0x00, 0x60, 0x60, 0x00, // . 0x20, 0x10, 0x08, 0x04, 0x02, // / 0x3E, 0x51, 0x49, 0x45, 0x3E, // 0 0x00, 0x42, 0x7F, 0x40, 0x00, // 1 0x42, 0x61, 0x51, 0x49, 0x46, // 2 0x21, 0x41, 0x49, 0x4D, 0x33, // 3 0x18, 0x14, 0x12, 0x7F, 0x10, // 4 0x27, 0x45, 0x45, 0x45, 0x39, // 5 0x3C, 0x4A, 0x49, 0x49, 0x30, // 6 0x41, 0x21, 0x11, 0x09, 0x07, // 7 0x36, 0x49, 0x49, 0x49, 0x36, // 8 0x06, 0x49, 0x49, 0x29, 0x1E, // 9 0x00, 0x00, 0x14, 0x00, 0x00, // : 0x00, 0x00, 0x40, 0x34, 0x00, // ; 0x00, 0x08, 0x14, 0x22, 0x41, // < 0x14, 0x14, 0x14, 0x14, 0x14, // = 0x00, 0x41, 0x22, 0x14, 0x08, // > 0x02, 0x01, 0x51, 0x09, 0x06, // ? 0x3E, 0x41, 0x5D, 0x59, 0x4E, // @ 0x7C, 0x12, 0x11, 0x12, 0x7C, // A 0x7F, 0x49, 0x49, 0x49, 0x36, // B 0x3E, 0x41, 0x41, 0x41, 0x22, // C 0x7F, 0x41, 0x41, 0x41, 0x3E, // D 0x7F, 0x49, 0x49, 0x49, 0x41, // E 0x7F, 0x09, 0x09, 0x09, 0x01, // F 0x3E, 0x41, 0x49, 0x49, 0x7A, // G 0x7F, 0x08, 0x08, 0x08, 0x7F, // H 0x00, 0x41, 0x7F, 0x41, 0x00, // I 0x20, 0x40, 0x41, 0x3F, 0x01, // J 0x7F, 0x08, 0x14, 0x22, 0x41, // K 0x7F, 0x40, 0x40, 0x40, 0x40, // L 0x7F, 0x02, 0x1C, 0x02, 0x7F, // M 0x7F, 0x04, 0x08, 0x10, 0x7F, // N 0x3E, 0x41, 0x41, 0x41, 0x3E, // O 0x7F, 0x09, 0x09, 0x09, 0x06, // P 0x3E, 0x41, 0x51, 0x21, 0x5E, // Q 0x7F, 0x09, 0x19, 0x29, 0x46, // R 0x26, 0x49, 0x49, 0x49, 0x32, // S 0x01, 0x01, 0x7F, 0x01, 0x01, // T 0x3F, 0x40, 0x40, 0x40, 0x3F, // U 0x1F, 0x20, 0x40, 0x20, 0x1F, // V 0x3F, 0x40, 0x38, 0x40, 0x3F, // W 0x63, 0x14, 0x08, 0x14, 0x63, // X 0x03, 0x04, 0x78, 0x04, 0x03, // Y 0x61, 0x51, 0x49, 0x45, 0x43, // Z 0x00, 0x7F, 0x41, 0x41, 0x41, // [ 0x02, 0x04, 0x08, 0x10, 0x20, // '\' 0x00, 0x41, 0x41, 0x41, 0x7F, // ] 0x04, 0x02, 0x01, 0x02, 0x04, // ^ 0x80, 0x80, 0x80, 0x80, 0x80, // _ 0x00, 0x03, 0x07, 0x08, 0x00, // ' 0x20, 0x54, 0x54, 0x54, 0x78, // a 0x7F, 0x28, 0x44, 0x44, 0x38, // b 0x38, 0x44, 0x44, 0x44, 0x28, // c 0x38, 0x44, 0x44, 0x28, 0x7F, // d 0x38, 0x54, 0x54, 0x54, 0x18, // e 0x00, 0x08, 0x7E, 0x09, 0x02, // f 0x18, 0xA4, 0xA4, 0xA4, 0x7C, // g 0x7F, 0x08, 0x04, 0x04, 0x78, // h 0x00, 0x44, 0x7D, 0x40, 0x00, // i 0x00, 0x20, 0x40, 0x40, 0x3D, // j 0x00, 0x7F, 0x10, 0x28, 0x44, // k 0x00, 0x41, 0x7F, 0x40, 0x00, // l 0x7C, 0x04, 0x78, 0x04, 0x78, // m 0x7C, 0x08, 0x04, 0x04, 0x78, // n 0x38, 0x44, 0x44, 0x44, 0x38, // o 0xFC, 0x18, 0x24, 0x24, 0x18, // p 0x18, 0x24, 0x24, 0x18, 0xFC, // q 0x7C, 0x08, 0x04, 0x04, 0x08, // r 0x48, 0x54, 0x54, 0x54, 0x24, // s 0x04, 0x04, 0x3F, 0x44, 0x24, // t 0x3C, 0x40, 0x40, 0x20, 0x7C, // u 0x1C, 0x20, 0x40, 0x20, 0x1C, // v 0x3C, 0x40, 0x30, 0x40, 0x3C, // w 0x44, 0x28, 0x10, 0x28, 0x44, // x 0x4C, 0x90, 0x90, 0x90, 0x7C, // y 0x44, 0x64, 0x54, 0x4C, 0x44, // z 0x00, 0x08, 0x36, 0x41, 0x00, // { 0x00, 0x00, 0x77, 0x00, 0x00, // | 0x00, 0x41, 0x36, 0x08, 0x00, // } 0x02, 0x01, 0x02, 0x04, 0x02, // ~ 0x00, 0x06, 0x09, 0x09, 0x06, // degrees }; template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::print(char c) { write(&font[c - 32][0], 5); write(&font[0][0], 1); } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::print(const char *s) { while(*s) { write(&font[*s - 32][0], 5); write(&font[0][0], 1); ++s; } } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::print(const char *s, unsigned char m) { unsigned char c; while(*s) { c = font[*s - 32][0] ^ m; write(&c, 1); c = font[*s - 32][1] ^ m; write(&c, 1); c = font[*s - 32][2] ^ m; write(&c, 1); c = font[*s - 32][3] ^ m; write(&c, 1); c = font[*s - 32][4] ^ m; write(&c, 1); write(&m, 1); ++s; } } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::printv(unsigned char x, unsigned char y, char *s) { while(*s) { pos(x, y); ++y; write(&font[*s - 32][0], 5); write(&font[0][0], 1); ++s; } } static const unsigned char num11x16[19][11 * 2] = { 0x00,0xF0,0xFC,0xFE,0x06,0x02,0x06,0xFE,0xFC,0xF0,0x00, // 0 0x00,0x07,0x1F,0x3F,0x30,0x20,0x30,0x3F,0x1F,0x07,0x00, 0x00,0x00,0x08,0x0C,0xFC,0xFE,0xFE,0x00,0x00,0x00,0x00, // 1 0x00,0x20,0x20,0x20,0x3F,0x3F,0x3F,0x20,0x20,0x20,0x00, 0x00,0x0C,0x0E,0x06,0x02,0x02,0x86,0xFE,0x7C,0x38,0x00, // 2 0x00,0x30,0x38,0x3C,0x36,0x33,0x31,0x30,0x30,0x38,0x00, 0x00,0x0C,0x0E,0x86,0x82,0x82,0xC6,0xFE,0x7C,0x38,0x00, // 3 0x00,0x18,0x38,0x30,0x20,0x20,0x31,0x3F,0x1F,0x0E,0x00, 0x00,0x00,0xC0,0x20,0x18,0x04,0xFE,0xFE,0xFE,0x00,0x00, // 4 0x00,0x03,0x02,0x02,0x02,0x22,0x3F,0x3F,0x3F,0x22,0x02, 0x00,0x00,0x7E,0x7E,0x46,0x46,0xC6,0xC6,0x86,0x00,0x00, // 5 0x00,0x18,0x38,0x30,0x20,0x20,0x30,0x3F,0x1F,0x0F,0x00, 0x00,0xC0,0xF0,0xF8,0xFC,0x4C,0xC6,0xC2,0x82,0x00,0x00, // 6 0x00,0x0F,0x1F,0x3F,0x30,0x20,0x30,0x3F,0x1F,0x0F,0x00, 0x00,0x06,0x06,0x06,0x06,0x06,0xC6,0xF6,0x3E,0x0E,0x00, // 7 0x00,0x00,0x00,0x30,0x3C,0x0F,0x03,0x00,0x00,0x00,0x00, 0x00,0x38,0x7C,0xFE,0xC6,0x82,0xC6,0xFE,0x7C,0x38,0x00, // 8 0x00,0x0E,0x1F,0x3F,0x31,0x20,0x31,0x3F,0x1F,0x0E,0x00, 0x00,0x78,0xFC,0xFE,0x86,0x02,0x86,0xFE,0xFC,0xF8,0x00, // 9 0x00,0x00,0x00,0x21,0x21,0x31,0x1D,0x1F,0x0F,0x03,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x70,0x70,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // : 0x00,0x0E,0x0E,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // . 0x00,0x38,0x38,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xC0,0x30,0x0C,0x00,0x00,0x00,0x00, // / 0x00,0x30,0x0C,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, // - 0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x00,0x18,0x3C,0x66,0x66,0x3C,0x18,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xF0,0xF8,0x0C,0x06,0x02,0x02,0x02,0x02,0x0E,0x0C,0x00, // C 0x03,0x07,0x0C,0x18,0x10,0x10,0x10,0x10,0x1C,0x0C,0x00, 0xFE,0xFE,0x42,0x42,0x42,0x42,0x42,0x42,0x00,0x00,0x00, // F 0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xFE,0xFE,0x40,0xE0,0xB0,0x18,0x0C,0x06,0x02,0x00,0x00, // K 0x1F,0x1F,0x00,0x00,0x01,0x03,0x06,0x0C,0x18,0x10,0x00 }; template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::pd12(unsigned n, unsigned x, unsigned y) { pos(x, y); write(num11x16[n], 11, lcd_data); pos(x, ++y); write(num11x16[n] + 11, 11, lcd_data); } } // namespace GeekDoc, xpg, yyrkoon and 9 others 12 Quote Link to post Share on other sites
SugarAddict 227 Posted April 9, 2012 Share Posted April 9, 2012 Most awesome. Quote Link to post Share on other sites
fj604 34 Posted April 10, 2012 Share Posted April 10, 2012 Brilliant. Will try now. Thank you!! [edit] Your code works perfectly. Before calibration: 29C After calibration: 23C My (messy breadboard) talking clock now has a thermometer feature- thanks to you! P.S. "there is no dark side in the moon, really. As a matter of fact it's all dark" Quote Link to post Share on other sites
fj604 34 Posted April 11, 2012 Share Posted April 11, 2012 More info regarding temperature sensor calibration in SLAU208, page 53: http://www.ti.com/lit/ug/slau208j/slau208j.pdf Quote Link to post Share on other sites
oPossum 1,083 Posted April 11, 2012 Author Share Posted April 11, 2012 That's a larger difference that I would expect. Does the calibrated value seem to be closer to correct? Use extreme caution when reading docs for another MSP430 family. They are often very similar, but have some very significant differences. The code in this thread, for example, will not work on F5000/F6000 chips due to differences in the TLV structure and tags. Quote Link to post Share on other sites
fj604 34 Posted April 11, 2012 Share Posted April 11, 2012 That's a larger difference that I would expect. Does the calibrated value seem to be closer to correct? Yes it does - 23 Celcius is normal room temperature. I'll check with Maxim DS1624 though. Use extreme caution when reading docs for another MSP430 family. They are often very similar, but have some very significant differences. The code in this thread, for example, will not work on F5000/F6000 chips due to differences in the TLV structure and tags. Actually SLAU144 has the same formulas for MSP430x2xx - page 597 - 600. http://www.ti.com/lit/ug/slau144i/slau144i.pdf Quote Link to post Share on other sites
kff2 22 Posted April 17, 2012 Share Posted April 17, 2012 Hi oPossum, Thank you for sharing this code and explaining how it works. I couldn't get this to work on a 2553. According to slas735e, page 15, calibration data for ADC10 is at offset 0x10DA, tag 0x10. The checksum for the segment passes, but I don't see any calibration data there. cal->t8515 is 0, and other values don't make any sense either. Could it be that not all chips are calibrated at the factory? Quote Link to post Share on other sites
oPossum 1,083 Posted April 18, 2012 Author Share Posted April 18, 2012 The 0x10 tag is not well documented by TI - it is not in SLAU144. SLAS735 refers to is simply as ADC calibration, but shows temperature calibration in the structure. It may be just for ADC scale/offset calibration and not for temperature calibration. I looked at a few G2553 chips and they did not seem to have valid temperature cal data. The only G series chip that I know has valid temperature calibration is the G2452 - they have tag 0x08. agaelema 1 Quote Link to post Share on other sites
Bloom 0 Posted December 30, 2012 Share Posted December 30, 2012 I also read 0 from CAL_ADC_15T85 field in 2553... :-( Quote Link to post Share on other sites
username 198 Posted May 18, 2013 Share Posted May 18, 2013 Very cool, finally found a project where I could use the internal temp sensor and this is a good reference. ThanksAlso, pretty sweet html in the forloop there =D . First time i've seen C and HTML mesh. I checked my memory and had 0s for all 85 measurements but there was data for the 30C measurements. Going to see if I can work something out linear interpolation. Quote Link to post Share on other sites
lunakid 0 Posted October 25, 2015 Share Posted October 25, 2015 Also, pretty sweet html in the forloop there =D . First time i've seen C and HTML mesh. Hehh, indeed, thanks for pointing it out! ) Quote Link to post Share on other sites
shadowncs 0 Posted July 27, 2017 Share Posted July 27, 2017 Hey I know old thread but... If we read an ADCraw value, using the 1V5 reference (not necessary the temp sensor). Do we first apply 1V5 gain correction, get an ADC1V5raw and then apply ADC gain and offset correction to that value, getting an ADCcorrected value? And if we're dealing with the temp sensor, do we take the ADCcorrected value and apply temp correction to that? Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.