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

📄 emeter-background.c

📁 msp430F437三相电表DEMO(编译器 IAR 3.42A)
💻 C
📖 第 1 页 / 共 4 页
字号:
            phase->status |= I_NEUTRAL_POS;
        }
#endif
#if !defined(SINGLE_PHASE)
        phase++;
    }
#endif

#if !defined(SINGLE_PHASE)  &&  defined(NEUTRAL_MONITOR_SUPPORT)  &&  defined(IRMS_SUPPORT)
    /* For multi-phase meters, neutral monitoring is limited to measuring the
       RMS current. */
    corrected = adc_buffer[++adc_ptr];
    if ((corrected >= ADC_MAX  ||  corrected <= ADC_MIN)  &&  neutral.I_endstops)
        neutral.I_endstops--;
    I_live_sample = corrected - adc_buffer[--adc_ptr];
    I_live_sample = dc_filter(&neutral.I_dc_estimate, I_live_sample);
    accum48(neutral.I_sq_accum[0], imul16(I_live_sample, I_live_sample));
    if (++neutral.sample_count[0] >= samples_per_second)
        log_neutral_parameters();
#endif

#if defined(TOTAL_ENERGY_SUPPORT)
    /* We now play the last measurement interval's power level, evaluated
       in the foreground, through this measurement interval. In this way
       we can evenly pace the pulsing of the LED. The only error produced
       by this is the ambiguity in the number of samples per measurement.
       This should not exceed 1 or 2 in over 4000. */
    #if defined(LIMP_MODE_SUPPORT)
    if (operating_mode == OPERATING_MODE_NORMAL)
    {
    #endif
    
    #if defined(INHIBIT_NEGATIVE_TOTAL_POWER_ACCUMULATION)
        if (total_power > 0  &&  (total_power_counter += total_power) >= TOTAL_ENERGY_PULSE_THRESHOLD)
    #else
        if ((total_power_counter += total_power) >= TOTAL_ENERGY_PULSE_THRESHOLD)
    #endif
        {
            total_power_counter -= TOTAL_ENERGY_PULSE_THRESHOLD;
    #if TOTAL_ENERGY_PULSES_PER_KW_HOUR < 1000
            if (++extra_total_power_counter >= 16)
            {
                extra_total_power_counter = 0;
    #endif
                ++total_consumed_energy;
                /* Ideally we want to log the energy each kWh unit, but doing
                   it with a mask here is good enough and faster. */
                if ((total_consumed_energy & 0x3FF) == 0)
                    phase->status |= ENERGY_LOGABLE;
                /* Pulse the LED. Long pulses may not be reliable, as at full
                   power we may be pulsing many times per second. People may
                   check the meter's calibration with an instrument that counts
                   the pulsing rate, so it is important the pulses are clear,
                   distinct, and exactly at the rate of one per
                   1/ENERGY_PULSES_PER_KW_HOUR kW/h. */
    #if defined(set_total_energy_pulse_indicator)
        #if defined(FINE_ENERGY_PULSE_TIMING_SUPPORT)
                /* TODO: This will not work if extra_total_power_counter is in use */
                /* Work out the fraction of an ADC interrupt, in 1/10ths of an ADC interrupt period,
                   at which the real transition occurs */
                /* Break up the loop a bit, for efficiency */
                xxx = total_power_counter << 1;
                j = 10;
                if (xxx >= total_power)
                {
                    xxx -= total_power;
                    j = 5;
                }
                xxx += (xxx << 2);
                do
                    j--;
                while ((xxx -= total_power) > 0);
                /* j is now our fraction of an ADC interrupt. If we use this right now to control timer A
                   its effect would be indeterminate. We need timer A to be updated at the very start of an
                   ADC interrupt service, to ensure the fraction of an ADC interrupt is programmed into the
                   timer while its count is at a well defined value - zero. */
                fine_pulse_operation = OUTMOD_5 | SCS;
                TACCR2 = j;
        #else
                set_total_energy_pulse_indicator();
        #endif
                total_energy_pulse_remaining_time = ENERGY_PULSE_DURATION;
    #endif
                custom_energy_pulse_start();
    #if defined(MULTI_RATE_SUPPORT)
                multirate_energy_pulse();
    #endif
    #if TOTAL_ENERGY_PULSES_PER_KW_HOUR < 1000
            }
    #endif
        }
    #if defined(clr_total_energy_pulse_indicator)
        if (total_energy_pulse_remaining_time  &&  --total_energy_pulse_remaining_time == 0)
        {
        #if defined(FINE_ENERGY_PULSE_TIMING_SUPPORT)
            /* Turn off the LED at the next CCR2 match. */
            fine_pulse_operation = OUTMOD_1 | SCS;
            /* Leave TACCR2 alone, and we should get the same offset as last time, resulting in even length pulses */
        #else
            clr_total_energy_pulse_indicator();
        #endif
            custom_energy_pulse_end();
        }
    #endif

    #if defined(INHIBIT_NEGATIVE_TOTAL_POWER_ACCUMULATION)
        if (total_reactive_power > 0  &&  (total_reactive_power_counter += total_reactive_power) >= TOTAL_ENERGY_PULSE_THRESHOLD)
    #else
        if ((total_reactive_power_counter += total_reactive_power) >= TOTAL_ENERGY_PULSE_THRESHOLD)
    #endif
        {
            total_reactive_power_counter -= TOTAL_ENERGY_PULSE_THRESHOLD;
    #if TOTAL_ENERGY_PULSES_PER_KW_HOUR < 1000
            if (++extra_total_reactive_power_counter >= 16)
            {
                extra_total_reactive_power_counter = 0;
    #endif
                ++total_consumed_reactive_energy;
                /* Ideally we want to log the energy each kWh unit, but doing
                   it with a mask here is good enough and faster. */
                if ((total_consumed_reactive_energy & 0x3FF) == 0)
                    phase->status |= ENERGY_LOGABLE;
                /* Pulse the LED. Long pulses may not be reliable, as at full
                   power we may be pulsing many times per second. People may
                   check the meter's calibration with an instrument that counts
                   the pulsing rate, so it is important the pulses are clear,
                   distinct, and exactly at the rate of one per
                   1/ENERGY_PULSES_PER_KW_HOUR kW/h. */
    #if defined(set_total_reactive_energy_pulse_indicator)
        #if defined(FINE_ENERGY_PULSE_TIMING_SUPPORT)
                /* TODO: This will not work if extra_total_power_counter is in use */
                /* Work out the fraction of an ADC interrupt, in 1/10ths of an ADC interrupt period,
                   at which the real transition occurs */
                /* Break up the loop a bit, for efficiency */
                xxx = total_reactive_power_counter << 1;
                j = 10;
                if (xxx >= total_reactive_power)
                {
                    xxx -= total_reactive_power;
                    j = 5;
                }
                xxx += (xxx << 2);
                do
                    j--;
                while ((xxx -= total_reactive_power) > 0);
                /* j is now our fraction of an ADC interrupt. If we use this right now to control timer A
                   its effect would be indeterminate. We need timer A to be updated at the very start of an
                   ADC interrupt service, to ensure the fraction of an ADC interrupt is programmed into the
                   timer while its count is at a well defined value - zero. */
                fine_pulse_operation = OUTMOD_5 | SCS;
                TACCR2 = j;
        #else
                set_total_reactive_energy_pulse_indicator();
        #endif
                total_reactive_energy_pulse_remaining_time = ENERGY_PULSE_DURATION;
    #endif
    #if TOTAL_ENERGY_PULSES_PER_KW_HOUR < 1000
            }
    #endif
        }
    #if defined(clr_total_reactive_energy_pulse_indicator)
        if (total_reactive_energy_pulse_remaining_time  &&  --total_reactive_energy_pulse_remaining_time == 0)
        {
        #if defined(FINE_ENERGY_PULSE_TIMING_SUPPORT)
            /* Turn off the LED at the next CCR2 match. */
            fine_pulse_operation = OUTMOD_1 | SCS;
            /* Leave TACCR2 alone, and we should get the same offset as last time, resulting in even length pulses */
        #else
            clr_total_reactive_energy_pulse_indicator();
        #endif
        }
    #endif

    #if defined(LIMP_MODE_SUPPORT)
    }
    else
    {
        if ((total_power_counter += LIMP_SAMPLING_RATIO*total_power) >= TOTAL_ENERGY_PULSE_THRESHOLD)
        {
            total_power_counter -= TOTAL_ENERGY_PULSE_THRESHOLD;
        #if TOTAL_ENERGY_PULSES_PER_KW_HOUR < 1000
            if (++extra_total_power_counter >= 16)
            {
                extra_total_power_counter = 0;
        #endif
                ++total_consumed_energy;
                if ((total_consumed_energy & 0x3FF) == 0)
                    phase->status |= ENERGY_LOGABLE;
                custom_energy_pulse_start();
        #if defined(set_total_energy_pulse_indicator)
                set_total_energy_pulse_indicator();
                total_energy_pulse_remaining_time = ENERGY_PULSE_DURATION;
        #endif
        #if defined(set_total_reactive_energy_pulse_indicator)
                set_total_reactive_energy_pulse_indicator();
                total_reactive_energy_pulse_remaining_time = ENERGY_PULSE_DURATION;
        #endif
        #if TOTAL_ENERGY_PULSES_PER_KW_HOUR < 1000
            }
        #endif
        }
        #if defined(clr_total_energy_pulse_indicator)
        if (total_energy_pulse_remaining_time  &&  (total_energy_pulse_remaining_time -= LIMP_SAMPLING_RATIO) == 0)
        {
            clr_total_energy_pulse_indicator();
            custom_energy_pulse_end();
        }
        #endif
    }
    #endif
#endif

    custom_adc_interrupt();

#if defined(x__MSP430__)
    #if defined(POWER_DOWN_SUPPORT)  &&  defined(POWER_UP_BY_SUPPLY_SENSING)
    /* Select the lower threshold to watch for the power supply dying. */ 
    CACTL1 = CAREF_1 | CAON;
    #endif
    #if defined(BASIC_KEYPAD_SUPPORT)  ||  defined(CUSTOM_KEYPAD_SUPPORT)
    if (keypad_debounce())
        _BIC_SR_IRQ(LPM0_bits);
    #endif

    #if defined(__MSP430__)  &&  (defined(IEC1107_SUPPORT)  ||  defined(SERIAL_CALIBRATION_SUPPORT))
    /* Update the inter-character timeout for receiving IR messages */
    if (char_timeout_1107)
        char_timeout_1107--;
    #endif
    #if defined(PWM_DITHERING_SUPPORT)
    if (operating_mode == OPERATING_MODE_NORMAL)
    {
        /* Only try to dither when in full operating mode.
           The dithering increases current consumtion a little! */ 
        /* Calculate new PWM duty cycle for the dithering */
        if ((meter_status & PWM_RAMPING_DOWN))
        {
            if (!(TBCCR1 == PWM_MID_POINT  &&  pwm_stutter--))
            {
                if (--TBCCR1 <= PWM_LOWER_LIMIT)
                {
                    meter_status &= ~PWM_RAMPING_DOWN;
                    /* Set a small randomised stutter for the cycle
                       of the triangular dithering waveform to avoid the
                       possibility of high correlation with the mains
                       waveform. */
                    pwm_stutter = ((rndnum >> 8) & 0x7);
                }
            }
        }
        else
        {
            if (++TBCCR1 >= PWM_UPPER_LIMIT)
                meter_status |= PWM_RAMPING_DOWN;
        }
    }
    #endif
    #if defined(DAC12_DITHERING_SUPPORT)
    fred = (rand16() >> 1) & 0x7F;
    DAC12_1DAT = fred2 + fred;
    fred2 = fred;
    #endif

    #if defined(POWER_DOWN_SUPPORT)  &&  defined(POWER_UP_BY_SUPPLY_SENSING)
        #if defined(__MSP430_HAS_COMPA__)
    if ((CACTL2 & CAOUT))
        #else
    /* Use an I/O pin to sense the power falling */
    POWER_GOOD_THRESHOLD_LOW;
    if (!POWER_GOOD_SENSE)
        #endif
    {
        /* The comparator output can oscillate a little around the
           switching point, so we need to do some debouncing. */
        if (power_down_debounce < POWER_FAIL_DEBOUNCE + 1)
        {
            if (++power_down_debounce == POWER_FAIL_DEBOUNCE)
            {
                power_down_debounce = 0;
                /* The power is falling. We need to get to a low power
                   consumption state now! The battery will be supplying the
                   meter soon. */
                operating_mode = OPERATING_MODE_POWERFAIL;
        #if defined(__MSP430__)
                /* Get the foreground to respond quickly. It might be conserving
                   power (e.g. in limp mode). */
                _BIC_SR_IRQ(LPM0_bits);
        #endif
            }
        }
    }
    else
    {
        power_down_debounce = 0;
    }
        #if defined(__MSP430_HAS_COMPA__)
    CACTL1 &= ~(CAON);
        #endif
    #endif
#endif
#if defined(MAGNETIC_INTERFERENCE_SUPPORT)
    if (custom_magnetic_sensor_test())
        magnetic_sensor_count++;
#endif

#if defined(__MSP430_HAS_SD16_3__)
    /* There may be some current samples available, which we need to pick up */
    #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;
    }
#endif
    /**/ P3OUT |= 0x04;
}

#if defined(__MSP430__)  &&  defined(__MSP430_HAS_ADC12__)
/* Interrupt to dynamically enable the ADC in limp mode */
ISR(TIMERA1, adcx_interrupt)
{
    /* Re-enable the ADC in time to take the next set of samples */
    if ((TACCTL2 & CCIFG))
    {
        //P2SEL &= ~BIT4;
        //P2OUT &= ~BIT4;
        TACCTL2 &= ~CCIFG;
        ADC12CTL0 |= (ENC | ADC12ON);
    }
}
#endif

#if defined(__MSP430__)  &&  defined(__MSP430_HAS_SD16_3__)
/* Interrupt to trigger the SD16 ADC in limp mode */
ISR(TIMERA0, limp_trigger_interrupt)
{
    #if defined(RF_LINK_SUPPORT)
    if (rf_timeout < 0)
    {
        /* Enable the USART */
        U0ME |= (UTXE0 | URXE0);
        #if defined(__MSP430_HAS_FLLPLUS__)  ||  defined(__MSP430_HAS_FLLPLUS_SMALL__)
        /* Speed up the clock to 8.388608MHz */
        SCFI0 = FN_3 | FLLD_4;
        SCFQCTL = 64 - 1;
        #endif
        custom_rf_exchange();
        /* Disable the USART */
        U0ME &= ~(UTXE0 | URXE0);
        /* Disable the TIMER_A0 interrupt */
        TACTL = 0;
        TACCTL0 = 0;
        #if defined(__MSP430_HAS_FLLPLUS__)  ||  defined(__MSP430_HAS_FLLPLUS_SMALL__)
        /* Slow the clock to 1MHz as quickly as possible. The FLL will not be active
           in LPM3, so switch it off now, and force the FLL's RC oscillator to
           about 1MHz. The exact frequency is not critical. */
        _BIS_SR(SCG0);                  /* switch off FLL locking */
        SCFI0 = FLLD_1;
        SCFQCTL = (32 - 1) | SCFQ_M;
        SCFI0 = 0x0;
        SCFI1 = 0x37;
        #endif
        rf_timeout = 0;
    }
    else
    #endif
    {
        /* Trigger the ADC to perform a single conversion from all inputs. */
        #if defined(SINGLE_PHASE)  &&  defined(NEUTRAL_MONITOR_SUPPORT)
        SD16PRE_NEUTRAL = 0;
        #endif
        SD16PRE_LIVE = 0;
        SD16PRE_VOLTAGE = 0;
        SD16CCTL_VOLTAGE |= SD16SC;
    }
}
#endif

⌨️ 快捷键说明

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