?? emeter-setup.c
字號:
ADC12CTL0 |= ENC;
#if defined(__MSP430_HAS_TA3__)
/* Switch to the normal sampling rate. */
TAR = 0;
TACCR0 = SAMPLE_PERIOD - 1;
TACCR1 = SAMPLE_PERIOD - 3;
TACCR2 = SAMPLE_PERIOD - 4;
TACCTL0 = CCIE;
TACCTL1 = OUTMOD_3;
TACTL = TACLR | MC_1 | TASSEL_1;
/* Disable the interrupt routine which re-enables the ADC */
TACCTL2 = 0;
#endif
#endif
#if defined(__MSP430_HAS_SD16_3__)
#if defined(__MSP430_HAS_TA3__)
/* Disable the TIMER_A0 interrupt */
TACTL = 0;
TACCTL0 = 0;
#endif
_DINT();
init_analog_front_end_normal();
#endif
samples_per_second = SAMPLES_PER_10_SECONDS/10;
_EINT();
#if defined(PWM_DITHERING_SUPPORT)
/* Enable dithering, by enabling Timer B */
TBR = 0;
TBCTL = TBCLR | MC_1 | TBSSEL_2;
#endif
#if defined(DAC12_DITHERING_SUPPORT)
DAC12_0CTL &= ~ENC;
DAC12_1CTL &= ~ENC;
DAC12_0CTL =
DAC12_1CTL = DAC12CALON | DAC12IR | DAC12AMP_7 | DAC12LSEL_2;
DAC12_0CTL |= ENC;
DAC12_1CTL |= ENC;
DAC12_0DAT = 0x800;
DAC12_1DAT = 0;
#endif
#if defined(IEC1107_SUPPORT)
enable_ir_receiver();
#endif
operating_mode = OPERATING_MODE_NORMAL;
}
#if defined(LIMP_MODE_SUPPORT)
void switch_to_limp_mode(void)
{
/* Switch to minimum consumption, current measurement only mode */
meter_status &= ~(STATUS_REVERSED | STATUS_PHASE_VOLTAGE_OK);
clr_normal_indicator();
clr_reverse_current_indicator();
#if defined(__MSP430_HAS_ADC12__)
/* Change the ADC reference to Vcc */
_DINT();
/* Must disable conversion while reprogramming the ADC */
ADC12CTL0 &= ~ENC;
/* Turn the Vref off and ADC on */
ADC12CTL0 = MSC | REF2_5V | ADC12ON | SHT0_2 | SHT1_2;
#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;
#if defined(BATTERY_MONITOR_SUPPORT)
ADC12MCTL5 = SREF_0 | VOLTAGE_INPUT;
ADC12MCTL6 = EOS | SREF_0 | BATTERY_INPUT;
#else
ADC12MCTL5 = EOS | SREF_0 | VOLTAGE_INPUT;
#endif
/* Skip the temperature, or the reference switches on! */
#else
ADC12MCTL0 = SREF_0 | LIVE_CURRENT_INPUT_1;
ADC12MCTL1 = SREF_0 | AGND_INPUT;
ADC12MCTL2 = SREF_0 | VOLTAGE_INPUT_1;
ADC12MCTL3 = SREF_0 | LIVE_CURRENT_INPUT_2;
ADC12MCTL4 = SREF_0 | AGND_INPUT;
ADC12MCTL5 = SREF_0 | VOLTAGE_INPUT_2;
ADC12MCTL6 = SREF_0 | LIVE_CURRENT_INPUT_3;
ADC12MCTL7 = SREF_0 | AGND_INPUT;
#if defined(NEUTRAL_CURRENT_INPUT)
ADC12MCTL8 = SREF_0 | VOLTAGE_INPUT_3;
ADC12MCTL9 = EOS | SREF_0 | NEUTRAL_CURRENT_INPUT;
#else
ADC12MCTL8 = EOS | SREF_0 | VOLTAGE_INPUT_3;
#endif
/* Skip the temperature, or the reference switches on! */
#endif
ADC12CTL0 |= ENC;
#if defined(__MSP430_HAS_TA3__)
/* Switch to a lower sampling rate. */
TAR = 0;
TACCR0 = (SAMPLE_PERIOD*LIMP_SAMPLING_RATIO) - 1;
TACCR1 = (SAMPLE_PERIOD*LIMP_SAMPLING_RATIO) - 3;
TACCR2 = (SAMPLE_PERIOD*LIMP_SAMPLING_RATIO) - 4;
TACCTL0 = CCIE;
TACCTL1 = OUTMOD_3;
TACTL = TACLR | MC_1 | TASSEL_1;
/* Enable the interrupt routine which re-enables the ADC */
TACCTL2 = CCIE;
#endif
#endif
#if defined(__MSP430_HAS_SD16_3__)
#if defined(__MSP430_HAS_TA3__)
/* Enable the TIMER_A0 interrupt */
TACTL = TACLR | MC_1 | TASSEL_1;
TACCTL0 = CCIE;
#endif
_DINT();
init_analog_front_end_limp();
#endif
samples_per_second = LIMP_SAMPLES_PER_10_SECONDS/10;
#if defined(IEC1107_SUPPORT)
disable_ir_receiver();
#endif
_EINT();
#if defined(PWM_DITHERING_SUPPORT)
/* Disable dithering, by disabling Timer B */
TBCTL = TBCLR | TBSSEL_2;
#endif
operating_mode = OPERATING_MODE_LIMP;
}
#endif
#if defined(POWER_DOWN_SUPPORT)
void switch_to_powerfail_mode(void)
{
operating_mode = OPERATING_MODE_POWERFAIL;
/* Note that a power down occured */
meter_status |= POWER_DOWN;
/* Turn off all the LEDs. */
meter_status &= ~(STATUS_REVERSED | STATUS_EARTHED | STATUS_PHASE_VOLTAGE_OK);
clr_normal_indicator();
clr_reverse_current_indicator();
clr_earthed_indicator();
clr_total_energy_pulse_indicator();
clr_total_reactive_energy_pulse_indicator();
/* Make the EEPROM signals inputs, and rely on pullups. */
disable_eeprom_port();
/* Shut down the LCD */
custom_lcd_sleep_handler();
#if defined(__MSP430_HAS_TA3__) && (defined(__MSP430_HAS_ADC12__) || defined(__MSP430_HAS_SD16_3__))
/* Disable the TIMER_A0 interrupt */
TACTL = 0;
TACCTL0 = 0;
/* Disable the interrupt routine which re-enables the ADC */
TACCTL2 = 0;
#endif
#if defined(__MSP430_HAS_ADC12__)
/* Now the interrupts have stopped it should be safe to power
down the ADC. */
ADC12CTL0 &= ~ENC;
ADC12CTL0 &= ~(REFON | REF2_5V | ADC12ON);
#endif
#if defined(__MSP430_HAS_SD16_3__)
disable_analog_front_end();
#endif
#if defined(PWM_DITHERING_SUPPORT)
/* Disable dithering, by disabling Timer B */
TBCTL = TBCLR | TBSSEL_2;
#endif
#if defined(IEC1107_SUPPORT) || defined(SERIAL_CALIBRATION_SUPPORT) || defined(SERIAL_CALIBRATION_REF_SUPPORT)
/* Disable the serial port. */
U0ME &= ~(UTXE0 | URXE0);
#if defined(IEC1107_SUPPORT)
disable_ir_receiver();
#endif
#endif
#if defined(BATTERY_MONITOR_SUPPORT)
/* Battery sensing control pin */
P3DIR &= ~(BIT1);
P3OUT |= (BIT1);
#endif
#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
#if defined(__MSP430_HAS_SVS__)
/* At 1MHz it is safe to turn off the SVS, and rely on the brownout
detector. Now the meter can survive on a very weak battery. */
SVSCTL = 0;
#endif
custom_power_fail_handler();
/* ******************** LOW POWER STATE ************************** */
/* Go to LPM3 mode and exit only when power comes back on. The timer
interrupt that ticks every second should be checking for power
restored while we sit here. When it sees the unregulated supply
at a healthy voltage, it will wake us up. */
_BIS_SR(LPM3_bits);
/* Waking up from power down mode */
#if defined(__MSP430_HAS_SVS__)
/* Before we go to high speed we need to make sure the supply voltage is
adequate. If there is an SVS we can use that. There should be no wait
at this point, since we should only have been woken up if the supply
is healthy. However, it seems better to be cautious. */
SVSCTL |= (SVSON | 0x60);
/* Wait for adequate voltage to run at full speed */
while ((SVSCTL & SVSOP))
/* dummy loop */;
/* The voltage should now be OK to run the CPU at full speed. Now it should
be OK to use the SVS as a reset source. */
SVSCTL |= PORON;
#endif
#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;
/* There seems no good reason to wait until the FLL has settled at this point. */
#endif
/* Take control of the EEPROM signals again. */
enable_eeprom_port();
/* Enable the serial port */
#if defined(IEC1107_SUPPORT) || defined(SERIAL_CALIBRATION_SUPPORT) || defined(SERIAL_CALIBRATION_REF_SUPPORT)
#if defined(SERIAL_CALIBRATION_REF_SUPPORT)
U0ME |= (UTXE0 | URXE0);
#elif defined(SERIAL_CALIBRATION_SUPPORT)
U0ME |= URXE0;
#else
U0ME |= UTXE0;
#endif
#endif
#if defined(__MSP430_HAS_TA3__) && (defined(__MSP430_HAS_ADC12__) || defined(__MSP430_HAS_SD16_3__))
/* Enable the TIMER_A0 interrupt */
TACTL = TACLR | MC_1 | TASSEL_1;
TACCTL0 = CCIE;
#endif
kick_watchdog();
#if defined(LOSE_FRACTIONAL_PULSE_AT_POWER_ON)
#if defined(PER_PHASE_ENERGY_SUPPORT)
phase->power_counter = 0;
#endif
#if defined(TOTAL_ENERGY_SUPPORT)
total_power_counter = 0;
#if TOTAL_ENERGY_PULSES_PER_KW_HOUR < 1000
extra_total_power_counter = 0;
#endif
#endif
#if defined(TOTAL_REACTIVE_ENERGY_SUPPORT)
total_reactive_power_counter = 0;
#if TOTAL_ENERGY_PULSES_PER_KW_HOUR < 1000
extra_total_reactive_power_counter = 0;
#endif
#endif
#endif
#if defined(BATTERY_MONITOR_SUPPORT)
if (battery_countdown)
{
battery_countdown = 1000;
/* Battery sensing control pin */
P3DIR |= (BIT1);
P3OUT &= ~(BIT1);
}
#endif
/* Come out of power down in limp mode, as we don't know
if there is sufficent power available to driver the meter
at full speed. We will soon switch to normal mode if a
voltage signal is available. */
/* Limp mode will fire up the ADC again. */
#if defined(LIMP_MODE_SUPPORT)
switch_to_limp_mode();
#else
switch_to_normal_mode();
#endif
custom_power_restore_handler();
}
#endif
#else
void switch_to_normal_mode(void)
{
}
#if defined(LIMP_MODE_SUPPORT)
void switch_to_limp_mode(void)
{
}
#endif
#if defined(POWER_DOWN_SUPPORT)
void switch_to_powerfail_mode(void)
{
}
#endif
#endif
#if defined(__MSP430_HAS_TA3__)
int32_t assess_rtc_speed(void)
{
int32_t period;
uint16_t this_capture;
uint16_t last_capture;
uint16_t step;
int32_t counter;
int limit;
/* The fast clock should be an exact multiple of the crystal clock, once the FLL has
settled. If we capture many cycles of an accurate external 32768Hz clock, using
timer A (or B), we can measure the speed difference between the MSP430's crystal
and the external clock in a reasonable time. */
/* The SM clock should be running at 244*32768Hz at this time. */
_DINT();
/* Change timer A to running fast, and sampling the external 32768Hz reference. */
P2SEL |= BIT0;
TACCR0 = 0xFFFF;
TACCTL0 = CAP | CCIS_0 | CM_1;
TACCTL2 = CAP | CCIS_0 | CM_1 | SCS;
TACTL = TACLR | MC_2 | TASSEL_2; /* start TIMER_A up mode, SMCLK as input clock */
period = 0;
last_capture = TACCR2;
limit = -1;
TACCTL2 &= ~CCIFG;
for (counter = 0; counter < 32768*5 + 1; counter++)
{
limit = 1000;
while (!(TACCTL2 & CCIFG))
{
if (--limit <= 0)
break;
}
if (limit <= 0)
break;
TACCTL2 &= ~CCIFG;
this_capture = TACCR2;
step = this_capture - last_capture;
last_capture = this_capture;
/* Skip the first sample, as it will be meaningless */
if (counter)
{
#if 0
if (step < (244 - 5) || step > (244 + 5))
{
limit = -2;
break;
}
#endif
period += step;
}
kick_watchdog();
}
if (limit <= 0)
period = limit;
#if defined(__MSP430_HAS_ADC12__)
/* Change timer A back to controlling the ADC sampling interval, and the ADC on/off timing. */
/* CCR0 determines the sample period */
TACCR0 = SAMPLE_PERIOD - 1;
TACCR1 = SAMPLE_PERIOD - 3;
TACCR2 = SAMPLE_PERIOD - 4;
TACCTL1 = OUTMOD_3;
#endif
TACTL = TACLR | MC_1 | TASSEL_1;
TACCTL0 = CCIE;
P2SEL &= ~BIT0;
_EINT();
return period;
}
#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -