Пример #1
0
/**
 * \brief Initialize ADC
 *
 * Here the averaging feature is disabled.
 */
static void main_adc_init(void)
{
	/* ADC module configuration structure */
	struct adc_config adc_conf;
	/* ADC channel configuration structure */
	struct adc_channel_config adcch_conf;

	/* Configure the ADC module:
	 * - unsigned, more than 12-bit results
	 * - VCC /2 voltage reference
	 * - 200 kHz maximum clock rate
	 * - freerun conversion triggering
	 * - enabled internal temperature sensor
	 */
	adc_read_configuration(&ADCA, &adc_conf);
	adc_set_conversion_parameters(&adc_conf, ADC_SIGN_OFF, ADC_RES_12,
			ADC_REF_VCCDIV2);
	adc_set_clock_rate(&adc_conf, 200000UL);
	adc_set_conversion_trigger(&adc_conf, ADC_TRIG_FREERUN, 1, 0);
	adc_enable_internal_input(&adc_conf, ADC_INT_TEMPSENSE);
	adc_write_configuration(&ADCA, &adc_conf);

	/* Configure ADC channel 0:
	 * - single-ended measurement from temperature sensor
	 * - interrupt flag set on completed conversion
	 */
	adcch_read_configuration(&ADCA, ADC_CH0, &adcch_conf);
	adcch_set_input(&adcch_conf, ADCCH_POS_TEMPSENSE, ADCCH_NEG_NONE, 1);
	adcch_set_interrupt_mode(&adcch_conf, ADCCH_MODE_COMPLETE);
	adcch_disable_interrupt(&adcch_conf);
	adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf);

	/* Enable ADC which starts the freerun conversion.*/
	adc_enable(&ADCA);
}
Пример #2
0
/**
 * \brief Callback function for ADCB-CH0 interrupts
 *  - Interrupt is configured for Conversion Complete Interrupt
 *  - ADCA CH0 result is accumulated
 *  - ADC sample count is incremented
 *  - Check If ADC sample count reached up to number of oversampling required
 *  - If so, disable ADC interrupt and set flag to start oversampling process
 *
 * \param adc Pointer to ADC module.
 * \param ch_mask ADC channel mask.
 * \param result Conversion result from ADC channel.
 */
static void adc_handler(ADC_t *adc, uint8_t ch_mask, adc_result_t result)
{
	/*  Get Result from ADCB-CH0 Register and Accumulate */
	adc_result_accumulator +=  result;

	/* Increment sample count */
	adc_samplecount++;

	/* Check if sample count has reached oversample count */
	if (adc_samplecount >= ADC_OVER_SAMPLED_NUMBER) {
		/* Disable ADCB-CHO conversion complete interrupt until stored
		 * samples are processed
		 */
		adcch_disable_interrupt(&adc_ch_conf);
		adcch_write_configuration(&ADCB, ADC_CH0, &adc_ch_conf);

		/* Clear any pending interrupt request by clearing interrupt
		 * flag
		 */
		adc_clear_interrupt_flag(&ADCB, ADC_CH0);

		/*Set adc_oversampled_flag to start oversampling process from
		 * main function
		 */
		adc_oversampled_flag = true;

		/* Store single sample ADC result to find analog input without
		 * oversampling
		 */
		adc_result_one_sample = result;
	}
}
Пример #3
0
/**
 * \brief Callback function that changes ADC settings
 *
 * This callback function for the ADC driver is used to change the ADC reference
 * after the next completed conversion, simulating a problem with the voltage
 * reference. It will be triggered after the next completed conversion.
 *
 * The fault will be detected when the analog IO test is run, i.e., when the
 * user turns up the power of the plate from 0.
 */
static void adc_foul_callback(ADC_t *adc, uint8_t ch_mask, adc_result_t res)
{
	struct adc_channel_config adcch_conf;

	adc->REFCTRL = ADC_REFSEL_INTVCC_gc;

	adcch_read_configuration(adc, ch_mask, &adcch_conf);
	adcch_disable_interrupt(&adcch_conf);
	adcch_write_configuration(adc, ch_mask, &adcch_conf);
}
/**
 * \brief Initialize ADC
 */
static void main_adc_init(void)
{
	/* ADC module configuration structure */
	struct adc_config adc_conf;
	/* ADC channel configuration structure */
	struct adc_channel_config adcch_conf;

	/* Configure the ADC module:
	 * - signed, 12-bit results
	 * - voltage reference = VCC / 1.6 = 3.3V / 1.6
	 * - 200 kHz maximum clock rate
	 * - manual conversion triggering
	 */
	adc_read_configuration(&ADCA, &adc_conf); /* Initialize structures. */
	adc_set_conversion_parameters(&adc_conf, ADC_SIGN_ON, ADC_RES_12,
			ADC_REF_VCC);
	adc_set_clock_rate(&adc_conf, 200000UL);
	adc_set_conversion_trigger(&adc_conf, ADC_TRIG_MANUAL, 1, 0);
	adc_write_configuration(&ADCA, &adc_conf);

	/* Configure ADC channel:
	 * - differential measurement mode
	 * - Input voltage V+ is ADC2 pin (PA2 pin)
	 * - Input voltage V- is ADC3 pin (PA3 pin)
	 * - 1x gain
	 * - interrupt flag set on completed conversion
	 */
	adcch_read_configuration(&ADCA, ADC_CH0, &adcch_conf);
	adcch_set_input(&adcch_conf, ADCCH_POS_PIN2, ADCCH_NEG_PIN3, 1);
	adcch_set_interrupt_mode(&adcch_conf, ADCCH_MODE_COMPLETE);
	adcch_disable_interrupt(&adcch_conf);
	adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf);

	/* Enable ADC */
	adc_enable(&ADCA);

	/* Do useful conversion */
	adc_start_conversion(&ADCA, ADC_CH0);
	adc_wait_for_interrupt_flag(&ADCA, ADC_CH0);
}
Пример #5
0
/**
 * \internal
 * \brief Measure differential input MUX combinations on channel
 *
 * Measures a set of input MUX combinations on a single channel, using averaging
 * of the number of samples specified with \ref NUM_AVERAGE_SAMPLES.
 *
 * \pre This function does not configure the ADC, only the ADC channel, and
 * therefore the specified ADC needs to be configured before this function
 * is run.
 *
 * \param adc Pointer to ADC to measure with.
 * \param ch_mask Mask for channel to measure with.
 * \param mux_pos_inputs Pointer to array of positive input MUX settings.
 * \param mux_neg_inputs Pointer to array of negative input MUX settings.
 * \param num_inputs Number of input MUX setting pairs.
 * \param results Pointer to array to store results in.
 * \param gain Gain to use for all measurements.
 *
 * \note The array which \e results points to must have at least \e num_inputs
 * elements.
 */
static void differential_signed_average(ADC_t *adc, uint8_t ch_mask,
		const uint8_t *mux_pos_inputs, const uint8_t *mux_neg_inputs,
		uint8_t num_inputs, int16_t *results, uint8_t gain)
{
	struct adc_channel_config adcch_conf;
	uint8_t input;
	uint8_t i;
	int32_t sum;

	memset(&adcch_conf, 0, sizeof(struct adc_channel_config));

	// Common configuration
	adcch_set_interrupt_mode(&adcch_conf, ADCCH_MODE_COMPLETE);
	adcch_disable_interrupt(&adcch_conf);

	for (input = 0; input < num_inputs; input++) {
		adcch_set_input(&adcch_conf, mux_pos_inputs[input],
				mux_neg_inputs[input], gain);
		adcch_write_configuration(adc, ch_mask, &adcch_conf);

		// Enable and do dummy conversion
		adc_enable(adc);
		adc_start_conversion(adc, ch_mask);
		adc_wait_for_interrupt_flag(adc, ch_mask);

		// Read an average
		sum = 0;
		for (i = 0; i < NUM_AVERAGE_SAMPLES; i++) {
			adc_start_conversion(adc, ch_mask);
			adc_wait_for_interrupt_flag(adc, ch_mask);
			sum += (int16_t)adc_get_result(adc, ch_mask);
		}
		adc_disable(adc);

		results[input] = sum / NUM_AVERAGE_SAMPLES;
	}
}
Пример #6
0
int main(void)
{
	struct adc_config         adc_conf;
	struct adc_channel_config adcch_conf;

	board_init();
	sysclk_init();
	sleepmgr_init();
	irq_initialize_vectors();
	cpu_irq_enable();

	// Initialize configuration structures.
	adc_read_configuration(&ADCA, &adc_conf);
	adcch_read_configuration(&ADCA, ADC_CH0, &adcch_conf);

	/* Configure the ADC module:
	 * - unsigned, 12-bit results
	 * - bandgap (1 V) voltage reference
	 * - 200 kHz maximum clock rate
	 * - manual conversion triggering
	 */
	adc_set_conversion_parameters(&adc_conf, ADC_SIGN_OFF, ADC_RES_12,
			ADC_REF_BANDGAP);
	adc_set_clock_rate(&adc_conf, 200000UL);
	adc_set_conversion_trigger(&adc_conf, ADC_TRIG_MANUAL, 1, 0);

	adc_write_configuration(&ADCA, &adc_conf);

	/* Configure ADC channel 0:
	 * - single-ended measurement from configured input pin
	 * - interrupt flag set on completed conversion
	 */
	adcch_set_input(&adcch_conf, INPUT_PIN, ADCCH_NEG_NONE,
			1);
	adcch_set_interrupt_mode(&adcch_conf, ADCCH_MODE_COMPLETE);
	adcch_disable_interrupt(&adcch_conf);

	adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf);

	// Enable the ADC and do one dummy conversion.
	adc_enable(&ADCA);
	adc_start_conversion(&ADCA, ADC_CH0);
	adc_wait_for_interrupt_flag(&ADCA, ADC_CH0);

	// Light up LED 1, wait for button press.
	ioport_set_pin_low(LED1_PIN);
	wait_for_button();

	// Perform oversampling of offset.
	cal_data.offset = get_mean_sample_value();

	// Light up LED 2, wait for button press.
	ioport_set_pin_low(LED2_PIN);
	wait_for_button();

	// Perform oversampling of 0.9 V for gain calibration.
	cal_data.gain = get_mean_sample_value() - cal_data.offset;

	// Turn off LEDs.
	ioport_set_pin_high(LED1_PIN);
	ioport_set_pin_high(LED2_PIN);

	// Enable interrupts on ADC channel, then trigger first conversion.
	adcch_enable_interrupt(&adcch_conf);
	adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf);
	adc_start_conversion(&ADCA, ADC_CH0);

	do {
		// Sleep until ADC interrupt triggers.
		sleepmgr_enter_sleep();
	} while (1);
}