Source
From emboxit
sluaa220
//------------------------------------------------------------------------------ // MSP430F42x Single Chip Weigh Scale - C Language Version // // Description: Program reads out the MSP430 SD16 Sigma-Delta ADC channel 0. // The differential input voltage is displayed as a signed number on a 7.5 digit // LCD. The displayed value is calculated using a 2-point calibration mechanism. // During initial power-up (with INFOA Flash memory erased), two calibration // data points are obtained (CalMin and CalMax) and stored into Flash memory. // The range of CalMin to CalMax is projected during measurement mode into a // display-value from 0 to CAL_MIN_MAX_SPAN. A button connected to P1.0 is // used to enter low-power mode (short press) and re-calibrate the // system (long press). An external 32-kHz watch crystal is used for FLL // stabilization, time interval generation and for driving the LCD. // // // MSP430F427 // +---------------+ // | | +----------------------+ // IN+ o---|A0+ S0-S23|--->| SoftBaugh SBLCDA4 | // IN- o---|A0- COM0-COM3|--->| 7.1 Digit,4-Mux LCD | // VBridge o--+|P2.0 | +----------------------+ // +|P2.1 | // o---|VRef R03-R33|<---LCD Voltage Ladder Rs // | | // | XIN/XOUT|<---32.768KHz Watch Crystal // | P1.0|<---Button (low-active) // +---------------+ // // Andreas Dannenberg // Texas Instruments Inc. // September 2004 // Built with IAR Embedded Workbench Version: 3.20A //------------------------------------------------------------------------------ #include "msp430x42x.h" #define CAL_MIN_MAX_SPAN 10000 // Scale value for CalMin/CalMax // 10,000 Counts=10kg=10,000g // Circuit related definitions #define BRIDGE_SUPPLY (0x03) // IO pins P2.0/P2.1 for // pos. bridge rail #define PUSH_BUTTON (0x01) // Button on pin P1.0 // Get a 18-bit wide result from SD16 channel 0 (17 bit + sign bit) #define GET_RESULT(var) SD16CCTL0 &= ~SD16LSBACC; \ var = (long)(int)SD16MEM0 << 2; \ SD16CCTL0 |= SD16LSBACC; \ var |= ((int)SD16MEM0 & 0xc0) >> 6 enum { PM_MEASURE, // Program Mode - Normal PM_CAL_LO, // Program Mode - Cal Low PM_CAL_HI, // Program Mode - Cal High PM_PWRDOWN // Program Mode - Powered Down }; // LCD segment definitions. #define e 0x40 // AAAA #define g 0x20 // F B #define f 0x10 // F B #define d 0x08 // GGGG #define c 0x04 // E C #define b 0x02 // E C #define a 0x01 // DDDD const char LCD_Tab[] = { a + b + c + d + e + f, // Displays "0" b + c, // Displays "1" a + b + d + e + g, // Displays "2" a + b + c + d + g, // Displays "3" b + c + f + g, // Displays "4" a + c + d + f +g, // Displays "5" a + c + d + e + f + g, // Displays "6" a + b + c, // Displays "7" a + b + c + d + e + f + g, // Displays "8" a + b + c + d + f + g, // Displays "9" a + b + c + e + f + g, // Displays "A" b + c + e + f + g, // Displays "H" a + d + e + f, // Displays "C" d + e + f, // Displays "L" 0x00, // Displays Blank 0x00 // Displays Blank }; #undef a #undef b #undef c #undef d #undef e #undef f #undef g // Global vars static unsigned int VoltageSettleCtr; // Used as voltage settle ctr. static unsigned int SD16TempCtr; // Number of resuts collected static long SD16Temp; // Temp sum register static long SD16Result; // Final averaged result static long LastADCValue; // Last averaged result static unsigned int ProgramMode; // Current program mode static long CalMinTmp; // Temp vars to hold static long CalMaxTmp; // calibration values static char ButtonDownCtr; // Keeps track of button press // duration #define FLAG_UPDATE_DISPL 0x01 // Bit definitions used for #define FLAG_BUTTON_DOWN 0x02 // flag register static char Flags = FLAG_UPDATE_DISPL; // Flag register #pragma dataseg = INFOA // Info Flash Memory Block A __no_init static long CalMin; __no_init static long CalMax; #pragma dataseg = default // Function prototypes void Init_Sys(void); void StartNextConversion(void); void StoreCalInFlash(void); void Disp_Signed_Long(long Value); void Disp_BCD(unsigned long Value); //------------------------------------------------------------------------------ void main(void) { Init_Sys(); if (CalMin == CalMax) // Are constants in Flash OK? { Disp_BCD(0xfcadfd0); // Display 'CAL LO' ProgramMode = PM_CAL_LO; // Enter calibration mode } else { ProgramMode = PM_MEASURE; // Enter measurement mode } StartNextConversion(); // Start conversions __bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ ints enabled } //------------------------------------------------------------------------------ void Init_Sys(void) { int i; char *pLCD = (char *)&LCDM1; WDTCTL = WDTPW + WDTHOLD; // Stop WDT FLL_CTL0 |= XCAP18PF; // Set load capacitance for xtal for (i = 0; i < 20; i++) // Clear LCD memory *pLCD++ = 0; LCDCTL = LCDSG0_3 + LCD4MUX + LCDON; // 4mux LCD, segs0-23 BTCTL = BT_fLCD_DIV128+BTDIV+BT_fCLK2_DIV64; // 0.5s BT Int, Set LCD freq IE2 |= BTIE; // Enable Basic Timer interrupt P1OUT = 0xff; // P1OUTs = 1 P1DIR = 0xff & ~PUSH_BUTTON; // All pins but button to output P1IES = PUSH_BUTTON; // Button int on falling edge P1IFG = 0; P1IE = PUSH_BUTTON; // Enable button interrupt P2OUT = 0xff; // P2OUTs = 1 P2DIR = 0xff; // All pins outputs SD16INCTL0 = SD16GAIN_32 + SD16INCH_0; // 32x gain, channel pair A0 SD16CCTL0 = SD16DF + SD16IE; // Continuous conv., 2s compl. } //------------------------------------------------------------------------------ // Programs the calibration constants CalMinTmp and CalMaxTmp into Flash // info memory segment A using in-system self programming techniques //------------------------------------------------------------------------------ void StoreCalInFlash(void) { FCTL2 = FWKEY + FSSEL1 + FN1; // SMCLK/3 = ~333kHz FCTL3 = FWKEY; // Clear LOCK FCTL1 = FWKEY + ERASE; // Enable segment erase *(unsigned int *)0x1080 = 0; // Dummy write, erase info A FCTL1 = FWKEY + WRT; // Enable write CalMin = CalMinTmp; // Program calibration constants CalMax = CalMaxTmp; FCTL1 = FWKEY; // Done. Clear WRT FCTL3 = FWKEY + LOCK; // Done. Set LOCK } //------------------------------------------------------------------------------ // Converts the 32-Bit integer number 'Value' to BCD and outputs it // on the LCD display //------------------------------------------------------------------------------ void Disp_Signed_Long(long Value) { unsigned int i; unsigned long Output; char fNeg = 0; if (Value < 0) // Test for negative value { Value = -Value; // Negate value fNeg = 1; // Set negative flag } for (i = 32, Output = 0; i; i--) // BCD Conversion, 32-Bit { Output = __bcd_add_long(Output, Output); if (Value & 0x80000000) Output = __bcd_add_long(Output, 1); Value <<= 1; } if (fNeg) // Display neg sign? Output |= 0x80000000; // Bit 31 indicates neg. number Disp_BCD(Output); } //------------------------------------------------------------------------------ // Displays the BCD number 'Value' on the LCD display //------------------------------------------------------------------------------ void Disp_BCD(unsigned long Value) { char *pLCD = (char *)&LCDM6; int i; for (i = 0; i < 7; i++) // Process 7 digits { *pLCD++ = LCD_Tab[Value & 0x0f]; // Segments to LCD Value >>= 4; // Process next digit } if (Value & 0x01) LCDM4 |= 0x08; // Display "1" (8th digit) else LCDM4 &= ~0x08; // Clear "1" (8th digit) if (Value & 0x08) // Bit 31 indicates neg. number LCDM4 |= 0x40; // Display "-" else LCDM4 &= ~0x40; // Clear "-" } //------------------------------------------------------------------------------ void StartNextConversion(void) { SD16Temp = 0; SD16TempCtr = 0; P2OUT |= BRIDGE_SUPPLY; // Power-up bridge sensor VoltageSettleCtr = 46; // Allow voltages to settle // (46+4)x244us=12ms SD16CCTL0 |= SD16SC; // Start conversion } //------------------------------------------------------------------------------ #pragma vector = SD16_VECTOR __interrupt void SD16_ISR(void) { long CurrentResult; GET_RESULT(CurrentResult); // Read SD16 result, clear IFG if (VoltageSettleCtr) // Wait for voltages to settle { VoltageSettleCtr--; // Decrement counter return; // Exit ISR } SD16Temp += CurrentResult; // Sum up results if (++SD16TempCtr >= 256) { SD16Result = SD16Temp >> 8; // Div 256 SD16CCTL0 &= ~SD16SC; // Disable conversions P2OUT &= ~BRIDGE_SUPPLY; // Power down bridge voltage if (ProgramMode == PM_MEASURE) if (Flags & FLAG_UPDATE_DISPL || LastADCValue != SD16Result) { Flags &= ~FLAG_UPDATE_DISPL; // Reset flag LastADCValue = SD16Result; // Store new value Disp_Signed_Long(((long)SD16Result - CalMin) * CAL_MIN_MAX_SPAN / (CalMax - CalMin)); } __bis_SR_register_on_exit(LPM3_bits); // Enter LPM3 on ISR exit } } //------------------------------------------------------------------------------ #pragma vector = BASICTIMER_VECTOR __interrupt void BT_ISR(void) { switch (ProgramMode) { case PM_MEASURE : if (Flags & FLAG_BUTTON_DOWN) if (P1IN & PUSH_BUTTON) // Was button released? { // Yes, then power down circuit Flags &= ~FLAG_BUTTON_DOWN; IE2 &= ~BTIE; // Disable Basic Timer interrupt P2OUT &= ~BRIDGE_SUPPLY; // Power down bridge voltage LCDCTL &= ~LCDON; // Disable LCD SD16CCTL0 &= ~SD16SC; // Disable conversions IFG2 &= ~BTIFG; // Clear Basic Timer int flag ProgramMode = PM_PWRDOWN; __bis_SR_register_on_exit(LPM3_bits); // Enter LPM3 on ISR exit break; } else if (++ButtonDownCtr > 5) // Button still pressed, { // time expired? Disp_BCD(0xfcadfd0); // Display 'CAL LO' ProgramMode = PM_CAL_LO; // Enter calibration mode } StartNextConversion(); __bic_SR_register_on_exit(SCG1 + SCG0); // Enter LPM0 on exit break; case PM_CAL_LO : case PM_CAL_HI : StartNextConversion(); __bic_SR_register_on_exit(SCG1 + SCG0); // Enter LPM0 on exit break; } } //------------------------------------------------------------------------------ #pragma vector = PORT1_VECTOR __interrupt void PORT1_ISR(void) { volatile unsigned int i; // 'volatile' to prevent opt. switch (ProgramMode) { case PM_MEASURE : Flags |= FLAG_BUTTON_DOWN; ButtonDownCtr = 0; break; case PM_CAL_LO : CalMinTmp = SD16Result; // Get conversion result Disp_BCD(0xfcadfb1); // Display 'CAL HI' ProgramMode = PM_CAL_HI; // Enter calibration mode (high) break; case PM_CAL_HI : CalMaxTmp = SD16Result; // Get conversion result if (CalMinTmp == CalMaxTmp) // Are calibr constants OK? { Disp_BCD(0xfcadfd0); // Display 'CAL LO' ProgramMode = PM_CAL_LO; // Enter calibration mode } else // Calibration OK { StoreCalInFlash(); // Yes, program constants and ProgramMode = PM_MEASURE; // Enter normal mode Flags |= FLAG_UPDATE_DISPL; // Request display update Flags &= ~FLAG_BUTTON_DOWN; // Clear button flag } break; case PM_PWRDOWN : IE2 |= BTIE; // Enable Basic Timer interrupt P2OUT |= BRIDGE_SUPPLY; // Power-up bridge sensor LCDCTL |= LCDON; // Enable LCD StartNextConversion(); // Start conversion Flags |= FLAG_UPDATE_DISPL; // Request display update ProgramMode = PM_MEASURE; __bic_SR_register_on_exit(SCG1 + SCG0); // Enter LPM0 on exit break; } for (i = 0x7fff; i; i--); // Delay for key-debounce P1IFG = 0x00; // Clear all P1 int flags }
sluaa283
//***************************************************************************** // Code for application report SLAA283 - "Ultra-low Power Motion Detection // using the MSP430F2013" // // Version 0-00 // // Version Summary: // 0-00 released 12-22-2005- Initial release // // Z. Albus // Texas Instruments Inc. // December 2005 // Built with IAR Embedded Workbench Version: 3.30B //***************************************************************************** // THIS PROGRAM IS PROVIDED "AS IS". TI MAKES NO WARRANTIES OR // REPRESENTATIONS, EITHER EXPRESS, IMPLIED OR STATUTORY, // INCLUDING ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR // COMPLETENESS OF RESPONSES, RESULTS AND LACK OF NEGLIGENCE. // TI DISCLAIMS ANY WARRANTY OF TITLE, QUIET ENJOYMENT, QUIET // POSSESSION, AND NON-INFRINGEMENT OF ANY THIRD PARTY // INTELLECTUAL PROPERTY RIGHTS WITH REGARD TO THE PROGRAM OR // YOUR USE OF THE PROGRAM. // // IN NO EVENT SHALL TI BE LIABLE FOR ANY SPECIAL, INCIDENTAL, // CONSEQUENTIAL OR INDIRECT DAMAGES, HOWEVER CAUSED, ON ANY // THEORY OF LIABILITY AND WHETHER OR NOT TI HAS BEEN ADVISED // OF THE POSSIBILITY OF SUCH DAMAGES, ARISING IN ANY WAY OUT // OF THIS AGREEMENT, THE PROGRAM, OR YOUR USE OF THE PROGRAM. // EXCLUDED DAMAGES INCLUDE, BUT ARE NOT LIMITED TO, COST OF // REMOVAL OR REINSTALLATION, COMPUTER TIME, LABOR COSTS, LOSS // OF GOODWILL, LOSS OF PROFITS, LOSS OF SAVINGS, OR LOSS OF // USE OR INTERRUPTION OF BUSINESS. IN NO EVENT WILL TI'S // AGGREGATE LIABILITY UNDER THIS AGREEMENT OR ARISING OUT OF // YOUR USE OF THE PROGRAM EXCEED FIVE HUNDRED DOLLARS // (U.S.$500). // // Unless otherwise stated, the Program written and copyrighted // by Texas Instruments is distributed as "freeware". You may, // only under TI's copyright in the Program, use and modify the // Program without any charge or restriction. You may // distribute to third parties, provided that you transfer a // copy of this license to the third party and the third party // agrees to these terms by its first use of the Program. You // must reproduce the copyright notice and any other legend of // ownership on each copy or partial copy, of the Program. // // You acknowledge and agree that the Program contains // copyrighted material, trade secrets and other TI proprietary // information and is protected by copyright laws, // international copyright treaties, and trade secret laws, as // well as other intellectual property laws. To protect TI's // rights in the Program, you agree not to decompile, reverse // engineer, disassemble or otherwise translate any object code // versions of the Program to a human-readable form. You agree // that in no event will you alter, remove or destroy any // copyright notice included in the Program. TI reserves all // rights not specifically granted under this license. Except // as specifically provided herein, nothing in this agreement // shall be construed as conferring by implication, estoppel, // or otherwise, upon you, any license or other right under any // TI patents, copyrights or trade secrets. // // You may not use the Program in non-TI devices. // //****************************************************************************** #include <msp430x20x3.h> #define LED_OUT BIT0 // Bit location for LED #define SENSOR_PWR BIT7 // Bit location for power to sensor #define THRESHOLD 50 // Threshold for motion static unsigned int result_old = 0; // Storage for last conversion void main(void) { WDTCTL = WDTPW+WDTTMSEL+WDTCNTCL+WDTSSEL; // ACLK/32768, int timer: ~10s BCSCTL1 = CALBC1_1MHZ; // Set DCO to 1MHz DCOCTL = CALDCO_1MHZ; BCSCTL1 |= DIVA_2; // ACLK = VLO/4 BCSCTL3 |= LFXT1S_2; P1OUT = 0x10; // P1OUTs P1SEL = 0x08; // Select VREF function P1DIR = 0xEF; // Unused pins as outputs P2OUT = 0x00 + SENSOR_PWR; // P2OUTs P2SEL &= ~SENSOR_PWR; // P2.7 = GPIO P2DIR = 0xff; // Unused pins as outputs SD16CTL = SD16VMIDON + SD16REFON + SD16SSEL_1;// 1.2V ref, SMCLK SD16INCTL0 = SD16GAIN_4 + SD16INCH_4; // PGA = 4x, Diff inputs A4- & A4+ SD16CCTL0 = SD16SNGL + SD16IE; // Single conversion, 256OSR, Int enable SD16CTL &= ~SD16VMIDON; // VMID off: used to settle ref cap SD16AE = SD16AE1 + SD16AE2; // P1.1 & P1.2: A4+/- SD16_A inputs // Wait for PIR sensor to settle: 1st WDT+ interval P1SEL |= LED_OUT; // Turn LED on with ACLK (for low Icc) while(!(IFG1 & WDTIFG)); // ~5.4s delay: PIR sensor settling P1SEL &= ~LED_OUT; // Turn LED off with ACLK (for low Icc) // Reconfig WDT+ for normal operation: interval of ~341msec WDTCTL = WDTPW+WDTTMSEL+WDTCNTCL+WDTSSEL+WDTIS1;// ACLK/512, int timer: 341msec BCSCTL1 |= DIVA_3; // ACLK = VLO/8 IE1 |= WDTIE; // Enable WDT interrupt _BIS_SR(LPM3_bits + GIE); // Enter LPM3 with interrupts } /****************************************************** // SD16_A interrupt service routine ******************************************************/ #pragma vector = SD16_VECTOR __interrupt void SD16ISR(void) { unsigned int result_new; SD16CTL &= ~SD16REFON; // Turn off SD16_A ref result_new = SD16MEM0; // Save result (clears IFG) if (result_new > result_old) // Get difference between samples result_old = result_new - result_old; else result_old = result_old - result_new; if (result_old > THRESHOLD) // If motion detected... P1OUT |= LED_OUT; // Turn LED on result_old = SD16MEM0; // Save last conversion __bis_SR_register_on_exit(SCG1+SCG0); // Return to LPM3 after reti } /****************************************************** // Watchdog Timer interrupt service routine ******************************************************/ #pragma vector=WDT_VECTOR __interrupt void watchdog_timer(void) { if (!(P1OUT & LED_OUT)) // Has motion already been detected? { SD16CTL |= SD16REFON; // If no, turn on SD16_A ref SD16CCTL0 |= SD16SC; // Set bit to start new conversion __bic_SR_register_on_exit(SCG1+SCG0); // Keep DCO & SMCLK on after reti } else P1OUT &= ~LED_OUT; // If yes, turn off LED, measure on next loop }
magnetic sensor reading
// NX 2011.08.03 // NX MODIFIED FOR MAGNETIC SENSOR READING // NX Based on SLAA283 // NX IAR EW IAR C/C++ Compiler for MSP430 5.30.1 [Kickstart LMS] (5.30.1.40284) // NX TODO: Check watchdog interrupt // //****************************************************************************** #include <msp430x20x3.h> #define LED_OUT BIT0 // Bit location for LED #define SENSOR_PWR BIT7 // Bit location for power to sensor //#define THRESHOLD 50 // Threshold for motion #define THRESHOLD 0x1000 // NX INCREASED Threshold for motion #define LEVEL 0xF000 // NX Threshold for absolute value // Get a 18-bit wide result from SD16 channel 0 (17 bit + sign bit) #define GET_RESULT(var) SD16CCTL0 &= ~SD16LSBACC; \ var = (long)(int)SD16MEM0 << 2; \ SD16CCTL0 |= SD16LSBACC; \ var |= ((int)SD16MEM0 & 0xc0) >> 6 static unsigned int result_old = 0; // Storage for last conversion void main(void) { WDTCTL = WDTPW+WDTTMSEL+WDTCNTCL+WDTSSEL; // ACLK/32768, int timer: ~10s //<-----------NX dalay to wait the PIR sensor after it is powered-up, change for magnetic sensor BCSCTL1 = CALBC1_1MHZ; // Set DCO to 1MHz DCOCTL = CALDCO_1MHZ; BCSCTL1 |= DIVA_2; // ACLK = VLO/4 BCSCTL3 |= LFXT1S_2; P1OUT = 0x10; // P1OUTs P1SEL = 0x08; // Select VREF function P1DIR = 0xEF; // Unused pins as outputs P2OUT = 0x00 + SENSOR_PWR; // P2OUTs P2SEL &= ~SENSOR_PWR; // P2.7 = GPIO P2DIR = 0xff; // Unused pins as outputs //NX from slau144h page 606 //NX An external voltage reference can be applied to the VREF input when SD16REFON and SD16VMIDON are both reset. //NX SD16CTL = SD16VMIDON + SD16REFON + SD16SSEL_1;// 1.2V ref, SMCLK SD16CTL = SD16SSEL_1; // NX External Reference, SMCLK SD16INCTL0 = SD16GAIN_32 + SD16INCH_4; // PGA = 4x, Diff inputs A4- & A4+ NX CHANGE GAIN FROM 4 TO 32 //SD16CCTL0 = SD16SNGL + SD16IE; // Single conversion, 256OSR, Int enable SD16CCTL0 = SD16IE; // Single conversion, 256OSR, Int enable // NX SD16DF like sluaa220 //SD16CTL &= ~SD16VMIDON; // VMID off: used to settle ref cap SD16AE = SD16AE1 + SD16AE2; // P1.1 & P1.2: A4+/- SD16_A inputs // Wait for PIR sensor to settle: 1st WDT+ interval P1SEL |= LED_OUT; // Turn LED on with ACLK (for low Icc) //while(!(IFG1 & WDTIFG)); // ~5.4s delay: PIR sensor settling ----->NX ATTENTION AT SINGLE STEP P1SEL &= ~LED_OUT; // Turn LED off with ACLK (for low Icc) // Reconfig WDT+ for normal operation: interval of ~341msec WDTCTL = WDTPW+WDTTMSEL+WDTCNTCL+WDTSSEL+WDTIS1;// ACLK/512, int timer: 341msec BCSCTL1 |= DIVA_3; // ACLK = VLO/8 IE1 |= WDTIE; // Enable WDT interrupt _BIS_SR(LPM3_bits + GIE); // Enter LPM3 with interrupts } /****************************************************** // SD16_A interrupt service routine ******************************************************/ #pragma vector = SD16_VECTOR __interrupt void SD16ISR(void) { unsigned long CurrentResult; //NX from sluaa220 unsigned int result_low; unsigned int result_new; // GET_RESULT(CurrentResult); // Read SD16 result, clear IFG // SD16CCTL0 |= SD16LSBACC; // result_low = SD16MEM0; // result_low = SD16MEM0; SD16CCTL0 &= ~SD16LSBACC; // SD16CTL &= ~SD16REFON; // Turn off SD16_A ref result_new = SD16MEM0; // Save result (clears IFG) if (result_new > result_old) // Get difference between samples result_old = result_new - result_old; else result_old = result_old - result_new; if (result_old > THRESHOLD) // If motion detected... P1OUT |= LED_OUT; // Turn LED on //if (CurrentResult > LEVEL){ if (SD16MEM0 > LEVEL){ P1OUT |= BIT6; } else{ P1OUT &= ~BIT6; } result_old = SD16MEM0; // Save last conversion __bis_SR_register_on_exit(SCG1+SCG0); // Return to LPM3 after reti } /****************************************************** // Watchdog Timer interrupt service routine ******************************************************/ #pragma vector=WDT_VECTOR __interrupt void watchdog_timer(void) { if (!(P1OUT & LED_OUT)) // Has motion already been detected? { SD16CTL |= SD16REFON; // If no, turn on SD16_A ref SD16CCTL0 |= SD16SC; // Set bit to start new conversion __bic_SR_register_on_exit(SCG1+SCG0); // Keep DCO & SMCLK on after reti } else P1OUT &= ~LED_OUT; // If yes, turn off LED, measure on next loop //P1OUT &= ~BIT6; // NX Turn off green-led at P1.6 }