⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 emeter-setup.c

📁 msp430F437三相电表DEMO(编译器 IAR 3.42A)
💻 C
📖 第 1 页 / 共 3 页
字号:
//--------------------------------------------------------------------------
//
//  Software for MSP430 based e-meters.
//
//  You may not use the Program in non-TI devices.
//
//  File: emeter-setup.c
//
//  Steve Underwood <steve-underwood@ti.com>
//  Texas Instruments Hong Kong Ltd.
//
//  $Id: emeter-setup.c,v 1.23 2005/12/20 10:17:57 a0754793 Exp $
//
/*! \file emeter-structs.h */
//
//--------------------------------------------------------------------------
//
//  MSP430 setup routines for e-meters.
//
//  This software is appropriate for single phase and three phase e-meters
//  using a voltage sensor plus CT or shunt resistor current sensors, or
//  a combination of a CT plus a shunt. 
//
#include <stdint.h>
#include <string.h>
#if !defined(__MSP430__)
#include <stdio.h>
#include <stdlib.h>
#endif
#if defined(__GNUC__)
#include <signal.h>
#endif
#include <io.h>
#include <emeter-toolkit.h>
#include "emeter.h"
#include "emeter-structs.h"

#if defined(__MSP430_HAS_SD16_3__)

#define SD16CONF0_FUDGE     0xC0    //0x70  //0xC0
#define SD16CONF1_FUDGE     0x40    //0x38  //0x40

/*
 * Analog front-end initialization routine.
 *
 * Configures the sigma-delta ADC module as analog front-end for
 * a tamper-resistant meter using a current transformer and a
 * shunt as current sensors (see configuration of channel 0 and 1).
 */
static __inline__ void init_analog_front_end_normal(void)
{
    /*
     * First it makes sure that the Embedded Signal Processing is 
     * disabled, otherwise it will not be possible to modify the 
     * SD16 registers.
     */
    ESPCTL &= ~ESPEN;

    /*
     * Then the general configurations of the analog front-end are done
     * that apply to all channels: clock selection (SMCLK) and divider
     * settings (depending on SMCLK frequency) and reference voltage
     * selections.
     */

    SD16CCTL_VOLTAGE &= ~SD16SC;
    SD16CCTL_LIVE &= ~SD16SC;
    #if defined(SINGLE_PHASE)  &&  defined(NEUTRAL_MONITOR_SUPPORT)
    SD16CCTL_NEUTRAL &= ~SD16SC;
    #endif

    #if defined(SINGLE_PHASE)
    SD16CTL = 0x800
            | SD16SSEL_1  /* Clock is SMCLK */
            | SD16DIV_3   /* Divide by 8 => ADC clock: 1.048576MHz */
            | SD16REFON;  /* Use internal reference */
    SD16INCTL_LIVE = SD16INCH_0 | CURRENT_LIVE_GAIN;            /* Set gain for channel 0 (I1) */
    SD16CCTL_LIVE = SD16OSR_256 | SD16DF | SD16GRP | SD16IE;    /* Set oversampling ratio to 256 (default) */
    SD16PRE_LIVE = 0;

        #if defined(NEUTRAL_MONITOR_SUPPORT)
    SD16INCTL_NEUTRAL = SD16INCH_0 | CURRENT_NEUTRAL_GAIN;      /* Set gain for channel 1 (I2) */
    SD16CCTL_NEUTRAL = SD16OSR_256 | SD16DF | SD16GRP | SD16IE; /* Set oversampling ratio to 256 (default) */
    SD16PRE_NEUTRAL = 0;
        #endif

    /* Configure analog front-end channel 2 - Voltage */
    SD16INCTL_VOLTAGE = SD16INCH_0 | VOLTAGE_GAIN;              /* Set gain for channel 2 (V) */
    SD16CCTL_VOLTAGE = SD16OSR_256 | SD16DF | SD16SC | SD16IE;  /* Set oversampling ratio to 256 (default) */
    SD16PRE_VOLTAGE = 0;
    #else
    SD16CTL = 0x800
            | SD16SSEL_1  /* Clock is SMCLK */
            | SD16DIV_0   /* Divide by 1 => ADC clock: 8*1.048576MHz */
            | SD16REFON;  /* Use internal reference */

    SD16INCTL0 = SD16INCH_0 | SD16GAIN_1;
    SD16CCTL0 = SD16OSR_128 | SD16DF | SD16SNGL | SD16GRP | SD16IE;
    SD16PRE0 = 0;

    SD16INCTL1 = SD16INCH_0 | SD16GAIN_1;
    SD16CCTL1 = SD16OSR_128 | SD16DF | SD16SNGL | SD16GRP | SD16IE;
    SD16PRE1 = 0;

    SD16INCTL_VOLTAGE = SD16INCH_0 | SD16GAIN_1;
    SD16CCTL_VOLTAGE = SD16OSR_128 | SD16DF | SD16SNGL | SD16IE;
    SD16PRE_VOLTAGE = 0;

    SD16CCTL2 |= SD16SC;
    #endif

    SD16CONF0 = SD16CONF0_FUDGE;                /* Tweaks recommended by Freising */
    SD16CONF1 = SD16CONF1_FUDGE;

    #if defined(SINGLE_PHASE)
    chan1.current.sd16_preloaded_offset = 0;
        #if defined(NEUTRAL_MONITOR_SUPPORT)
    chan1.neutral.sd16_preloaded_offset = 0;
        #endif
    #endif
    /*
     * \note 
     * Please note, the oversampling ratio should be the same 
     * for all channels. Default is 256.
     */
}

    #if defined(LIMP_MODE_SUPPORT)
static __inline__ void init_analog_front_end_limp(void)
{
    ESPCTL &= ~ESPEN;
    SD16CCTL_VOLTAGE &= ~SD16SC;
    SD16CCTL_LIVE &= ~SD16SC;
        #if defined(SINGLE_PHASE)  &&  defined(NEUTRAL_MONITOR_SUPPORT)
    SD16CCTL_NEUTRAL &= ~SD16SC;
        #endif
    SD16CTL = 0x800
            | SD16SSEL_1  /* Clock is SMCLK */
            | SD16DIV_3   /* Divide by 8 => ADC clock: 1.048576MHz */
            | SD16REFON   /* Use internal reference */
            | SD16LP;
    SD16INCTL_LIVE = SD16INCH_0 | CURRENT_LIVE_GAIN;                        /* Set gain for channel 0 (I1) */
    SD16CCTL_LIVE = SD16OSR_32 | SD16DF | SD16SNGL | SD16GRP | SD16IE;      /* Set oversampling ratio to 32 */
    SD16PRE_LIVE = 0;
    #if defined(SINGLE_PHASE)  &&  defined(NEUTRAL_MONITOR_SUPPORT)
    SD16INCTL_NEUTRAL = SD16INCH_0 | CURRENT_NEUTRAL_GAIN;                  /* Set gain for channel 1 (I2) */
    SD16CCTL_NEUTRAL = SD16OSR_32 | SD16DF | SD16SNGL | SD16GRP | SD16IE;   /* Set oversampling ratio to 32 */
    SD16PRE_NEUTRAL = 0;
    #endif
    SD16INCTL_VOLTAGE = SD16INCH_0 | VOLTAGE_GAIN;                  /* Set gain for channel 2 (V) */
    SD16CCTL_VOLTAGE = SD16OSR_32 | SD16DF | SD16SNGL | SD16IE;     /* Set oversampling ratio to 32 */
    SD16PRE_VOLTAGE = 0;
    SD16CONF0 = SD16CONF0_FUDGE;                                    /* Tweaks recommended by Freising */
    SD16CONF1 = SD16CONF1_FUDGE;

    chan1.current.sd16_preloaded_offset = 0;
        #if defined(SINGLE_PHASE)  &&  defined(NEUTRAL_MONITOR_SUPPORT)
    chan1.neutral.sd16_preloaded_offset = 0;
        #endif
}
    #endif

static __inline__ void disable_analog_front_end(void)
{
    ESPCTL &= ~ESPEN;

    SD16INCTL_VOLTAGE = 0;
    SD16CCTL_VOLTAGE = 0;
    SD16PRE_VOLTAGE = 0;

    SD16INCTL_LIVE = 0;
    SD16CCTL_LIVE = 0;
    SD16PRE_LIVE = 0;

    #if defined(SINGLE_PHASE)  &&  defined(NEUTRAL_MONITOR_SUPPORT)
    SD16INCTL_NEUTRAL = 0;
    SD16CCTL_NEUTRAL = 0;
    SD16PRE_NEUTRAL = 0;
    #endif

    SD16CTL = 0;

    SD16CONF0 = SD16CONF0_FUDGE;
    SD16CONF1 = SD16CONF1_FUDGE;

    #if defined(SINGLE_PHASE)
    chan1.current.sd16_preloaded_offset = 0;
        #if defined(NEUTRAL_MONITOR_SUPPORT)
    chan1.neutral.sd16_preloaded_offset = 0;
        #endif
    #endif
}
#endif

#if defined(__MSP430__)
void system_setup(void)
{
    #if !defined(SINGLE_PHASE)
    struct phase_parms_s *phase;
    struct phase_nv_parms_s const *phase_nv;
    int j;
    #endif

    #if defined(__MSP430_HAS_BT__)  ||  defined(__MSP430_HAS_BT_RTC__)
    /* Basic timer setup */
    /* Set ticker to 32768/(256*256) */
        #if defined(__MSP430_HAS_BT__)
    BTCTL = BT_fLCD_DIV64 | BT_fCLK2_DIV128 | BT_fCLK2_ACLK_DIV256;
        #else
    BTCTL = BT_fCLK2_DIV128 | BT_fCLK2_ACLK_DIV256;
        #endif
    /* Enable the 1 second counter interrupt */
    IE2 |= BTIE;

    /* We want a real watchdog function, but it doesn't have to be fast. */
    /* Use the longest timer - 1s */
        #if USE_WATCHDOG
    kick_watchdog();    /* Set the watchdog timer to exactly 1s */
        #else
    WDTCTL = (WDTCTL & 0xFF) | WDTPW | WDTHOLD;
        #endif
    #else
    IE1 |= WDTIE;               /* Enable the WDT interrupt */
    #endif

    #if (defined(BASIC_LCD_SUPPORT)  ||  defined(CUSTOM_LCD_SUPPORT))
    LCDinit();
    custom_lcd_init();
        #if defined(LCD_INIT)  &&  defined(__MSP430_HAS_LCD4__)
    LCDCTL = LCD_INIT;
        #endif
        #if defined(LCDACTL_INIT)  &&  defined(__MSP430_HAS_LCD_A__)
    LCDACTL = LCDACTL_INIT;
    LCDAPCTL0 = LCDAPCTL0_INIT;
    LCDAPCTL1 = LCDAPCTL1_INIT;
    LCDAVCTL0 = LCDAVCTL0_INIT;
    LCDAVCTL1 = LCDAVCTL1_INIT;
        #endif
    #endif

    #if defined(P1OUT_INIT)
    P1OUT = P1OUT_INIT;
    #endif
    #if defined(P1DIR_INIT)
    P1DIR = P1DIR_INIT;
    #endif
    #if defined(P1SEL_INIT)
    P1SEL = P1SEL_INIT;
    #endif

    #if defined(P2OUT_INIT)
    P2OUT = P2OUT_INIT;
    #endif
    #if defined(P2DIR_INIT)
    P2DIR = P2DIR_INIT;
    #endif
    #if defined(P2SEL_INIT)
    P2SEL = P2SEL_INIT;
    #endif

    #if defined(P3OUT_INIT)
    P3OUT = P3OUT_INIT;
    #endif
    #if defined(P3DIR_INIT)
    P3DIR = P3DIR_INIT;
    #endif
    #if defined(P3SEL_INIT)
    P3SEL = P3SEL_INIT;
    #endif

    #if defined(P4OUT_INIT)
    P4OUT = P4OUT_INIT;
    #endif
    #if defined(P4DIR_INIT)
    P4DIR = P4DIR_INIT;
    #endif
    #if defined(P4SEL_INIT)
    P4SEL = P4SEL_INIT;
    #endif

    #if defined(P5OUT_INIT)
    P5OUT = P5OUT_INIT;
    #endif
    #if defined(P5DIR_INIT)
    P5DIR = P5DIR_INIT;
    #endif
    #if defined(P5SEL_INIT)
    P5SEL = P5SEL_INIT;
    #endif

    #if defined(P6OUT_INIT)
    P6OUT = P6OUT_INIT;
    #endif
    #if defined(P6DIR_INIT)
    P6DIR = P6DIR_INIT;
    #endif
    #if defined(P6SEL_INIT)
    P6SEL = P6SEL_INIT;
    #endif

    #if defined(IO_EXPANDER_SUPPORT)
    set_io_expander(0, 0);
    #endif
    
    #if defined(BASIC_LCD_SUPPORT)
    display_startup_message();
    #endif

    #if defined(__MSP430_HAS_DCO__)
    /* Set up the DCO clock */
    BCSCTL1 |= (RSEL0 | RSEL1 | RSEL2); /* Select the highest nominal freq */
    BCSCTL2 |= DCOR;                    /* Select the external clock control resistor pin */
    DCOCTL = 0xFF;                      /* Select the highest speed. */
    #endif
    #if defined(__MSP430_HAS_FLLPLUS__)  ||  defined(__MSP430_HAS_FLLPLUS_SMALL__)
    FLL_CTL0 |= XCAP10PF;               /* Configure load caps */
        #if defined(XT2OFF)
    FLL_CTL1 |= XT2OFF;
        #endif
    SCFI0 = FLLD_1;                     /* Freq = 1.024MHz */
    SCFQCTL = 32 - 1;
    FLL_CTL0 |= DCOPLUS;
    /* There seems no benefit in waiting for the FLL to settle at this point. */
    #endif

    #if defined(LIMP_MODE_SUPPORT)
    samples_per_second = LIMP_SAMPLES_PER_10_SECONDS/10;
    #else
    samples_per_second = SAMPLES_PER_10_SECONDS/10;
    #endif

    #if defined(__MSP430_HAS_TA3__)  &&  defined(__MSP430_HAS_ADC12__)
    /* Use timer A to control the ADC sampling interval, and the ADC on/off timing. */
    /* TACCR0 determines the sample period */
    TAR = 0;
        #if defined(LIMP_MODE_SUPPORT)
    TACCR0 = (SAMPLE_PERIOD*LIMP_SAMPLING_RATIO) - 1;
    TACCR1 = (SAMPLE_PERIOD*LIMP_SAMPLING_RATIO) - 3;
    TACCR2 = (SAMPLE_PERIOD*LIMP_SAMPLING_RATIO) - 4;
        #else
    TACCR0 = SAMPLE_PERIOD - 1;
    TACCR1 = SAMPLE_PERIOD - 3;
    TACCR2 = SAMPLE_PERIOD - 4;
        #endif
    TACCTL0 = 0;
    TACCTL1 = OUTMOD_3;
        #if defined(FINE_ENERGY_PULSE_TIMING_SUPPORT)
    TACCTL2 = OUTMOD_0 | OUT;           /* Turn off the pulse LED */
        #endif    
    TACTL = TACLR | MC_1 | TASSEL_1;
    #endif

    #if defined(__MSP430_HAS_TA3__)  &&  defined(__MSP430_HAS_SD16_3__)
    /* Use timer A to control the ADC sampling interval in limp mode. */
    /* CCR0 determines the sample period - 1024Hz */
    TAR = 0;
    TACCR0 = 32 - 1;
    TACCTL0 = 0;
    TACCTL1 = OUTMOD_3;
    TACTL = TACLR | MC_1 | TASSEL_1;
    #endif

    #if defined(PWM_DITHERING_SUPPORT)
    /* Configure timer B to generate a dithering signal, to be added to the     */
    /* analogue signals, something like this.                                   */
    /*                                                                          */
    /*   -----------------                100n                                  */
    /*                    |    __47k_     ||    __1M__       __4K7__            */
    /*                TB1 |->-|______|-- -||---|______|->---|_______|--< Signal */
    /*                    |             | ||              |                     */
    /*                    |           -----               |                     */
    /*                    |           -----2n2            |                     */
    /*                    |             |                 |                     */
    /*                    |            GND                |                     */
    /*                    |                               |                     */
    /*                A0  |-<-----------------------------                      */
    /*                    |                                                     */
    P2SEL |= BIT2;                      /* Select P2.2 for PWM output */
    P2DIR |= BIT2;                      /* Select P2.2 for PWM output */

    TBR = 0;
    TBCCR0 = PWM_FREQ - 1;              /* load period register */
    TBCCR1 = PWM_MID_POINT;             /* start with 50% PWM duty cycle */
    TBCCR2 = PWM_FREQ - 1;
    TBCCTL0 = OUTMOD_4;                 /* set outmode 4 for toggle */
    TBCCTL1 = OUTMOD_6 | CLLD_1;        /* set outmode 6 Toggle/set */
                                        /* load new CCR1 when TBR = 0 */
    TBCCTL2 = OUTMOD_4;
    TBCTL = TBCLR | MC_1 | TBSSEL_2;    /* start TIMER_B up mode, SMCLK as input clock */
    #endif

    #if defined(__MSP430_HAS_ADC12__)
    /* Set up the ADC12 */
    /* Disable conversion while changing the settings */
    ADC12CTL0 = 0;
        #if defined(SINGLE_PHASE)
    ADC12MCTL0 = SREF_0 | AGND_INPUT;
    ADC12MCTL1 = SREF_0 | NEUTRAL_CURRENT_INPUT;
    ADC12MCTL2 = SREF_0 | AGND_INPUT;
    ADC12MCTL3 = SREF_0 | LIVE_CURRENT_INPUT;
    ADC12MCTL4 = SREF_0 | AGND_INPUT;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -