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

📄 emeter-foreground.c

📁 msp430F437三相电表DEMO(编译器 IAR 3.42A)
💻 C
📖 第 1 页 / 共 4 页
字号:
//--------------------------------------------------------------------------
//
//  Software for MSP430 based e-meters.
//
//  File: emeter-foreground.c
//
//  Steve Underwood <steve-underwood@ti.com>
//  Texas Instruments Hong Kong Ltd.
//
//  $Id: emeter-foreground.c,v 1.22 2005/12/20 10:17:57 a0754793 Exp $
//
/*! \file emeter-structs.h */
//
//--------------------------------------------------------------------------
//
//  MSP430 foreground (non-interrupt) routines for e-meters
//
//  This software is appropriate for single phase and three phase e-meters
//  using a voltage sensor plus a CT or shunt resistor current sensors, or
//  a combination of a CT plus a shunt. 
// 
//    Foreground process includes:
//    -Using timer tick to wait
//    -Calculating the power per channel
//    -Determine if current channel needs scaling.
//    -Determine if needs to be in low power modes.
//    -Compensate reference from temperature sensor
//
#include <stdint.h>
#include <stdlib.h>

#include <math.h>
#include <io.h>

#include <emeter-toolkit.h>
#define __MAIN_PROGRAM__
#include "emeter.h"
#include "emeter-structs.h"

#if defined(TOTAL_ENERGY_SUPPORT)
unsigned char total_energy_pulse_remaining_time;
long int total_power;
long int total_power_counter;
    #if TOTAL_ENERGY_PULSES_PER_KW_HOUR < 1000
int extra_total_power_counter;
    #endif
unsigned long int total_consumed_energy;
#endif

#if defined(TOTAL_REACTIVE_ENERGY_SUPPORT)
unsigned char total_reactive_energy_pulse_remaining_time;
long int total_reactive_power;
long int total_reactive_power_counter;
    #if TOTAL_ENERGY_PULSES_PER_KW_HOUR < 1000
int extra_total_reactive_power_counter;
    #endif
unsigned long int total_consumed_reactive_energy;
#endif

#if 0 //CUSTOM_LCD_SUPPORT
/* Keep the toolkit library happy */
const int lcd_cells = LCD_CELLS;
const int lcd_pos_base = LCD_POS_BASE;
const int lcd_pos_step = LCD_POS_STEP;
#endif

#if defined(TEMPERATURE_SUPPORT)
unsigned int temperature;
#endif

#if defined(CORRECTED_RTC_SUPPORT)
long int rtc_correction;
#endif

/* Meter status flag bits. */
unsigned int meter_status;

/* Current operating mode - normal, limp, power down, etc. */
signed char operating_mode;

/* Persistence check counters for anti-tamper measures. */
#if defined(PHASE_REVERSED_DETECTION_SUPPORT)
signed char current_reversed;
#endif
#if defined(POWER_BALANCE_DETECTION_SUPPORT)
signed char current_unbalanced;
#endif
#if defined(MAGNETIC_INTERFERENCE_SUPPORT)
signed char magnetic_interference_persistence;
#endif

/* The main per-phase working parameter structure */
#if !defined(SINGLE_PHASE)
struct phase_parms_s chan[NUM_PHASES];
    #if defined(NEUTRAL_MONITOR_SUPPORT)
struct neutral_parms_s neutral;
    #endif
#else
struct phase_parms_s chan1;
#endif

/* The main per-phase non-volatile parameter structure */
__infomem__ const struct info_mem_s nv_parms =
{
    {
    {
        0xFFFF,
#if SELF_TEST_SUPPORT
        0xFFFF,
        0xFFFF,
#endif
#if !defined(SINGLE_PHASE)
        {
#endif
            {
                {
#if defined(IRMS_SUPPORT)
                    {DEFAULT_I_RMS_SCALE_FACTOR},
    #if defined(LIMP_MODE_SUPPORT)
                    {DEFAULT_I_RMS_LIMP_SCALE_FACTOR},
    #endif
                    0,
#endif
                    {DEFAULT_P_SCALE_FACTOR_A_LOW, DEFAULT_P_SCALE_FACTOR_A_HIGH},
                    DEFAULT_I_DC_ESTIMATE << 16,
#if defined(PHASE_CORRECTION_SUPPORT)
                    {DEFAULT_BASE_PHASE_A_CORRECTION_LOW, DEFAULT_BASE_PHASE_A_CORRECTION_HIGH},
#endif
                },
#if defined(VRMS_SUPPORT)
                DEFAULT_V_RMS_SCALE_FACTOR,
    #if defined(LIMP_MODE_SUPPORT)
                DEFAULT_V_RMS_LIMP_SCALE_FACTOR,
    #endif
#endif
                DEFAULT_V_DC_ESTIMATE << 16,
#if defined(LIMP_MODE_SUPPORT)
                DEFAULT_V_LIMP_DC_ESTIMATE << 16,
#endif
            },
#if !defined(SINGLE_PHASE)
            {
                {
    #if defined(IRMS_SUPPORT)
                    {DEFAULT_I_RMS_SCALE_FACTOR},
        #if defined(LIMP_MODE_SUPPORT)
                    {DEFAULT_I_RMS_LIMP_SCALE_FACTOR},
        #endif
                    0,
    #endif
                    {DEFAULT_P_SCALE_FACTOR_B_LOW, DEFAULT_P_SCALE_FACTOR_B_HIGH},
                    DEFAULT_I_DC_ESTIMATE << 16,
    #if defined(PHASE_CORRECTION_SUPPORT)
                    {DEFAULT_BASE_PHASE_B_CORRECTION_LOW, DEFAULT_BASE_PHASE_B_CORRECTION_HIGH},
    #endif
                },
    #if defined(VRMS_SUPPORT)
                DEFAULT_V_RMS_SCALE_FACTOR,
        #if defined(LIMP_MODE_SUPPORT)
                DEFAULT_V_RMS_LIMP_SCALE_FACTOR,
        #endif
    #endif
                DEFAULT_V_DC_ESTIMATE << 16,
    #if defined(LIMP_MODE_SUPPORT)
                DEFAULT_V_LIMP_DC_ESTIMATE << 16,
    #endif
            },
            {
                {
    #if defined(IRMS_SUPPORT)
                    {DEFAULT_I_RMS_SCALE_FACTOR},
        #if defined(LIMP_MODE_SUPPORT)
                    {DEFAULT_I_RMS_LIMP_SCALE_FACTOR},
        #endif
                    0,
    #endif
                    {DEFAULT_P_SCALE_FACTOR_C_LOW, DEFAULT_P_SCALE_FACTOR_C_HIGH},
                    DEFAULT_I_DC_ESTIMATE << 16,
    #if defined(PHASE_CORRECTION_SUPPORT)
                    {DEFAULT_BASE_PHASE_C_CORRECTION_LOW, DEFAULT_BASE_PHASE_C_CORRECTION_HIGH},
    #endif
                },
    #if defined(VRMS_SUPPORT)
                DEFAULT_V_RMS_SCALE_FACTOR,
        #if defined(LIMP_MODE_SUPPORT)
                DEFAULT_V_RMS_LIMP_SCALE_FACTOR,
        #endif
    #endif
                DEFAULT_V_DC_ESTIMATE << 16,
    #if defined(LIMP_MODE_SUPPORT)
                DEFAULT_V_LIMP_DC_ESTIMATE << 16,
    #endif
            }
        },
#endif
#if defined(NEUTRAL_MONITOR_SUPPORT)
        {
    #if defined(IRMS_SUPPORT)
            DEFAULT_NEUTRAL_I_RMS_SCALE_FACTOR,
        #if defined(LIMP_MODE_SUPPORT)
            DEFAULT_NEUTRAL_I_RMS_LIMP_SCALE_FACTOR,
        #endif
            0,
    #endif
            DEFAULT_NEUTRAL_P_SCALE_FACTOR,
            DEFAULT_I_DC_ESTIMATE << 16,
    #if defined(PHASE_CORRECTION_SUPPORT)
            DEFAULT_NEUTRAL_BASE_PHASE_CORRECTION,
    #endif
        },
#endif
#if defined(TEMPERATURE_SUPPORT)
        25,
        DEFAULT_TEMPERATURE_OFFSET,
        DEFAULT_TEMPERATURE_SCALING,
#endif
#if defined(CORRECTED_RTC_SUPPORT)
        0,
#endif
        {
            0,
            0,
            0,
            0,
            0,
            0
        },
        0,
        "",
        "",
        ""
    }
    }
};

#if !defined(__IAR_SYSTEMS_ICC__)
static __inline__ long labs(long __x);
static __inline__ long labs(long __x)
{
    return (__x < 0) ? -__x : __x;
}
#endif

#if SELF_TEST_SUPPORT
int record_meter_failure(int type)
{
    /* The error type should be a value between 0 and 15, specifying the unrecoverable error
       type to be recorded in the failures word in flash. */
    /* Don't worry about the time taken to write to flash - we are recording a serious
       error condition! */
    flash_write_int16((int *) &(nv_parms.seg_a.s.meter_failures), nv_parms.seg_a.s.meter_failures & ~(1 << type));
    flash_secure();
    return TRUE;
}

int record_meter_warning(int type)
{
    /* The warning type should be a value between 0 and 15, specifying the warning type to be
       recorded in the recoverable failures word in flash. */
    /* Don't worry about the time taken to write to flash - we are recording a serious
       problem! */
    flash_write_int16((int *) &(nv_parms.seg_a.s.meter_warnings), nv_parms.seg_a.s.meter_warnings & ~(1 << type));
    flash_secure();
    return TRUE;
}
#endif

#if defined(BATTERY_MONITOR_SUPPORT)
void test_battery(void)
{
    P3DIR |= (BIT1);
    P3OUT &= ~(BIT1);
    battery_countdown = 1000;
}
#endif

#if defined(RTC_SUPPORT)
void rtc_bumper(void)
{
    int i;

    i = bump_rtc();
    /* And now, a series of optional routines to get actions to take
       place at various intervals. Remember, we are in an interrupt
       routine. Do not do anything very complex here. If a complex action
       is needed set a flag in a simple routine and do the main work in
       the non-interrupt code's main loop. */
    #if defined(PER_YEAR_ACTIVITY_SUPPORT)
    if (i >= RTC_CHANGED_YEAR)
        per_year_activity();    
    #endif
    #if defined(PER_MONTH_ACTIVITY_SUPPORT)
    if (i >= RTC_CHANGED_MONTH)
        per_month_activity();
    #endif
    #if defined(PER_DAY_ACTIVITY_SUPPORT)  ||  defined(MULTI_RATE_SUPPORT)
    if (i >= RTC_CHANGED_DAY)
    {
        #if defined(PER_MINUTE_ACTIVITY_SUPPORT)
        per_day_activity();
        #endif
        #if defined(MULTI_RATE_SUPPORT)
        tariff_flags |= TARIFF_NEW_DAY;
        #endif
    }
    #endif
    #if defined(PER_HOUR_ACTIVITY_SUPPORT)
    if (i >= RTC_CHANGED_HOUR)
        per_hour_activity();
    #endif
    #if defined(PER_MINUTE_ACTIVITY_SUPPORT)  ||  defined(MULTI_RATE_SUPPORT)  ||  defined(BATTERY_MONITOR_SUPPORT)
    if (i >= RTC_CHANGED_MINUTE)
    {
        #if defined(PER_MINUTE_ACTIVITY_SUPPORT)
        per_minute_activity();
        #endif
        #if defined(MULTI_RATE_SUPPORT)
        tariff_flags |= TARIFF_NEW_MINUTE;
        #endif
        #if defined(BATTERY_MONITOR_SUPPORT)
        test_battery();
        #endif
    }
    #endif
    #if defined(PER_SECOND_ACTIVITY_SUPPORT)
    if (i >= RTC_CHANGED_SECOND)
        per_second_activity();
    #endif
}
#endif

#if (defined(RTC_SUPPORT)  ||  defined(CUSTOM_RTC_SUPPORT))  &&  defined(CORRECTED_RTC_SUPPORT)
static void correct_rtc(void)
{
    long int temp;

    /* Correct the RTC to allow for basic error in the crystal, and
       temperature dependant changes. This is called every two seconds,
       so it must accumulate two seconds worth of error at the current
       temperature. */
    if (nv_parms.seg_a.s.temperature_offset)
    {
        temp = temperature - nv_parms.seg_a.s.temperature_offset;
        temp *= nv_parms.seg_a.s.temperature_scaling;
        temp >>= 16;

        /* The temperature is now in degrees C. */
        /* Subtract the centre point of the crystal curve. */
        temp -= 25;
        /* Do the parabolic curve calculation, to find the current ppm of
           error due to temperature, and then the scaled RTC correction
           value for 2 seconds at this temperature. */
        temp = temp*temp*(2589L*4295L >> 5);
        temp >>= 11;
        temp = -temp;
    }
    else
    {
        temp = 0;
    }
    /* Allow for the basic manufacturing tolerance error of the crystal, found
       at calibration time. */
    temp += nv_parms.seg_a.s.crystal_base_correction;
    if (rtc_correction >= 0)
    {
        rtc_correction += temp;
        if (rtc_correction < 0)
        {
            rtc_correction -= 0x80000000;
            /* We need to add an extra second to the RTC */
    #if CUSTOM_RTC_SUPPORT
            custom_rtc();
    #else
            rtc_bumper();
    #endif
        }
    }
    else
    {
        rtc_correction += temp;
        if (rtc_correction >= 0)
        {
            rtc_correction += 0x80000000;
            /* We need to drop a second from the RTC */
            meter_status |= SKIP_A_SECOND;
        }
    }
}
#endif

#if IO_EXPANDER_SUPPORT
/* This routine supports the use of a device like the 74HC595 to expand the number of
   output bits available on the lower pin count MSP430s. */
void set_io_expander(int what, int which)
{
    static uint8_t io_state = 0;
    int i;
    int j;

    if (what < 0)
        io_state &= ~which;
    else if (what > 0)
        io_state |= which;
    else
        io_state = which;
    /* Pump the data into the shift register */
    for (i = 8, j = io_state;  i > 0;  i--)

⌨️ 快捷键说明

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