#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_2;
/* 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 | MSC | REF2_5V | REFON | ADC12ON | ENC;
/* 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;
for (sample_index = 0; sample_index < NUMBER_SAMPLES; ++sample_index)
{
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();
}