#include "io430.h" void SetConversion(unsigned int value); unsigned int GetConversion(void); void WaitConversion(void); #define NUMBER_SAMPLES (3) void SetDCORegisters(unsigned char bcsctl, unsigned char dcoctl) { char current_rsel = (BCSCTL1 & 0x0F); char new_rsel = (bcsctl & 0x0F); /* Clear DCO bits initially to prevent going over * frequency during change (see device errata sheet). */ DCOCTL = 0; /* Apply intermediate step */ if ((current_rsel > 13 && new_rsel < 13) | (current_rsel < 13 && new_rsel > 13)) { BCSCTL1 = (BCSCTL1 & 0xF0) | 13; } /* Set new range */ BCSCTL1 = (BCSCTL1 & 0xF0) | bcsctl; /* Set target DCO and modulation fields */ DCOCTL = dcoctl; } int main( void ) { unsigned int sample; unsigned int samples[NUMBER_SAMPLES] = {0}; int sample_index; unsigned long total; /* Stop watchdog timer to prevent time out reset */ WDTCTL = WDTPW + WDTHOLD; if ((CALDCO_1MHZ != 0xFF) && (CALBC1_1MHZ != 0xFF)) { SetDCORegisters(CALBC1_1MHZ, CALDCO_1MHZ); } BCSCTL2 = (BCSCTL2 & ~(DIVM1|DIVM0|DIVS1|DIVS0)) | DIVM_0 | DIVS_0; /* Wait for oscillator startup */ while (IFG1_bit.OFIFG) { unsigned char tdelay = 0xFF; IFG1_bit.OFIFG = 0; while (tdelay > 0) { tdelay--; } } __enable_interrupt(); while (1) { total = 0; /* Ensure ADC12 is configurable */ ADC12CTL0 &= ~ENC; /* Convert from memory control 0, * Use ADC12SC for S/H * Use pulse mode for sample timing * Do not invert S/H signal * ADC12 clock divider = 1 * Sourced from ACLK * Repeat single channel mode */ ADC12CTL1 = CSTARTADD_0 | SHS_0 | SHP | ADC12DIV_0 | ADC12SSEL_1 | CONSEQ_0; /* Select input range from internal Vref+ to AVss and temperature sensor channel */ ADC12MCTL0 = SREF_1 | INCH_10; /* Clear any pending interrupt for result 0 */ ADC12IFG &= ~BIT0; /* Enable interrupts for result 0 */ ADC12IE |= BIT0; /* Complete configuration and enable conversions. * Don't care about SHT1x * Sample hold time is 4 ADC12CLKs @ 32768 = 122us (needs to be minimum 30us for temperature channel) * Multiple Sample and Convert (MSC) set for repeated conversion * Reference voltage 2.5 * Enable reference * Enable ADC12 * No MEMx overflow * No conversion time overflow * Enable conversions */ ADC12CTL0 = SHT0_0 | REF2_5V | REFON | ADC12ON | ENC; for (sample_index = 0; sample_index < NUMBER_SAMPLES; ++sample_index) { /* Start conversion - could be done at same time as above statement, * could have ENC set along with it. Can also set up once and just use * this for each conversion (only works when SC is the trigger). */ ADC12CTL0 |= ADC12SC; WaitConversion(); sample = GetConversion(); samples[sample_index] = sample; total += sample; } // Disable ADC12 /* Disable conversions so we can configure the module */ ADC12CTL0 &= ~(ENC); /* Disable reference and module */ ADC12CTL0 &= ~(REFON | ADC12ON); /* Disable interrupts */ ADC12IE &= ~BIT0; } } #pragma vector=ADC12_VECTOR __interrupt void ADC12ISR(void) { switch (__even_in_range(ADC12IV, ADC12IV_ADC12IFG15)) { case ADC12IV_ADC12IFG0: SetConversion(ADC12MEM0); __low_power_mode_off_on_exit(); break; default: break; } } static volatile unsigned int s_conversion_complete; static volatile unsigned int s_sample; void SetConversion(unsigned int value) { s_sample = value; s_conversion_complete = 1; } unsigned int GetConversion(void) { unsigned int value; ADC12IE &= ~BIT0; value = s_sample; ADC12IE |= BIT0; return (value); } void WaitConversion(void) { unsigned int wait; __disable_interrupt(); wait = s_conversion_complete; while (0 == wait) { __low_power_mode_3(); __disable_interrupt(); wait = s_conversion_complete; } s_conversion_complete = 0; __enable_interrupt(); }