初级会员

- 积分
- 173
- 金钱
- 173
- 注册时间
- 2015-11-16
- 在线时间
- 22 小时
|
发表于 2017-5-3 18:00:11
|
显示全部楼层
[mw_shl_code=c,true]/*************************************************************************************************************************************************/
/*! Thermocouple temperature application Code TIDA-00168
*
* The Thermocouple Transmitter reference design is a system solution providing precision K type thermocouples measurements.
* This design is intended as an evaluation module for users to develop end products for factory automation and process control applications.
* The software is specifically written to execute on a MSP430FR5949.
*
*
*/
/**************************************************************************************************************************************************
* Copyright ?2014 Texas Instruments Incorporated - http://www.ti.com/ *
***************************************************************************************************************************************************
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: *
* *
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. *
* *
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* Neither the name of Texas Instruments Incorporated nor the names of its contributors may be used to endorse or promote products derived *
* from this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT *
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE *
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
**************************************************************************************************************************************************/
#include <msp430.h>
#include <stdint.h>
#include "ADS1220.h"
#include "RTD_Math.h"
#include "TC_Math.h"
#include "TI_MSP430.h"
#include "uart.h"
// The ADS1220 RTD Gain Calibration is intended to be performed once for any system.
// The results will be stored in ADS1220RTDGainCorrection
const long ADS1220RTDGainCorrection = 100000; //99938; // RTD Gain correction factor; needs to be calculated once for any system
// The ADS1220 TC Gain Calibration is intended to be performed once for any system.
// The results will be stored in ADS1220TCGainCorrection
const long ADS1220TCGainCorrection = 100000; //99986; // TC Gain correction factor; needs to be calculated once for any system
volatile unsigned char buttonDebounce, ReadConversionData = 0;
void portsInit (void);
void startWDT(void);
void ucsInit(void);
//=================================================================================================================================================
//Main
//=================================================================================================================================================
void main (void)
{
static volatile unsigned char tempData[3];
volatile long ADS1220RTDdata, RTDtemperature, TCvoltage, CJCcode, TCtemperature, ADS1220temperature, ADS1220TCdata;
volatile long ADS1220code;
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
portsInit ();
ucsInit();
__enable_interrupt();
// Configure the SPI components
Setup_SPI_Master ();
// Reset the ADS1220
ADS1220_Reset();
// Configure ADS1220 for first measurement
Setup_ADS1220 (ADS1220_MUX_AIN3_AIN2, ADS1220_OP_MODE_NORMAL,
ADS1220_CONVERSION_SINGLE_SHOT, ADS1220_DATA_RATE_20SPS, ADS1220_GAIN_32, ADS1220_USE_PGA,
ADS1220_IDAC1_AIN3, ADS1220_IDAC2_AIN2, ADS1220_IDAC_CURRENT_250_UA, ADS1220_VREF_EXT_REF0_PINS, ADS1220_TEMP_SENSOR_OFF);
// Delay 500ms to allow for IDAC and Input Filter settling
__delay_cycles(CPU_CLK/2);
#ifdef UART_ENABLE
uart_puts ("ADS1220temperature RTDtemperature TCtemperature");
uart_puts ("\r\n");
uart_puts ("\r\n");
#endif
LED_POUT |= LED_GREEN_BIT;
// Configure ADS1220 for first RTD measurement
Setup_ADS1220 (ADS1220_MUX_AIN3_AIN2, ADS1220_OP_MODE_NORMAL,
ADS1220_CONVERSION_SINGLE_SHOT, ADS1220_DATA_RATE_20SPS, ADS1220_GAIN_32, ADS1220_USE_PGA,
ADS1220_IDAC1_AIN3, ADS1220_IDAC2_AIN2, ADS1220_IDAC_CURRENT_250_UA, ADS1220_VREF_EXT_REF0_PINS, ADS1220_TEMP_SENSOR_OFF);
while (1)
{
__delay_cycles(CPU_CLK/10);
ReadConversionData = 0;
ADS1220_Start ();
while (!ReadConversionData); // Wait for Data Ready interrupt
ADS1220_Get_RTD_Conversion_Data_Calibrated (&ADS1220RTDdata); // Get the temperature data with the calibration value subtracted
// Configure ADS1220 for second chopped RTD measurement
Setup_ADS1220 (ADS1220_MUX_AIN2_AIN3, ADS1220_OP_MODE_NORMAL,
ADS1220_CONVERSION_SINGLE_SHOT, ADS1220_DATA_RATE_20SPS, ADS1220_GAIN_32, ADS1220_USE_PGA,
ADS1220_IDAC1_AIN2, ADS1220_IDAC2_AIN3, ADS1220_IDAC_CURRENT_250_UA, ADS1220_VREF_EXT_REF0_PINS, ADS1220_TEMP_SENSOR_OFF);
RTDtemperature = ADS1220RTDdata;
__delay_cycles(CPU_CLK/10); //
ReadConversionData = 0;
ADS1220_Start (); // Only one start needed for Continuous Mode
while (!ReadConversionData); // Wait for Data Ready interrupt
ADS1220_Get_RTD_Conversion_Data_Calibrated (&ADS1220RTDdata); // Get the temperature data with the calibration value subtracted
// Configure ADS1220 for first Thermocouple measurements
Setup_ADS1220 (ADS1220_MUX_AIN0_AIN1, ADS1220_OP_MODE_NORMAL,
ADS1220_CONVERSION_SINGLE_SHOT, ADS1220_DATA_RATE_20SPS, ADS1220_GAIN_32, ADS1220_USE_PGA,
ADS1220_IDAC1_AIN3, ADS1220_IDAC2_AIN2, ADS1220_IDAC_CURRENT_250_UA, ADS1220_VREF_INTERNAL, ADS1220_TEMP_SENSOR_OFF);
RTDtemperature += ADS1220RTDdata; //now averaging RTD results
RTDtemperature = RTDtemperature/2;
RTDtemperature = interpolateRTDTemperatureValue (RTDtemperature); // Get the RTD temperature and convert into millidegrees C
//cold junction compensation
CJCcode = calc_CJC(RTDtemperature); // convert RTD temperature into thermocouple voltage
__delay_cycles(CPU_CLK/10); //
ReadConversionData = 0;
ADS1220_Start ();
while (!ReadConversionData); // Wait for Data Ready interrupt
ADS1220_Get_TC_Conversion_Data_Calibrated (&ADS1220TCdata); // Get the temperature data with the calibration value subtracted
TCtemperature = ADS1220TCdata/2;
// Configure ADS1220 for second chopped Thermocouple measurements
Setup_ADS1220 (ADS1220_MUX_AIN1_AIN0, ADS1220_OP_MODE_NORMAL,
ADS1220_CONVERSION_SINGLE_SHOT, ADS1220_DATA_RATE_20SPS, ADS1220_GAIN_32, ADS1220_USE_PGA,
ADS1220_IDAC1_AIN3, ADS1220_IDAC2_AIN2, ADS1220_IDAC_CURRENT_250_UA, ADS1220_VREF_INTERNAL, ADS1220_TEMP_SENSOR_OFF);
__delay_cycles(CPU_CLK/10);
ReadConversionData = 0;
ADS1220_Start (); // Only one start needed for Continuous Mode
while (!ReadConversionData); // Wait for Data Ready interrupt
ADS1220_Get_TC_Conversion_Data_Calibrated (&ADS1220TCdata); // Get the temperature data with the calibration value subtracted
ADS1220TCdata = ADS1220TCdata/2;
TCtemperature -= ADS1220TCdata;
TCtemperature += CJCcode; //CJC
TCtemperature = interpolateTCTemperatureValue (TCtemperature); // Get the temperature and convert into millidegrees C
// measure internal Temperature Sensor
Setup_ADS1220 (ADS1220_MUX_AIN1_AIN0, ADS1220_OP_MODE_NORMAL,
ADS1220_CONVERSION_SINGLE_SHOT, ADS1220_DATA_RATE_20SPS, ADS1220_GAIN_32, ADS1220_USE_PGA,
ADS1220_IDAC1_AIN3, ADS1220_IDAC2_AIN2, ADS1220_IDAC_CURRENT_250_UA, ADS1220_VREF_INTERNAL, ADS1220_TEMP_SENSOR_ON);
__delay_cycles(CPU_CLK/10);
ReadConversionData = 0;
ADS1220_Start (); // Only one start needed for Continuous Mode
while (!ReadConversionData); // Wait for Data Ready interrupt
ADS1220_Get_Conversion_Data((unsigned char *)tempData);
// Configure ADS1220 for next RTD measurement
Setup_ADS1220 (ADS1220_MUX_AIN3_AIN2, ADS1220_OP_MODE_NORMAL,
ADS1220_CONVERSION_SINGLE_SHOT, ADS1220_DATA_RATE_20SPS, ADS1220_GAIN_32, ADS1220_USE_PGA,
ADS1220_IDAC1_AIN3, ADS1220_IDAC2_AIN2, ADS1220_IDAC_CURRENT_250_UA, ADS1220_VREF_EXT_REF0_PINS, ADS1220_TEMP_SENSOR_OFF);
ADS1220code = (((long)tempData[0] << 16) + ((long)tempData[1] << 8) + (long)tempData[2]) >> 10; // take 3 bytes of voltage returned and place in word
if(ADS1220code & 0x2000) // check if 14-bit temperature result is negative
{
ADS1220code -= 1; // invert and make
ADS1220code ^= 0x3FFF; // two's complement
ADS1220temperature = ((-1000)*ADS1220code)/32;
}
else
{
ADS1220temperature = (1000*ADS1220code)/32;
}
#ifdef UART_ENABLE
uart_putLong(ADS1220temperature);
uart_puts (" ");
uart_putLong(RTDtemperature);
uart_puts (" ");
uart_putLong(TCtemperature);
uart_puts ("\r\n");
#endif
}
}
/*************************************************************************************************************************************************
* portsInit
**************************************************************************************************************************************************/
/*!
* @brief Initialize the GPIO pins on the MSP430FR5949 for use with ADS1220
*
* This function is called once to configure the GPIO pins on the system.
*
* @return none
**************************************************************************************************************************************************/
void portsInit (void)
{
P1OUT &= ~UNUSED_P1_BITS;
P1DIR |= UNUSED_P1_BITS;
P2OUT &= ~UNUSED_P2_BITS;
P2DIR |= UNUSED_P2_BITS;
P3OUT &= ~UNUSED_P3_BITS;
P3DIR |= UNUSED_P3_BITS;
P4OUT &= ~UNUSED_P4_BITS;
P4DIR |= UNUSED_P4_BITS;
PJOUT &= ~UNUSED_PJ_BITS;
PJDIR |= UNUSED_PJ_BITS;
//initialize LEDs
LED_POUT &= ~(LED_RED_BIT + LED_GREEN_BIT + LED_YELLOW_BIT);
LED_PDIR |= (LED_RED_BIT + LED_GREEN_BIT + LED_YELLOW_BIT);
//ADS1220 nDRDY Interrupt
P1IES |= (ADS_DRDY_N_BIT); // High to Low Edge
P1IFG &= ~(ADS_DRDY_N_BIT); // Clear any previous interrupt
P1IE |= (ADS_DRDY_N_BIT);
ADS_CS_N_POUT |= ADS_CS_N_BIT;
ADS_CS_N_PDIR |= ADS_CS_N_BIT;
P2SEL0 &= ~(ADS_CLK_BIT + ADS_DIN_BIT + ADS_DOUT_BIT);
P2SEL1 |= (ADS_CLK_BIT + ADS_DIN_BIT + ADS_DOUT_BIT);
//Switch SW1 and SW2 Interrupt
P4OUT |= (SW1_INTERRUPT_N_BIT + SW2_INTERRUPT_N_BIT);
P4REN |= (SW1_INTERRUPT_N_BIT + SW2_INTERRUPT_N_BIT); //pullup
P4IES |= (SW1_INTERRUPT_N_BIT + SW2_INTERRUPT_N_BIT); // High to Low Edge
//Initialize buttons
buttonDebounce = 1;
#ifdef UART_ENABLE
P2SEL0 &= ~(USCIA0_RX_BIT + USCIA0_TX_BIT);
P2SEL1 |= (USCIA0_RX_BIT + USCIA0_TX_BIT);
// Configure USCI_A0 for UART mode
UCA0CTLW0 = UCSWRST; // Put eUSCI in reset
UCA0CTLW0 |= UCSSEL__SMCLK; // CLK = SMCLK
// Baud Rate calculation
// 8000000/(16*9600) = 52.083
// Fractional portion = 0.083
// User's Guide Table 21-4: UCBRSx = 0x04
// UCBRFx = int ( (52.083-52)*16) = 1
UCA0BR0 = 52; // 8000000/16/9600
UCA0BR1 = 0x00;
UCA0MCTLW |= UCOS16 | UCBRF_1;
UCA0CTLW0 &= ~UCSWRST; // Initialize eUSCI
//UCA0IE |= UCRXIE; // Enable USCI_A0 RX interrupt
#else
P2OUT &= ~(USCIA0_RX_BIT + USCIA0_TX_BIT);
P2DIR |= (USCIA0_RX_BIT + USCIA0_TX_BIT);
#endif
// Disable the GPIO power-on default high-impedance mode to activate
// previously configured port settings
PM5CTL0 &= ~LOCKLPM5;
P4IFG = 0x00; // Clear any previous interrupt
P4IE |= (SW1_INTERRUPT_N_BIT + SW2_INTERRUPT_N_BIT);
}
//------------------------------------------------------------------------------
// void ucsInit(void)
//
// DESCRIPTION:
// MSP430 System Clock Init 8MHz
// Note: This function is for MSP430FR5949 & might need modifications for other MSP430s
//------------------------------------------------------------------------------
void ucsInit(void)
{
// Clock System Setup
CSCTL0_H = CSKEY >> 8; // Unlock CS registers
CSCTL1 = DCOFSEL_6; // Set DCO to 8MHz
CSCTL2 = SELA__VLOCLK | SELS__DCOCLK | SELM__DCOCLK; // Set SMCLK = MCLK = DCO
// ACLK = VLOCLK
//ToDo: use 32kHz clock?
CSCTL3 = DIVA__1 | DIVS__1 | DIVM__1; // Set all dividers to 1
CSCTL0_H = 0; // Lock CS registers
}
/**************************************************************************************************************************************************
* startWDT
**************************************************************************************************************************************************/
/*!
* @start WDT as interval counter
*
*
* @return None
**************************************************************************************************************************************************/
void startWDT(void)
{
SFRIFG1 &= ~WDTIFG;
WDTCTL = WDT_ADLY_16; // WDT, ACLK, interval timer
SFRIE1 |= WDTIE;
}
/**************************************************************************************************************************************************
* WDT_ISR
**************************************************************************************************************************************************/
/*!
* @brief WDT Interrupt Routine
*
*
* @return None
**************************************************************************************************************************************************/
#pragma vector=WDT_VECTOR
__interrupt void WDT_ISR(void)
{
if (buttonDebounce == 2)
{
buttonDebounce = 1;
SFRIFG1 &= ~WDTIFG;
SFRIE1 &= ~WDTIE;
WDTCTL = WDTPW + WDTHOLD;
}
}
/**************************************************************************************************************************************************
* PORT1_ISR
**************************************************************************************************************************************************/
/*!
* @brief Port 1 Interrupt Routine
*
*
* @return None
**************************************************************************************************************************************************/
#pragma vector = PORT1_VECTOR
__interrupt void PORT1_ISR (void)
{
unsigned char interrupts = ADS_DRDY_N_PIFG;
P1IFG = 0;
// Has a Data Ready occurred from the ADS1220?
if (interrupts & ADS_DRDY_N_BIT)
{
ReadConversionData = 1;
//__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}
}
/**************************************************************************************************************************************************
* PORT4_ISR
**************************************************************************************************************************************************/
/*!
* @brief Port 4 Interrupt Routine
*
*
* @return None
**************************************************************************************************************************************************/
#pragma vector = PORT4_VECTOR
__interrupt void PORT4_ISR (void)
{
unsigned char interrupts = P4IFG;
if (buttonDebounce == 1)
{
buttonDebounce = 2;
startWDT();
// SW1 pressed?
if (interrupts & SW1_INTERRUPT_N_BIT)
{
//insert function for SW1
LED_POUT ^= LED_YELLOW_BIT;
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}
// SW2 pressed?
if (interrupts & SW2_INTERRUPT_N_BIT)
{
//insert function for SW2
LED_POUT ^= LED_RED_BIT;
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}
}
P4IFG = 0;
}
[/mw_shl_code] |
|