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

📄 emeter-background.c

📁 msp430F437三相电表DEMO(编译器 IAR 3.42A)
💻 C
📖 第 1 页 / 共 4 页
字号:
    {   129,   2038,   1961,   1810},
    {   129,   2038,   1961,   1809},
    {   129,   2038,   1960,   1808},
    {   128,   2038,   1960,   1807},
    {   128,   2038,   1960,   1806},
    {   128,   2038,   1959,   1805},
    {   128,   2038,   1959,   1804},
    {   127,   2038,   1959,   1803},
    {   127,   2038,   1958,   1802},
    {   127,   2038,   1958,   1802},
    {   127,   2038,   1958,   1801},
    {   126,   2038,   1957,   1800},
    {   126,   2038,   1957,   1799},
    {   126,   2038,   1957,   1798},
    {   126,   2038,   1956,   1797},
    {   125,   2038,   1956,   1796},
    {   125,   2038,   1956,   1795},
    {   125,   2038,   1955,   1794},
};

void goertzel_init(goertzel_state_t *s)
{
    s->v2 =
    s->v3 = 0;
}

void goertzel_update(goertzel_state_t *s, int16_t x, int16_t fac)
{
    int32_t v1;

    v1 = s->v2;
    s->v2 = s->v3;
    s->v3 = ((fac*s->v2) >> 10) - v1 + x;
}

int32_t goertzel_result(goertzel_state_t *s, int16_t fac)
{
    int32_t v1;
    int32_t v2;
    int32_t v3;

    /* Push a zero through the process to finish things off. */
    v1 = s->v2;
    s->v2 = s->v3;
    s->v3 = ((fac*s->v2) >> 10) - v1;
    
    /* Now calculate the non-recursive side of the filter. */
    /* The result here is not scaled down to allow for the magnification
       effect of the filter (the usual DFT magnification effect). */
    v2 = s->v2 >> 5;
    v3 = s->v3 >> 5;
    return v3*v3 + v2*v2 - ((v2*v3) >> 10)*fac;
}

    #if defined(SINGLE_PHASE)
static __inline__ void init_harmonics()
    #else
static __inline__ void init_harmonics(struct phase_parms_s *phase)
    #endif
{
        goertzel_init(&(phase->current.harm_1));
        goertzel_init(&(phase->current.harm_3));
        goertzel_init(&(phase->current.harm_5));
        phase->current.harmonic_step = phase->frequency/10 - 475;
        phase->current.harmonic_samples = harm_factors[phase->current.harmonic_step][0];
}

    #if defined(SINGLE_PHASE)
static __inline__ void harmonics(int16_t iamp)
    #else
static __inline__ void harmonics(struct phase_parms_s *phase, int16_t iamp)
    #endif
{
    int step;
    
    step = phase->current.harmonic_step;

    goertzel_update(&(phase->current.harm_1), iamp, harm_factors[step][1]);
    goertzel_update(&(phase->current.harm_3), iamp, harm_factors[step][2]);
    goertzel_update(&(phase->current.harm_5), iamp, harm_factors[step][3]);
    if (--phase->current.harmonic_samples <= 0)
    {
        phase->current.pow_1 = goertzel_result(&(phase->current.harm_1), harm_factors[step][1]);
        phase->current.pow_3 = goertzel_result(&(phase->current.harm_3), harm_factors[step][2]);
        phase->current.pow_5 = goertzel_result(&(phase->current.harm_5), harm_factors[step][3]);
    #if defined(SINGLE_PHASE)
        init_harmonics();
    #else
        init_harmonics(phase);
    #endif
    }
}
#endif

int16_t fred;
int16_t fred2;

/*---------------------------------------------------------------------------
  This is the main interrupt routine where the main signal processing is done
  ---------------------------------------------------------------------------*/
#if defined(__MSP430__)
    #if defined(__MSP430_HAS_SD16_3__)
ISR(SD16, adc_interrupt)
    #endif
    #if defined(__MSP430_HAS_ADC12__)
ISR(TIMERA0, adc_interrupt)
    #endif
#else
void adc_interrupt(void)
#endif
{
#if defined(PWM_DITHERING_SUPPORT)
    extern uint16_t rndnum;
#endif
    int16_t V_sample;
    int16_t corrected;
    int16_t I_live_sample;
#if defined(SINGLE_PHASE)  &&  defined(NEUTRAL_MONITOR_SUPPORT)
    int16_t I_neutral_sample;
#endif
#if GAIN_STAGES > 1
    int16_t use_stage;
#else
#define i 0
#endif
#if !defined(SINGLE_PHASE)
    struct phase_parms_s *phase;
    int j;
#endif
#if defined(__MSP430_HAS_ADC12__)
    #if !defined(SINGLE_PHASE)
    int16_t adc_buffer[10];
    #else
    int16_t adc_buffer[5];
    #endif
    int adc_ptr;
#endif
#if defined(__MSP430_HAS_SD16_3__)
    static int16_t adc_buffer[3];
    int adc_ptr;
#endif    
#if !defined(__MSP430__)
    int16_t adc_buffer[15];
    int adc_ptr;
#endif
#if defined(FINE_ENERGY_PULSE_TIMING_SUPPORT)
    int32_t xxx;
#endif
#if defined(MAINS_FREQUENCY_SUPPORT)
    int k;
    int x;
    int y;
    int z;
#endif

    /**/ P3OUT &= ~0x04;
#if defined(__MSP430_HAS_SD16_3__)
    if (!(SD16CCTL_VOLTAGE & SD16IFG))
    {
        /* We do not have a complete set of samples yet, but we may need to pick
           up some current values at this time */
    #if defined(SINGLE_PHASE)  &&  defined(NEUTRAL_MONITOR_SUPPORT)
        if ((SD16CCTL_NEUTRAL & SD16IFG))
        {
            adc_buffer[2] = SD16MEM_NEUTRAL;
            SD16CCTL_NEUTRAL &= ~SD16IFG;
        }
    #endif
        if ((SD16CCTL_LIVE & SD16IFG))
        {
            adc_buffer[1] = SD16MEM_LIVE;
            SD16CCTL_LIVE &= ~SD16IFG;
        }
        return;
    }
#endif

#if defined(FINE_ENERGY_PULSE_TIMING_SUPPORT)
    /* Trigger the energy pulse, timed by timer A */
    /* This needs to be at the start of the interrupt service routine so its timing is well defined in
       relation to the counting of timer A */
    if (fine_pulse_operation)
    {
        /* This early in the interrupt routine timer A's counter should still be at zero. If we request
           a target compare match count of zero while the count is already zero, the output will change
           immediately. Counts of 0 to 9 should, therefore, hit somewhere through the current ADC interrupt
           period. A match of zero will not be as well timed as the others, as we will have missed the exact
           moment when it should begin, but it is good enough. */
        TACCTL2 = fine_pulse_operation;
        fine_pulse_operation = 0;
    }
#endif
    /* Filter away the DC bias.
    
       Do the phase lag compensation. Use a simple FIR approach,
       and absorb the non-unity gain of the filter in the overall
       current/power scaling later on. This is OK for the small
       phase shifts we expect to get. It would cause dynamic
       range problems for larger shifts. Note the some of this
       phase shift is due to the operation of the ADC itself. It
       performs sequential conversions of its 8 inputs, so there is
       some time delay between sampling of the various sensors.
    
       Accumulate power for each of the channels. These will
       be divided by the number of samples at the end of the
       measurement cycles, resulting in an average power
       value for each source.

       If RMS voltage and/or current readings are required, calculate the
       dot products needed to evaluate these. */

#if defined(__MSP430_HAS_ADC12__)
    //P2SEL &= ~BIT4;
    //P2OUT |= BIT4;
    ADC12CTL0 &= ~ENC;
    if (operating_mode == OPERATING_MODE_NORMAL)
    {
        /* Start a new ADC scan sequence when Timer_B0 next triggers. */
        ADC12CTL0 |= ENC;
    }
    else
    {
        ADC12CTL0 &= ~ADC12ON;
    }
    #if !defined(SINGLE_PHASE)
    /* Grab the data quickly, in case it gets overwritten later in
       this long interrupt routine. */
    adc_buffer[0] = ADC12MEM[2];    //V1
    adc_buffer[1] = ADC12MEM[0];    //L1
    adc_buffer[2] = ADC12MEM[1];    //H1
    adc_buffer[3] = ADC12MEM[5];    //V2
    adc_buffer[4] = ADC12MEM[3];    //L2
    adc_buffer[5] = ADC12MEM[4];    //H2
    adc_buffer[6] = ADC12MEM[8];    //V3
    adc_buffer[7] = ADC12MEM[6];    //L3
    adc_buffer[8] = ADC12MEM[7];    //H3
        #if defined(NEUTRAL_CURRENT_INPUT)
    adc_buffer[9] = ADC12MEM[9];    //N
            #if defined(TEMPERATURE_SUPPORT)
    if (operating_mode == OPERATING_MODE_NORMAL)
        temperature = temperature - (temperature >> 3) + ADC12MEM[10];
            #endif
        #else
            #if defined(TEMPERATURE_SUPPORT)
    if (operating_mode == OPERATING_MODE_NORMAL)
        temperature = temperature - (temperature >> 3) + ADC12MEM[9];
            #endif
        #endif
        #if 0
    instant_Vcc = ADC12MEM[11];
    instant_VeREF_plus = ADC12MEM[12];
    instant_VeREF_minus = ADC12MEM[13];
        #endif
    #else
    /* Grab the data quickly, in case it gets overwritten later in
       this long interrupt routine. */
    adc_buffer[0] = ADC12MEM[5];    //V
    adc_buffer[1] = ADC12MEM[3];    //L
    adc_buffer[2] = ADC12MEM[2];    //A(L)
    adc_buffer[3] = ADC12MEM[1];    //N
    adc_buffer[4] = ADC12MEM[0];    //A(N)
        #if defined(BATTERY_MONITOR_SUPPORT)
    if (battery_countdown)
    {
        if (--battery_countdown == 0)
        {
            if (ADC12MEM[6] > 0x800)
                meter_status |= STATUS_BATTERY_OK;
            else
                meter_status &= ~(STATUS_BATTERY_OK);
            /* Battery sensing control pin */
            P3DIR &= ~(BIT1);
            P3OUT |= (BIT1);
        }
    }
        #endif
        #if defined(TEMPERATURE_SUPPORT)
    if (operating_mode == OPERATING_MODE_NORMAL)
        temperature = temperature - (temperature >> 3) + ADC12MEM[7];
        #endif
    #endif
    adc_ptr = -1;
#endif

#if defined(__MSP430_HAS_SD16_3__)
    /* Voltage is available */
    adc_buffer[0] = SD16MEM_VOLTAGE;
    SD16CCTL_VOLTAGE &= ~SD16IFG;
    /* Pick up any current samples which may have occurred a little before the
       voltage sample, but not those which may have occurred just after the
       voltage sample. */
        #if defined(SINGLE_PHASE)  &&  defined(NEUTRAL_MONITOR_SUPPORT)
    if (phase->neutral.sd16_preloaded_offset < 128  &&  (SD16CCTL_NEUTRAL & SD16IFG))
    {
        adc_buffer[2] = SD16MEM_NEUTRAL;
        SD16CCTL_NEUTRAL &= ~SD16IFG;
    }
        #endif
    if (phase->current.sd16_preloaded_offset < 128  &&  (SD16CCTL_LIVE & SD16IFG))
    {
        adc_buffer[1] = SD16MEM_LIVE;
        SD16CCTL_LIVE &= ~SD16IFG;
    }
    /* We have a complete set of samples. Process them. */
    adc_ptr = -1;
#endif

#if !defined(__MSP430__)
    get_sample(adc_buffer);
    adc_ptr = -1;
#endif

    kick_watchdog();

#if defined(__MSP430_HAS_ADC12__)
    tpd_gen();
#endif
#if !defined(SINGLE_PHASE)
    phase = chan;
    for (j = 0;  j < 3/*NUM_PHASES*/;  j++)
    {
#endif
        V_sample = adc_buffer[++adc_ptr];
        if ((V_sample >= ADC_MAX  ||  V_sample <= ADC_MIN)  &&  phase->V_endstops)
            phase->V_endstops--;
#if defined(LIMP_MODE_SUPPORT)
        V_sample = dc_filter(&phase->V_dc_estimate[(operating_mode == OPERATING_MODE_NORMAL)  ?  0  :  1], V_sample);
#else
        V_sample = dc_filter(&phase->V_dc_estimate, V_sample);
#endif
#if defined(VRMS_SUPPORT)  ||  defined(POWER_FACTOR_SUPPORT)
        accum48(phase->V_sq_accum, imul16(V_sample, V_sample));
#endif
#if defined(REACTIVE_POWER_BY_QUADRATURE_SUPPORT)  ||  defined(PHASE_CORRECTION_SUPPORT)
        /* We need to save the history of the voltage signal if we are performing phase correction, and/or
           measuring the quadrature shifted power (to obtain an accurate measure of one form of the reactive power). */
        phase->V_history[(int) phase->V_history_index] = V_sample;
#endif
        I_live_sample = -dc_filter(&phase->current.I_dc_estimate[0], phase->current.I_history[0][0]);
        phase->current.I_history[0][0] = phase->current.I_history[0][1];
        corrected = adc_buffer[++adc_ptr];
#if GAIN_STAGES > 1
        if ((corrected >= ADC_MAX  ||  corrected <= ADC_MIN))
        {
            phase->current.stage_hits = 100;
            phase->current.stage_in_use = 1;
        }
        else
        {
            if (phase->current.stage_hits)
            {
                if (--phase->current.stage_hits == 0)
                    phase->current.stage_in_use = 0;
            }
        }
        use_stage = phase->current.stage_in_use;
#else
        if ((corrected >= ADC_MAX  ||  corrected <= ADC_MIN)  &&  phase->current.I_endstops)
            phase->current.I_endstops--;
#endif
#if defined(__MSP430_HAS_SD16_3__)
        phase->current.I_history[0][1] = corrected;
#else
        //phase->current.I_history[0][1] = corrected - adc_buffer[++adc_ptr];
        phase->current.I_history[0][1] = corrected;
#endif
#if GAIN_STAGES > 1
        corrected = dc_filter(&phase->current.I_dc_estimate[1], phase->current.I_history[1][0]);
        if (use_stage)
            I_live_sample = corrected;
        phase->current.I_history[1][0] = phase->current.I_history[1][1];
        corrected = adc_buffer[++adc_ptr];
        if ((corrected >= ADC_MAX  ||  corrected <= ADC_MIN)  &&  phase->current.I_endstops)
            phase->current.I_endstops--;
        phase->current.I_history[1][1] = corrected;
#endif
#if defined(IRMS_SUPPORT)  ||  defined(POWER_FACTOR_SUPPORT)
        accum48(phase->current.I_sq_accum[use_stage], imul16(I_live_sample, I_live_sample));
#endif
        if (operating_mode == OPERATING_MODE_NORMAL)
        {
            /* Perform phase shift compensation, to allow for the time
               between ADC samplings, internal phase shifts in CTs, etc.
               This uses a 1 tap FIR (basically an interpolator/extrapolator) */
#if defined(PHASE_CORRECTION_SUPPORT)
    #if defined(__MSP430_HAS_ADC12__)  ||  defined(__MSP430_HAS_ADC10__)
            corrected = Q1_15_mul(phase->V_history[(phase->V_history_index - phase->current.in_phase_phase_correction_step[use_stage] - 1) & V_HISTORY_MASK], phase->current.in_phase_fir_beta[use_stage])

⌨️ 快捷键说明

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