Jump to content
43oh

oPossum

Members
  • Content Count

    925
  • Joined

  • Last visited

  • Days Won

    103

Reputation Activity

  1. Like
    oPossum got a reaction from LeoLiu in Volt/Amp/Watt meter   
    This is a simple voltage and current meter that uses the TI INA219 chip. Voltage measurement range is 0 to 26 volts with 4 mV resolution and current measurement range is -4 to +4 amps with 1 mV resolution (when using a 0.01 ohm shunt). The specs are inferior to a pair of quality multimeters, but it is a fraction of the price and shows wattage in addition to voltage and current. The Nokia 5110 display is used so the firmware could be enhanced to do simple graphing. Sending the measurements to a computer could also be done.
     
    Using the INA219 makes for a very simple circuit.

     
    The normal display is three lines with voltage, amperage and wattage.

     
    Pressing the P1.3 switch will show the 6 registers in the INA219 in hex and signed decimal.

     
    The code is written in C++ and uses templates for the LCD, IIC and INA219. Software SPI and IIC is used for maximum portability.
    vam.zip
  2. Like
    oPossum got a reaction from keithehenry in G2553 Hardware UART "Hello World" Example   
    #include <msp430.h> #include <stdint.h> const unsigned RXD = BIT1; const unsigned TXD = BIT2; const unsigned SW2 = BIT3; const unsigned long smclk_freq = 16000000; // SMCLK frequency in hertz const unsigned long bps = 9600; // Async serial bit rate // Output char to UART static inline void putc(const unsigned c) { while(UCA0STAT & UCBUSY); UCA0TXBUF = c; } // Output string to UART void puts(const char *s) { while(*s) putc(*s++); } // CR LF void crlf(void) { puts("\r\n"); } // Output binary array to UART void putb(const uint8_t *b, unsigned n) { do putc(*b++); while(--n); } // Print unsigned int void print_u(unsigned x) {     static const unsigned dd[] = { 10000, 1000, 100, 10, 1 };     const unsigned *dp = dd; unsigned d;     if(x) { while(x < *dp) ++dp;         do { d = *dp++; char c = '0'; while(x >= d) ++c, x -= d; putc(c); } while(!(d & 1));     } else putc('0'); } // Print signed int void print_i(const int x) { if(x < 0) putc('-'); print_u((x < 0) ? -x : x); } // Print hex nibble static inline void puth(const unsigned x) { putc("0123456789ABCDEF"[x & 15]); } // Print hex byte void print_hb(const unsigned x) { puth(x >> 4); puth(x); } // Print hex word void print_hw(const unsigned x) { print_hb(x >> 8); print_hb(x); } void main(void) { WDTCTL = WDTPW + WDTHOLD; // No watchdog reset // DCOCTL = 0; // Run at 16 MHz BCSCTL1 = CALBC1_16MHZ; // DCOCTL = CALDCO_16MHZ; // // P1DIR = ~(RXD | SW2); // Setup I/O for UART and switch P1OUT = P1REN = RXD | SW2; // P1SEL = P1SEL2 = RXD | TXD; // // const unsigned long brd = (smclk_freq + (bps >> 1)) / bps; // Bit rate divisor UCA0CTL1 = UCSWRST; // Hold USCI in reset to allow configuration UCA0CTL0 = 0; // No parity, LSB first, 8 bits, one stop bit, UART (async) UCA0BR1 = (brd >> 12) & 0xFF; // High byte of whole divisor UCA0BR0 = (brd >> 4) & 0xFF; // Low byte of whole divisor UCA0MCTL = ((brd << 4) & 0xF0) | UCOS16; // Fractional divisor, oversampling mode UCA0CTL1 = UCSSEL_2; // Use SMCLK for bit rate generator, release reset for(; { // int n = 1; // do (P1IN & BIT3) ? --n : (n = 5000); while(n); do (P1IN & BIT3) ? n = 5000 : --n; while(n); puts("Poke me with a Stick\r\n"); // for(n = -5; n <= 5;) print_i(n++), putc(' '); crlf(); n = 0xDEAD; print_hw(n); putc(' '); // n += 0xE042; print_hw(n); crlf(); // crlf(); // } // } //  
  3. Like
    oPossum got a reaction from agaelema in How to use temperature calibration data   
    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.
  4. Like
    oPossum got a reaction from agaelema in How to use temperature calibration data   
    [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
  5. Like
    oPossum reacted to Fmilburn in Products using MSP430   
    It is interesting that you posted this as I recently gave some thought to building one of these. TI has a number of reference articles about them, e.g. http://www.ti.com/tool/TIDA-00311
  6. Like
    oPossum reacted to chicken in Products using MSP430   
    A MSP430F415 in a cheap fingertip oximeter from AliExpress


     
    Teardown here: http://www.kean.com.au/oshw/oximeter/
     
    I wonder if that nicely labeled JTAG header is still functional.

     
    With 16K Flash and 512 bytes of RAM, this MCU is comparable to the MSP430G2553. Energia on an oximeter anyone?
     
    Addendum 2/28: I ordered an identical looking model off AliExpress. Unfortunately, it's no longer MSP430 inside :-( It's now powered by a STM32F030 ARM M0.
  7. Like
    oPossum reacted to zeke in Open Source Books that teach C Programming   
    I stumbled across a list of nine open source books on Hacker News today that will help people learn how to program in C.
     
    YMMV
  8. Like
    oPossum reacted to michanisani in TM4c1294 - Program over Ethernet   
    1.
    Run program eflash.exe with the following parameters:
    This program downloads a file to a remote device, using the Ethernet Boot Loader.
    Open windows CMD
    eflash -i <IP address>  -m <MAC address>  <file_to_program.bin>
     
    IP address foirmat: XXX.XXX.XXX.XXX
    MAC address format example: 00.1A.B6.03.0F.0C
     
    2.
    Jump in your TM4C1294 board to the boot loader
     
    void UpgradeSoftware(void)     {    uint32_t *Reg_OPA_REG_1;       // Disable all processor interrupts.  Instead of disabling them     // one at a time (and possibly missing an interrupt if new sources     // are added), a direct write to NVIC is done to disable all     // peripheral interrupts.     HWREG(NVIC_DIS0) = 0xffffffff;     HWREG(NVIC_DIS1) = 0xffffffff;     HWREG(NVIC_DIS2) = 0xffffffff;     HWREG(NVIC_DIS3) = 0xffffffff;     HWREG(NVIC_DIS4) = 0xffffffff;       // Also disable the SysTick interrupt.     SysTickIntDisable();     SysTickDisable();         // Return control to the boot loader.  This is a call to the SVC     // handler in the flashed-based boot loader, or to the ROM if configured.       ROM_UpdateEMAC(g_ui32SysClock);       }   3. How to find your board MAC addressUsing LM Flash programmer connected to USB port of CPU card
     
    Or
     
    void read_mac_address()   {     uint32_t ui32User0, ui32User1;     uint8_t pui8MAC[6];       // Get the MAC address from the user registers.     MAP_FlashUserGet(&ui32User0, &ui32User1);     // Convert the 24/24 split MAC address from NV ram into a 32/16 split MAC     // address needed to program the hardware registers, then program the MAC     // address into the Ethernet Controller registers.     pui8MAC[0] = ((ui32User0 >>  0) & 0xff);     pui8MAC[1] = ((ui32User0 >>  8) & 0xff);     pui8MAC[2] = ((ui32User0 >> 16) & 0xff);     pui8MAC[3] = ((ui32User1 >>  0) & 0xff);     pui8MAC[4] = ((ui32User1 >>  8) & 0xff);     pui8MAC[5] = ((ui32User1 >> 16) & 0xff);       sprintf(Str, "MAC address= %02x-%02x-%02x-%02x-%02x-%02x\n",pui8MAC[0],pui8MAC[1],pui8MAC[2],pui8MAC[3],pui8MAC[4],pui8MAC[5]);     UARTprintf(Str);   }    
     
     
    4.
    https://github.com/kroesche/stellaris_eflash
     
     
     

     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     bootp_server.c
    bootp_server.h
    eflash.c
    eflash.h
    SW_update by Enternet.rar
  9. Like
    oPossum reacted to zborgerd in MSP-FET Backchannel UART.   
    Just got my half-price MSP-FET in the mail today.  MSP-FET Backchannel UART support was added in MSP Debug Stack 3.4.1.0.  The firmware version and driver versions match this on my system.
     
    I default my terminal (Linux) to 9600 bps and this is normally fine with the FR5969 and F5529 Launchpad built-in EZ-FET.  However, when I use the MSP-FET on the 5969 LP, I have to bump the speed of the port up to something higher and back down to 9600 before data begins to pass correctly.  Has anyone else observed this?
     
    Again, the EZ-FET on the same FR5969 LP is fine.  When I switch to the JTAG header with the MSP-FET, the behavior is different.
     
    There seem to be some differences in the UART behavior on the EZ-FET vs the MSP-FET.
  10. Like
    oPossum reacted to Bubele in MSP-FET Backchannel UART.   
    Hello zborgerd,
     
    even this thread was never answered and is a bit old.
     
    I was close to give up on a MSP2553 on a bredboard and using the MSP-FET with uart backchannel @ 9600.
    It never worked for no reason, even connecting ping 14 and 12 directly.
    found your topic and indeed, switching to 115200, it magically works.
    not to bad switching the MCU to 115200, however, one may get some grey hairs not knowing about this "bug?".
     
    ps: i used ccs 7.0.0 on linux.
     
    best regards
    Peter ;-)
  11. Like
    oPossum got a reaction from piranha32 in msp430-g++ and interrupts   
    There are 5 vectors in that table
  12. Like
    oPossum reacted to chicken in Generate 1 pulse per second using MSP430   
    You could do that. But with your simple task, it is probably easier to use an interrupt.
     
    The most common approach for simple pin wiggling based on the timer is to setup a timer interrupt that fires every millisecond and maintaining a millisecond counter.
     
    Main:
     
    - set a millisecond counter variable to 0
    - setup timer to up mode, divide clock by 8, etc. (TA0CTL)
    - set compare register to 1600, so that the timer interrupt occurs 1000 times per second (12.8M / 8 / 1600 = 1000) (TA0CCR0)
    - enable timer interrupt
    - go into endless loop
     
    Inside the interrupt:
     
    - increase millisecond counter variable
    - if it reaches 1000, 1 second passed
    -- reset your millisecond counter to 0
    -- do your thing depending on state of input pin
     
    See MSP430 family guide chapter 17.2 through 17.2.3.1.1
    http://www.ti.com/lit/ug/slau208p/slau208p.pdf
     
    Here's a very similar example. Note that the timer registers may have slightly different names as it's for a different MCU.
    http://www.crash-bang.com/getting-started-msp430-timers-3/
     
    PS: You only need to include msp430.h. Together with the MCU selection in the CCS project, it will take care to include the correct files.
  13. Like
    oPossum reacted to nonsuchpro in msp430-g++: error   
    Hi all.
    Newb here. I just picked up (5) MSP-EXP430F5529LP's on a whim while placing an order for Arduino swag.
    MCM is blowing them out at $4 a piece so I figured I have nothing to lose and will enjoy the new experience.
    Of course, I'm running into issues. Most of the tutorials on Energia are for older versions and have a few different options.
    Anyway, I am just starting out with these boards and I believe I have downloaded and installed all necessary drivers and software.
    Energia sees the Launchpad and gives me the 2 com ports as it should. I open the "Blink" example sketch, click Upload, and this what I get.
     
    Energia: 1.6.10E18 (Windows 10), Board: "MSP-EXP430F5529LP" Rev 1.6 msp430-g++: error: Files: No such file or directory msp430-g++: error: (x86)\energia-1.6.10E18\hardware\tools\msp430/include: No such file or directory exit status 1 Error compiling for board MSP-EXP430F5529LP. The folder "include" does exist in that location and it does contain files. So I'm at a loss.
    Also, I don't understand why there is a forward slash (/) in between msp430 and include and not a back slash (\) in the error msg, not that it has anything to do with the error.
     
    Any help will be appreciated.
    Thanks!

  14. Like
    oPossum reacted to lsm in V7 embedded JavaScript engine is ported to MSP432   
    We are the creators of the smallest embedded JavaScript engine - V7 (https://github.com/cesanta/v7). It allows to export existing C/C++ functionality into the JS environment and express device logic in the JS script - easily updatable, unlike monolithic firmware.

     

    Here it is - with examples for CCS: https://github.com/cesanta/v7/tree/master/examples/TI/MSP432

     

    We are looking for feeback and requests for ports to other devices.

  15. Like
    oPossum got a reaction from timg11 in Is there a "breakout board" for MSP340?   
    http://forum.43oh.com/topic/2482-3-way-50x50mm-proto-board/
     
     
    http://forum.43oh.com/topic/2481-launchpad-mini-revision-3/
  16. Like
    oPossum got a reaction from timg11 in 3 way 50x50mm proto board   
    This can be used as...
    - Prototype booster
    - Stand alone MSP430 dev board
    - MSP430 dev board with booster
     
    The LEDs are 0603, bypass cap 0805, all other 0402.
    Pilot holes for mounting holes.
     

    lp_mini_proto_plus.sch
    lp_mini_proto_plus.brd
  17. Like
    oPossum got a reaction from jazz in Comprehensive DCO calibration   
    The G series MSP430 have 1 or 4 factory calibrations for the DCO stored in info segment A. This firmware will store 96 DCO calibrations in info segments B, C, and D. After these calibrations have been stored it is possible to set the DCO to any frequency from 125 kHz to 16 MHz (128:1 range) with a simple function call...
     
    set_dco.c

    #include static const unsigned * const InfoSegA = (unsigned *)0x10C0; static const unsigned * const InfoSegD = (unsigned *)0x1000; int set_dco(const unsigned f) // Set DCO to specified frequency in kHz { // unsigned i; // unsigned rsel = 0; // Init rsel/dco unsigned dco = 0x20; // const unsigned *cal = InfoSegD; // Begin at info segment D do { // if(f >= cal[0] && f < cal[1]) { // Frequency in range? i = cal[1] - cal[0]; // Interpolate for MODx dco += ((((f - cal[0]) * 0x20) + (i >> 1)) / i); DCOCTL = dco; // Set the DCO/MOD BCSCTL1 = rsel; // and RSEL return 0; // Return success } // if((dco += 0x20) == 0xC0) // Next DCO/RSEL dco = 0x20, ++rsel, ++cal; // } while(++cal < InfoSegA); // While in info seg D, C, or B return -1; // Return failure }
     
    Make sure that CCS is configured to write only to main memory so the calibration constants are not erased. This is not the default configuration.

     
    The following code writes the DCO calibrations to the info segments. This only has to be done once for a specific chip. A 32 kHz crystal must be installed while this code is running, but is no longer needed once the calibration has been written.
     
    Serial output while running calibration...

    Info Segments - before calibration D 65535,65535,65535,65535,65535,65535,65535,65535, 65535,65535,65535,65535,65535,65535,65535,65535, 65535,65535,65535,65535,65535,65535,65535,65535, 65535,65535,65535,65535,65535,65535,65535,65535, C 65535,65535,65535,65535,65535,65535,65535,65535, 65535,65535,65535,65535,65535,65535,65535,65535, 65535,65535,65535,65535,65535,65535,65535,65535, 65535,65535,65535,65535,65535,65535,65535,65535, B 65535,65535,65535,65535,65535,65535,65535,65535, 65535,65535,65535,65535,65535,65535,65535,65535, 65535,65535,65535,65535,65535,65535,65535,65535, 65535,65535,65535,65535,65535,65535,65535,65535, A 35969,5886,65535,65535,65535,65535,65535,65535, 65535,65535,65535,65535,65535,4112,32786,0, 32209,742,0,32332,437,0,2302,65535, 65535,65535,65535,2049,36757,36504,36234,34506, Calibrating... 99,106,114,123,134,146,122,131, 141,152,165,181,170,182,196,212, 229,251,241,258,278,299,323,354, 338,361,388,418,450,493,484,517, 555,596,642,703,673,718,770,827, 891,973,949,1012,1084,1163,1252,1368, 1348,1437,1538,1649,1776,1937,1924,2048, 2189,2346,2526,2754,2738,2911,3109,3329, 3586,3906,3520,3746,4007,4299,4635,5057, 4731,5032,5374,5761,6213,6770,6427,6824, 7278,7786,8385,9123,9350,9928,10587,11331, 12209,13283,12672,13414,14248,15200,16325,17715, Info Segments - after calibration D 99,106,114,123,134,146,122,131, 141,152,165,181,170,182,196,212, 229,251,241,258,278,299,323,354, 338,361,388,418,450,493,484,517, C 555,596,642,703,673,718,770,827, 891,973,949,1012,1084,1163,1252,1368, 1348,1437,1538,1649,1776,1937,1924,2048, 2189,2346,2526,2754,2738,2911,3109,3329, B 3586,3906,3520,3746,4007,4299,4635,5057, 4731,5032,5374,5761,6213,6770,6427,6824, 7278,7786,8385,9123,9350,9928,10587,11331, 12209,13283,12672,13414,14248,15200,16325,17715, A 35969,5886,65535,65535,65535,65535,65535,65535, 65535,65535,65535,65535,65535,4112,32786,0, 32209,742,0,32332,437,0,2302,65535, 65535,65535,65535,2049,36757,36504,36234,34506, Done
     
    Calibration code...
     
    main.c

    #include void putc(unsigned); // serial_tx.asm void puts(char *); // serial_tx.asm void utoa(unsigned, char *); // utoa.asm static char s[8]; // buffer for printing unsigned int // Address of info segments static unsigned * const InfoSegA = (unsigned *)0x10C0; static unsigned * const InfoSegB = (unsigned *)0x1080; static unsigned * const InfoSegC = (unsigned *)0x1040; static unsigned * const InfoSegD = (unsigned *)0x1000; /* Freq = Count / Time Freq = Count / (100 / 32768) <-- 100 cycles of 32.768 kHz clock Freq (kHz) = Count / ((100 / 32768) * 1000) Freq (kHz) = Count / 3.0517578125 Freq (kHz) = Count * (1 / 3.0517578125) Freq (kHz) = Count * 0.32768 Freq (kHz) ~= (Count * 21475) / 65536 Freq (kHz) ~= (Count * 21475) >> 16 Freq (kHz) ~= ((Count * 21475) + 32768) >> 16 <-- Better rounding */ void cal_block(unsigned *d, unsigned rsel, unsigned dco) { unsigned n = 32; // Do 32 cals beginning at rsel/dco with // dco range of 0x20 to 0xA0 using 0x20 step // - no modulation - 6 values per rsel DCOCTL = 0; // DCOCTL = dco & 0xE0; // Set initial DCOx, MODx == 0 BCSCTL1 = rsel; // Set initial RSELx do { // __delay_cycles(3277); // Wait for DCO to settle for 100 ms TACTL |= TACLR; // Clear TimerA TACTL |= MC_2; // Start counting - TimerA continuous mode __delay_cycles(100 - 5); // 100 cycles (5 overhead from previous and next instructions) TACTL &= ~MC_2; // Stop counting - TimerA stop mode // *d++ = ((21475L * TAR) + 32768) >> 16; // Scale to kHz // if((DCOCTL += 0x20) == 0xE0) { // Increment DCOx, check if limit reached DCOCTL = 0x20; // Reset DCOx ++BCSCTL1; // Next RSELx } // } while(--n); // } void cal_write(const unsigned *c, unsigned *f) { // Write one full info segment - 64 bytes / 32 ints unsigned n; // DCOCTL = 0; // Run DCO at 1 MHz BCSCTL1 = CALBC1_1MHZ; // DCOCTL = CALDCO_1MHZ; // FCTL2 = FWKEY | FSSEL_2 | 3 - 1; // SMCLK / 3 for flash timing generator FCTL3 = FWKEY; // Clear lock bit FCTL1 = FWKEY | ERASE; // Set erase bit *f = 0; // Dummy write to erase segment FCTL1 = FWKEY | WRT; // Set wrt bit for write operation n = 32; do *f++ = *c++; while(--n); // Write flash FCTL1 = FWKEY; // Clear wrt bit FCTL3 = FWKEY | LOCK; // Set lock bit } void show_block(const unsigned *c) { // Show 32 unsigned ints unsigned a, b; // a = 4; // 4 lines do { // b = 8; // 8 columns do { // utoa(*c++, s); // Unsigned to ASCII puts(s); // Print it putc(','); // } while(--; // Next column puts("\r\n"); // Next line } while(--a); // } void show_all_info_segs(void) { puts("D\r\n"); // show_block(InfoSegD); // D puts("C\r\n"); // show_block(InfoSegC); // C puts("B\r\n"); // show_block(InfoSegB); // B puts("A\r\n"); // show_block(InfoSegA); // A puts("\r\n"); // } void main(void) // { // unsigned n; // unsigned cal[32]; // WDTCTL = WDTPW | WDTHOLD; // Disable watchdog reset // TACTL = TASSEL_2; // SMCLK (DCO) // P1DIR = BIT1; // P1OUT = BIT1; // // BCSCTL3 = XCAP_2; // 10 pF n = 0; // do { // - Wait for MSP430 to detect clock is stable IFG1 &= ~OFIFG; // Clear OFIFG while(--n); // Wait a while } while(IFG1 & OFIFG); // Loop until OFIFG remains cleared BCSCTL2 = SELM1 | SELM0; // - Use LFXT1CLK (32 kHz xtal) as clock source // // Show all the info segments before calibration puts("Info Segments - before calibration\r\n"); show_all_info_segs(); // // puts("Calibrating...\r\n"); // Do calibration and write to flash info segments D to B // cal_block(cal, 0, 0x20); // Calibrate cal_write(cal, InfoSegD); // Write show_block(cal); // Show on terminal // cal_block(cal, 5, 0x60); // cal_write(cal, InfoSegC); // show_block(cal); // // cal_block(cal, 10, 0xA0); // cal_write(cal, InfoSegB); // show_block(cal); // // puts("\r\n"); // // Show all the info segments after calibration has been written puts("Info Segments - after calibration\r\n"); show_all_info_segs(); // // puts("Done\r\n"); // // for(;; // }
     
    serial_tx.asm

    .cdecls C, LIST, "msp430g2211.h" .text .def putc, puts ; 32768 Hz / 2400 bps = 13.6533 cycles per bit ~= 41 cycles per 3 bits (14 / 13 / 14) ; Char to tx in R12 putc: or #0x0100, R12 ; Stop bit mov #0x02, R15 ; Serial out bitmask jmp bit_start ; ; bit0: jmp $ + 2 ; jmp $ + 2 ; nop ; rra R12 ; Bit 0/3/6 jc bit0h ; bic.b R15, &P1OUT ; 14/55/96 jmp bit1 ; bit0h: bis.b R15, &P1OUT ; 14/55/96 jmp bit1 ; ; bit1: jmp $ + 2 ; jmp $ + 2 ; rra R12 ; Bit 1/4/7 jc bit1h ; bic.b R15, &P1OUT ; 27/68/109 jmp bit2 ; bit1h: bis.b R15, &P1OUT ; 27/68/109 jmp bit2 ; ; bit2: jmp $ + 2 ; jmp $ + 2 ; nop ; rra R12 ; Bit Start/2/5/Stop jc bit2h ; bit_start: bic.b R15, &P1OUT ; 0/41/82/- jmp bit0 ; bit2h: bis.b R15, &P1OUT ; -/41/82/123 jne bit0 ; ret_ins: ret puts: ; Tx string using putc mov R12, R14 ; String pointer in R12, copy to R14 putsloop: ; mov.b @R14+, R12 ; Get a byte, inc pointer tst.b R12 ; Test if end of string jz ret_ins ; Yes, exit... call #putc ; Call putc jmp putsloop ; ; .end ;
     
    utoa.asm

    .cdecls C, LIST, "msp430g2211.h" .text .def utoa utoa: ; --- Unsigned to ASCII --- ; - Range 0 to 65535 ; - Leading zeros supressed push R10 ; clr R14 ; Clear packed BCD .loop 13 ; Do 13 bits rla R12 ; Get bit 15 to 3 of binary dadd R14, R14 ; Multiply BCD by 2 and add binary bit .endloop ; clr R15 ; Clear digit 1 of packed BCD .loop 3 ; Do 3 bits rla R12 ; Get bit 2 to 0 of binary dadd R14, R14 ; Multiply BCD by 2 and add binary bit dadd R15, R15 ; .endloop ; swpb R14 ; Swap digit order mov R14, R12 ; Copy packed BCD digits and #0x0F0F, R12 ; Mask digits 5 & 3 rra R14 ; Shift digits 4 & 2 to lower nibble rra R14 ; rra R14 ; rra R14 ; and #0x0F0F, R14 ; Mask digits 4 & 2 mov #('0' << 8) | '0', R10 ; Make ASCII add R10, R12 ; add R10, R14 ; add R10, R15 ; cmp.b R10, R15 ; Is first digit a 0? jne dig5 ; No... cmp.b R10, R14 ; Is second digit a 0? jne dig4 ; No, only the first... cmp.b R10, R12 ; Is third digit a 0? jne dig3 ; No, only the first two... cmp R10, R14 ; Is fourth digit a 0? (second is zero) jne dig2 ; No, only the first three... dig1: ; First four digits are all 0 swpb R12 ; Fifth digit to string mov.b R12, 0(R13) ; inc R13 ; clr.b 0(R13) ; NULL terminate string pop R10 ; ret ; Return ; dig5: ; mov.b R15, 0(R13) ; First digit to string inc R13 ; dig4: ; mov.b R14, 0(R13) ; Second digit to string inc R13 ; dig3: ; mov.b R12, 0(R13) ; Third digit to string inc R13 ; dig2: ; swpb R14 ; Fourth digit to string mov.b R14, 0(R13) ; inc R13 ; jmp dig1 ;
  18. Like
    oPossum got a reaction from jazz in 3 way 50x50mm proto board   
    This can be used as...
    - Prototype booster
    - Stand alone MSP430 dev board
    - MSP430 dev board with booster
     
    The LEDs are 0603, bypass cap 0805, all other 0402.
    Pilot holes for mounting holes.
     

    lp_mini_proto_plus.sch
    lp_mini_proto_plus.brd
  19. Like
    oPossum got a reaction from jazz in Launchpad Mini - revision 3   
    A few updates...
    - 2 or 4 pin pushbuttons
    - SPI MISO/MOSI reversing jumpers (J8)
    - Support for FTDI on 6 pin 100 mil header - requires 2 trace cuts and a jumper
     

    lp_mini_r3.sch
    lp_mini_r3.brd
  20. Like
    oPossum got a reaction from Apr30 in CCS for $9.99   
    Free shipping until 9/18/2016.
  21. Like
    oPossum got a reaction from veryalive in CCS for $9.99   
    Free shipping until 9/18/2016.
  22. Like
    oPossum reacted to Rickta59 in CCS for $9.99   
    [NOTE]
    Before you bother trying to find this deal,  read this post:
    http://forum.43oh.com/topic/10050-ccs-70-will-be-available-without-license-requiremens/
     
    and this TI web page:
    http://processors.wiki.ti.com/index.php/CCSv7_Changes
    "Licensing
    With the release of Code Composer Studio v7 TI is no longer charging for licenses. You can simply download the tool and start using it. Along with this the end user license agreement has changed to a simple TSPA compatible license."
     
    [/NOTE]
     
    I didn't see anyone else mention this offer so here it is. Use the link below to buy the promo version of a G2 launchpad bundled with a node locked full version of CCS for only *$9.99:

    https://store.ti.com/MSP430G2-LaunchPad-Development-Kit-With-Code-Composer-Studio-Promotion-P50861.aspx

    -rick
     
    [Edit]
    * price is $9.99 + plus shipping
    [/Edit]
  23. Like
    oPossum reacted to chicken in Ken Shirriff's articles about BeagleBone   
    I don't have a BeagleBone, but found these two articles from Ken Shirriff very insightful.
     
    The BeagleBone's I/O pins: inside the software stack that makes them work
    http://www.righto.com/2016/08/the-beaglebones-io-pins-inside-software.html
     
    PRU tips: Understanding the BeagleBone's built-in microcontrollers
    http://www.righto.com/2016/08/pru-tips-understanding-beaglebones.html
     
    Like all his articles, these are long and VERY detailed. Solidly in the "all you ever wanted to know about.."  category.
     
    I suspect (hope) there are more BeagleBone articles coming.
  24. Like
    oPossum reacted to will in Temperature & Humidity sensor -with LCD & RF   
    Hi everyone, this is my credit card size wireless sensor node,
    with a 7-seg LCD display showing temperature & humidity, update every second.
    using MSP430FR4133 with HDC1080,BMP180 and OPT3002, 
    transmit by nRF24l01, which sends out temp,humid,pressure,luminosity and also battery voltage per minute.
     

     
    It is all power by a CR2032, and thanks to MSP430FR4133, I can manage to have half an year battery life.

    also thanks to MSP430RF4133 Launchpad with build-in energyTrace, I can estimate battery life with a click(no more oscilloscope  )

    note that I've actually put an RF430 on the down left ot the board(there is an antenna for that),
    which will act as a NFC tag, but it draws too much current (~15uA), so I took it off
    and at the down right is the battery voltage measurement with a mosfet to cut the power,
    but I found out that I can just measure internal voltage reference to calculate its supply voltage, so I've also remove that. 

     
    although I'm pretty much satisfy with this power consumption, but I still think that 16.5uA is a little bit too far from estimating from datasheet
    and I am still trying to figure that out
  25. Like
    oPossum reacted to Clavier in GPIO interrupts in both directions   
    Toggling the PxIES bit once has a race condition, when the signal switches again before the interrupt has run. You also have to check the current state of the PxIN bit to ensure that PxIES catches the next edge.
     
    But the easiest way to get interrupts for both edges is to route the signal to two pins.
×
×
  • Create New...