打印
[资料分享]

ADS1100 驱动程序--MSP430F413

[复制链接]
372|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
xyz549040622|  楼主 | 2020-1-27 10:47 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
//------------------------------------------------------------------------------
// 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
}


使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:qq群: 嵌入式系统arm初学者 224636155←← +→→点击-->小 i 精品课全集,21ic公开课~~←←→→点击-->小 i 精品课全集,给你全方位的技能策划~~←←

2700

主题

19156

帖子

103

粉丝