- //------------------------------------------------------------------------------
- // ADS1100_Demo.c - ADS1100 Bridge Sensor Readout Demo w/ MSP430F413
- //
- // Description: Program reads out an external ADS1100 Sigma-Delta ADC over the
- // I2C interface. The differential input voltage is displayed as a signed number
- // on a 3.5 digit LCD display. The displayed value is calculated using a 2-point
- // calibration mechanism. During initial power-up (INFOA Flash memory is erased),
- // two calibration data points are obtained (CalMin and CalMax) and stored in
- // Flash memory. The range of CalMin to CalMax is projected into a display-value
- // from 0 to CAL_MIN_MAX_SPAN. Button #1 is used to enter low-power mode,
- // button #2 is used to re-calibrate. An external 32-kHz watch crystal is used
- // for time interval generation and for driving the LCD.
- //
- // /|\ /|\ /|\
- // | ADS1100 10k 10k MSP430F413
- // | +-------+ | | +----------+
- // +---|Vcc SDA|<-|---+>|P2.0 | +----------------------+
- // o-------|VIN+ | | | S0-S23|--->| Varitronix 3.5 digit |
- // o-------|VIN- | | | COM0|--->| Static LCD Display |
- // +--|Vss SCL|<-+-----|P2.1 | +----------------------+
- // \|/ +-------+ | |
- // | XIN/XOUT|<---32.768KHz Watch Crystal
- // | P1.6|<---Button #1 (low-active)
- // | P1.7|<---Button #2 (low-active)
- // +----------+
- // Andreas Dannenberg
- // Texas Instruments Inc.
- // June 2004
- // Built with IAR Embedded Workbench Version: 3.10A
- //------------------------------------------------------------------------------
- #include "msp430x41x.h"
- #include "I2C_Master.h"
- #define CAL_MIN_MAX_SPAN 1000 // Scale value for CalMin/CalMax
- // Definitions for ADS1100 A/D converter
- #define ADS1100_SA (0x48) // ADS1100 I2C Slave Address
- #define ADS1100_GAIN1 (0x00) // PGA Gain X1
- #define ADS1100_GAIN2 (0x01) // PGA Gain X2
- #define ADS1100_GAIN4 (0x02) // PGA Gain X4
- #define ADS1100_GAIN8 (0x03) // PGA Gain X8
- #define ADS1100_128SPS (0x00) // 128 Samples/s
- #define ADS1100_32SPS (0x04) // 32 Samples/s
- #define ADS1100_16SPS (0x08) // 16 Samples/s
- #define ADS1100_8SPS (0x0C) // 8 Samples/s
- #define ADS1100_SC (0x10) // Single Conversion Mode
- #define ADS1100_ST_BSY (0x80) // Start Conversion + Busy
- // Circuit related definitions
- #define BRIDGE_H (0x38) // IO pins for pos. bridge rail
- #define BRIDGE_L (0x07) // IO pins for neg. bridge rail
- enum
- {
- BT_ISR_NRM, // BT ISR - Wakeup
- BT_ISR_CL1, // BT ISR - Show 'CAL'
- BT_ISR_CL2, // BT ISR - Display 'LO'
- BT_ISR_CH1, // BT ISR - Toggle CAL/HI
- BT_ISR_CH2 // BT ISR - Toggle CAL/HI
- };
- enum
- {
- P1_ISR_NRM, // Port1 ISR - Normal Mode
- P1_ISR_CL, // Port1 ISR - Cal Low Mode
- P1_ISR_CH // Port1 ISR - Cal High Mode
- };
- const unsigned char LCD_Tab[] =
- {
- 0x77, // Displays "0"
- 0x12, // Displays "1"
- 0x3d, // Displays "2"
- 0x3b, // Displays "3"
- 0x5a, // Displays "4"
- 0x6b, // Displays "5"
- 0x6f, // Displays "6"
- 0x13, // Displays "7"
- 0x7f, // Displays "8"
- 0x7b, // Displays "9"
- 0x5e, // Displays "H"
- 0x64, // Displays "L"
- 0x65, // Displays "C"
- 0x5f, // Displays "A"
- 0x00, // Displays Blank
- 0x00 // Displays Blank
- };
- // Global vars
- static unsigned int BtIsrMode; // ISR Mode for Basic Timer
- static unsigned int P1IsrMode; // ISR Mode for Port 1
- static int CalMinTmp; // Vars to hold calib values
- static int CalMaxTmp;
- static int LastADCValue;
- static char UpdateDisplay = 1; // Flag to request LCD update
- #pragma dataseg = INFOA // Info Flash Memory Block A
- __no_init static int CalMin;
- __no_init static int CalMax;
- #pragma dataseg = default
- // Function prototypes
- void Init_Sys(void);
- void StoreCalInFlash(void);
- void Disp_Signed_3_5(int Value);
- void Disp_BCD_3_5(unsigned int Value);
- //------------------------------------------------------------------------------
- void main(void)
- {
- Init_Sys();
-
- if (CalMin == CalMax) // Are constants in Flash OK?
- {
- BtIsrMode = BT_ISR_CL1; // Go to calibration mode
- P1IsrMode = P1_ISR_CL;
- }
- else
- {
- BtIsrMode = BT_ISR_NRM; // Go to measurement mode
- P1IsrMode = P1_ISR_NRM;
- }
-
- I2CWrite8(ADS1100_SA, ADS1100_8SPS + ADS1100_GAIN8); // Start conversions
- __bis_SR_register(LPM3_bits + GIE); // Enter LPM3 w/ ints enabled
- }
- //------------------------------------------------------------------------------
- void Init_Sys(void)
- {
- WDTCTL = WDTPW + WDTHOLD; // Stop WDT
- FLL_CTL0 |= XCAP18PF; // Set load capacitance for xtal
- LCDCTL = 0xc5; // Static LCD, segments = 0 - 23
- BTCTL = BT_fLCD_DIV256+BTDIV+BT_fCLK2_DIV32; // 0.25s BT Int, Set LCD freq
- IE2 |= BTIE; // Enable Basic Timer interrupt
- P1OUT = 0; // P1OUTs = 0
- P1DIR = 0x3f; // P1.7/P1.6 input, others outp
- P1IES = 0xc0; // P1.7/P1.6 int on falling edge
- P1IFG = 0;
- P1IE = 0xc0; // Enable button intuerrupts
- P2OUT = 0; // P2OUTs = 0
- P2DIR = 0xfc; // Set port but I2C pins to outputs
- P3OUT = 0; // P3OUTs = 0
- P3DIR = 0xff; // Set port to outputs
- P4OUT = 0; // P4OUTs = 0
- P4DIR = 0xff; // Set port to outputs
- P5OUT = 0; // P5OUTs = 0
- P5DIR = 0xff; // Set port to outputs
- P6OUT = BRIDGE_H; // Enable bridge supply voltage
- P6DIR = 0xff; // Set port to outputs
- }
- //------------------------------------------------------------------------------
- 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
- }
- //------------------------------------------------------------------------------
- void Disp_Signed_3_5(int Value)
- {
- unsigned int i;
- unsigned int Output;
- char fNeg = 0;
-
- if (Value >= 2000) // Higher/equ w/ 2000?
- {
- Disp_BCD_3_5(0x0a1f); // Display 'HI'
- return;
- }
- if (Value < -1999) // Less than -1999?
- {
- Disp_BCD_3_5(0x0b0f); // Display 'LO'
- return;
- }
- if (Value < 0) // Test for new negative value
- {
- Value = -Value; // Negate value
- fNeg = 1; // Set negative flag
- }
- for (i = 16, Output = 0; i; i--) // BCD Conversion, 16-Bit
- {
- Output = __bcd_add_short(Output, Output);
- if (Value & 0x8000)
- Output = __bcd_add_short(Output, 1);
- Value <<= 1;
- }
- if (fNeg)
- Output |= 0x2000;
- Disp_BCD_3_5(Output);
- }
- //------------------------------------------------------------------------------
- void Disp_BCD_3_5(unsigned int Value)
- {
- unsigned char *pLCD = (unsigned char *)&LCDM1; // 1st LCD mem location
- unsigned char LCDSegInfo;
- unsigned char LCDDigit;
-
- do
- {
- LCDDigit = Value & 0x0f; // Get one LCD digit
- LCDSegInfo = LCD_Tab[LCDDigit]; // Get LCD segment information
- *pLCD++ = LCDSegInfo; // Segments a & b to LCD
- LCDSegInfo >>= 1;
- *pLCD++ = LCDSegInfo; // Segments c & d to LCD
- LCDSegInfo >>= 1;
- *pLCD++ = LCDSegInfo; // Segments e & f to LCD
- LCDSegInfo >>= 1;
- *pLCD++ = LCDSegInfo; // Segments g & h to LCD
- Value >>= 4; // Process next digit
- } while (pLCD < (unsigned char *)&LCDM13); // Updated all segments?
- if (Value & 0x01) // Data >999?
- LCDM12 |= 0x10; // B-C digit active
-
- if (Value & 0x02) // Display neg sign?
- LCDM8 |= 0x10; // "-" segment active
- }
- //------------------------------------------------------------------------------
- #pragma vector = BASICTIMER_VECTOR
- __interrupt void BT_ISR(void)
- {
- int CurrentADCValue;
- switch (BtIsrMode)
- {
- case BT_ISR_NRM :
- CurrentADCValue = I2CRead16(ADS1100_SA); // Get conversion result
- if (UpdateDisplay || LastADCValue != CurrentADCValue)
- {
- UpdateDisplay = 0; // Reset flag
- LastADCValue = CurrentADCValue; // Store new value
- Disp_Signed_3_5(((long)CurrentADCValue - CalMin) * CAL_MIN_MAX_SPAN /
- (CalMax - CalMin));
- }
- break;
- case BT_ISR_CL1 :
- Disp_BCD_3_5(0x0cdb); // Display 'CAL'
- BtIsrMode = BT_ISR_CL2; // Next state
- break;
- case BT_ISR_CL2 :
- Disp_BCD_3_5(0x0b0f); // Display 'LO'
- BtIsrMode = BT_ISR_CL1; // Next state
- break;
- case BT_ISR_CH1 :
- Disp_BCD_3_5(0x0cdb); // Display 'CAL'
- BtIsrMode = BT_ISR_CH2; // Next state
- break;
- case BT_ISR_CH2 :
- Disp_BCD_3_5(0x0a1f); // Display 'HI'
- BtIsrMode = BT_ISR_CH1; // Next state
- break;
- }
- }
- //------------------------------------------------------------------------------
- #pragma vector = PORT1_VECTOR
- __interrupt void PORT1_ISR(void)
- {
- volatile unsigned int i; // 'volatile' to prevent opt.
-
- switch (P1IsrMode)
- {
- case P1_ISR_NRM :
- if (P1IFG & 0x40) // Test for on P1.6 (on/off)
- {
- IE2 ^= BTIE; // Toggle Basic Timer interrupt
- P6OUT ^= BRIDGE_H; // Toggle Bridge Supply Voltage
- LCDCTL ^= LCDON; // Toggle LCD on/off
-
- if (LCDCTL & LCDON)
- {
- I2CWrite8(ADS1100_SA, ADS1100_8SPS + ADS1100_GAIN8); // Start conversions
- UpdateDisplay = 1; // Request display update
- }
- else
- {
- I2CWrite8(ADS1100_SA, ADS1100_SC); // Disable conversions
- IFG2 &= ~BTIFG; // Clear Basic Timer int flag
- }
- }
- if (P1IFG & 0x80 && LCDCTL & LCDON) // Test for on P1.7 (calibration)
- {
- P1IsrMode = P1_ISR_CL; // Enter calibration mode (low)
- BtIsrMode = BT_ISR_CL1;
- }
- break;
- case P1_ISR_CL :
- if (P1IFG & 0xc0) // Test for P1.6/P1.7
- {
- CalMinTmp = I2CRead16(ADS1100_SA); // Get 16-bit conversion result
- P1IsrMode = P1_ISR_CH;
- BtIsrMode = BT_ISR_CH1; // Enter calibration mode (high)
- }
- break;
- case P1_ISR_CH :
- if (P1IFG & 0xc0) // Test for P1.6/P1.7
- {
- CalMaxTmp = I2CRead16(ADS1100_SA); // Get 16-bit conversion result
- if (CalMinTmp == CalMaxTmp) // Are calibr constants OK?
- {
- P1IsrMode = P1_ISR_CL; // No,
- BtIsrMode = BT_ISR_CL1; // enter calibration mode (low)
- }
- else // Calibration OK
- {
- StoreCalInFlash(); // Yes, program constants and
- P1IsrMode = P1_ISR_NRM; // enter normal mode
- BtIsrMode = BT_ISR_NRM;
- UpdateDisplay = 1; // Request display update
- }
- }
- break;
- }
-
- for (i = 0x7fff; i; i--); // Delay for key-debounce
- P1IFG = 0x00; // Clear all P1 int flags
- }
|