Пример #1
0
void adcInit()
{
	struct adc_config adc_conf;
	struct adc_channel_config adc_ch_conf;
	
	/* Clear the ADC configuration structs */
	adc_read_configuration(&ADCA, &adc_conf);
	adcch_read_configuration(&ADCA, ADC_CH0, &adc_ch_conf);
	
	adc_set_conversion_parameters(&adc_conf, ADC_SIGN_ON, ADC_RES_12,
	ADC_REF_VCC);
	adc_set_clock_rate(&adc_conf, 100000UL);
	adc_set_conversion_trigger(&adc_conf, ADC_TRIG_MANUAL, 0, 0);
	adc_write_configuration(&ADCA, &adc_conf);
	//adc_set_callback(&ADCA, &adc_handler);
	
	adcch_set_input(&adc_ch_conf, ADCCH_POS_PIN0, ADCCH_NEG_PIN5, 1);
	//adcch_set_interrupt_mode(&adc_ch_conf, ADCCH_MODE_COMPLETE);
	//adcch_enable_interrupt(&adc_ch_conf);
	adcch_write_configuration(&ADCA, ADC_CH1, &adc_ch_conf);
	
	
	adcch_set_input(&adc_ch_conf, ADCCH_POS_PIN0, ADCCH_NEG_PIN6, 1);
	adcch_write_configuration(&ADCA, ADC_CH0, &adc_ch_conf);


	adc_enable(&ADCA);
}
Пример #2
0
/**
 * \brief Configure the ADC for DAC calibration
 */
static void configure_adc(void)
{
	struct adc_config adc_conf;
	struct adc_channel_config adcch_conf;

	adc_read_configuration(&CALIBRATION_ADC, &adc_conf);
	adcch_read_configuration(&CALIBRATION_ADC, ADC_CH_TO_DAC_CH0, &adcch_conf);

	adc_set_conversion_parameters(&adc_conf, ADC_SIGN_ON, ADC_RES_12, ADC_REF_VCC);
	adc_set_conversion_trigger(&adc_conf, ADC_TRIG_MANUAL, 2, 0);
	adc_set_clock_rate(&adc_conf, 62500UL);

	adcch_set_input(&adcch_conf, ADCCH_POS_PIN1, ADCCH_NEG_PIN1, 1);

	adc_write_configuration(&CALIBRATION_ADC, &adc_conf);
	adcch_write_configuration(&CALIBRATION_ADC, ADC_CH_TO_DAC_CH0, &adcch_conf);

	/* Find the offset of the ADC */
	adc_enable(&CALIBRATION_ADC);
	adc_offset = adc_get_sample_avg(ADC_CH_TO_DAC_CH0, 128);
	adc_disable(&CALIBRATION_ADC);

	/* Switch input to the DAC output pin PB3, i.e. ADC pin 11 */
	adcch_set_input(&adcch_conf, ADCCH_POS_PIN10, ADCCH_NEG_PAD_GND, 1);
	adcch_write_configuration(&CALIBRATION_ADC, ADC_CH_TO_DAC_CH0, &adcch_conf);

	adcch_set_input(&adcch_conf, ADCCH_POS_PIN11, ADCCH_NEG_PAD_GND, 1);
	adcch_write_configuration(&CALIBRATION_ADC, ADC_CH_TO_DAC_CH1, &adcch_conf);

	adc_enable(&CALIBRATION_ADC);

}
Пример #3
0
/**
 * \brief Measures and enables offset and gain corrections
 */
static void main_adc_correction(void)
{
	/* ADC channel configuration structure */
	struct adc_channel_config adcch_conf;
	uint16_t offset_correction;

	/* Expected value for gain correction at 1.9V
	 * expected_value = Max. range * 1.9V / (VCC / 1.6)
	 * Max. range = 12 bits signed = 11 bits unsigned
	 */
	const uint16_t expected_value
		= ((1 << 11) * 1900UL) / (3300L * 1000L / 1600L);
	/* Captured value for gain correction */
	uint16_t captured_value;

	/* DAC Output 0 Volt */
	main_dac_output(0);

	/* Capture value for 0 Volt */
	adc_wait_for_interrupt_flag(&ADCA, ADC_CH0);
	adc_wait_for_interrupt_flag(&ADCA, ADC_CH0);
	offset_correction = adc_get_unsigned_result(&ADCA, ADC_CH0);

	/* Enable offset correction */
	adcch_read_configuration(&ADCA, ADC_CH0, &adcch_conf);
	adcch_enable_correction(&adcch_conf, offset_correction, 1, 1);
	adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf);

	/* DAC Output 1.9 Volts */
	main_dac_output(1900);

	/* Capture value for 1.9 Volts */
	adc_wait_for_interrupt_flag(&ADCA, ADC_CH0);
	adc_wait_for_interrupt_flag(&ADCA, ADC_CH0);
	captured_value = adc_get_unsigned_result(&ADCA, ADC_CH0);

	/* Enable offset & gain correction */
	adcch_enable_correction(&adcch_conf, offset_correction, expected_value,
			captured_value);
	adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf);

	printf("\n\rADC correction:  ");
	printf("Offset correction %d,   ", offset_correction);
	if (expected_value > captured_value) {
		printf("Gain correction 1.%03u\n\r\n\r", (uint16_t)
				((((uint32_t)expected_value - captured_value)
				* 1000) / captured_value));
	} else {
		printf("Gain correction 0.%03u\n\r\n\r", (uint16_t)
				(((uint32_t)expected_value
				* 1000) / captured_value));
	}
}
Пример #4
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);
}
Пример #5
0
/**
 * \brief Initialize ADC and DAC used to simulate a temperature sensor
 *
 * DACB is used by the simulation plant to output a temperature reading of the
 * oven plate. It is set up to output a voltage on pin B2 which is marked as
 * ADC2 on header J2.
 *
 * ADCA is used in the control step and graphical interface to show the current
 * temperature of the oven plate. It is set up to read a voltage on pin A4 which
 * is marked as ADC4 on header J2.
 *
 * ADC2 and ADC4 should be connected together, so that the ADC samples the DAC
 * directly.
 */
void main_init_adc_dac(void)
{
    struct adc_config adc_conf;
    struct adc_channel_config adcch_conf;
    struct dac_config dac_conf;

    /* Set up the DAC for the simulation to output "real" temperature */
    dac_read_configuration(&DACB, &dac_conf);
    dac_set_conversion_parameters(&dac_conf, DAC_REF_BANDGAP,
                                  DAC_ADJ_RIGHT);
    dac_set_active_channel(&dac_conf, DAC_CH0, 0);
    dac_write_configuration(&DACB, &dac_conf);
    dac_enable(&DACB);

    /* Set up the ADC for the controller to read "real" temperature */
    adc_read_configuration(&ADCA, &adc_conf);
    adcch_read_configuration(&ADCA, ADC_CH0, &adcch_conf);
    adc_set_conversion_parameters(&adc_conf, ADC_SIGN_ON, ADC_RES_12,
                                  ADC_REF_BANDGAP);
    adc_set_clock_rate(&adc_conf, 20000UL);
    adc_set_conversion_trigger(&adc_conf, ADC_TRIG_MANUAL, 1, 0);
    adc_write_configuration(&ADCA, &adc_conf);
    adcch_set_input(&adcch_conf, ADCCH_POS_PIN4, ADCCH_NEG_NONE, 1);
    adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf);
    adc_enable(&ADCA);
    adc_start_conversion(&ADCA, ADC_CH0);

    /* Enable pull-down, so an open circuit can be detected */
    ioport_set_pin_dir(J2_PIN4, IOPORT_DIR_INPUT);
    ioport_set_pin_mode(J2_PIN4, IOPORT_MODE_PULLDOWN);
}
Пример #6
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;
	}
}
Пример #7
0
/**
 * \brief Callback function for ADC interrupts
 *
 * \param adc Pointer to ADC module.
 * \param channel ADC channel number.
 * \param result Conversion result from ADC channel.
 */
static void adc_handler(ADC_t *adc, uint8_t channel, adc_result_t result)
{
	switch (adc_conv[adc_mux_index].in) {
		case EXT_VIN_ADC_INPUT:
			ext_voltage=result;
			adc_mux_index++;

			//start new measurement
			adc_disable(&EXT_VIN_ADC_MODULE);
			adc_set_conversion_parameters(&adc_conf
					,ADC_SIGN_OFF
					,ADC_RES_12
					,adc_conv[adc_mux_index].ref);
			adc_write_configuration(
					&POTENTIOMETER_ADC_MODULE
					, &adc_conf);
			adc_enable(&POTENTIOMETER_ADC_MODULE);
			adcch_set_input(&adcch_conf
					,adc_conv[adc_mux_index].in
					,ADCCH_NEG_NONE,1);
			adcch_write_configuration(
					&POTENTIOMETER_ADC_MODULE
					, ADC_CH0, &adcch_conf);
			adc_start_conversion(&POTENTIOMETER_ADC_MODULE
					, ADC_CH0);
			break;
		case POTENTIOMETER_ADC_INPUT:
			potentiometer=result;
		break;

		default:
		break;
	}
}
Пример #8
0
int adc_init(void)
{
	/* Offset Measurement*/
	/*
	struct adc_config adc_conf;
	struct adc_channel_config adcch_conf;
	adc_read_configuration(&MY_ADC, &adc_conf);
	adcch_read_configuration(&MY_ADC, MY_ADC_CH, &adcch_conf);
	adc_set_conversion_parameters(&adc_conf, ADC_SIGN_ON, ADC_RES_12, ADC_REF_AREFA);
	adc_set_conversion_trigger(&adc_conf, ADC_TRIG_MANUAL, 1, 0);
	adc_set_clock_rate(&adc_conf, 62500UL);
	adcch_set_input(&adcch_conf, ADCCH_POS_PIN4, ADCCH_NEG_PIN4, 1);
	adc_write_configuration(&MY_ADC, &adc_conf);
	adcch_write_configuration(&MY_ADC, MY_ADC_CH, &adcch_conf);
	adc_enable(&MY_ADC);
	*/
	
	/* Normal Measurement*/
	struct adc_config adc_conf;
	struct adc_channel_config adcch_conf;
	adc_read_configuration(&MY_ADC, &adc_conf);
	adcch_read_configuration(&MY_ADC, MY_ADC_CH, &adcch_conf);
	adc_set_conversion_parameters(&adc_conf, ADC_SIGN_OFF, ADC_RES_12, ADC_REF_AREFA);
	adc_set_conversion_trigger(&adc_conf, ADC_TRIG_MANUAL, 1, 0);
	adc_set_clock_rate(&adc_conf, 62500UL);
	adcch_set_input(&adcch_conf, ADCCH_POS_PIN4, ADCCH_NEG_NONE, 1); //PAD_GND
	adc_write_configuration(&MY_ADC, &adc_conf);
	adcch_write_configuration(&MY_ADC, MY_ADC_CH, &adcch_conf);
	adc_enable(&MY_ADC);
	
	return 0;
}
Пример #9
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();
	gfx_mono_init();

	// Enable back light of display
	ioport_set_pin_high(LCD_BACKLIGHT_ENABLE_PIN);

	// 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
	 * - VCC voltage reference
	 * - 200 kHz maximum clock rate
	 * - manual conversion triggering
	 * - temperature sensor enabled
	 * - callback function
	 */
	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_enable_internal_input(&adc_conf, ADC_INT_TEMPSENSE);

	adc_write_configuration(&ADCA, &adc_conf);
	adc_set_callback(&ADCA, &adc_handler);

	/* Configure ADC channel 0:
	 * - single-ended measurement from temperature sensor
	 * - interrupt flag set on completed conversion
	 * - interrupts disabled
	 */
	adcch_set_input(&adcch_conf, ADCCH_POS_PIN1, ADCCH_NEG_NONE,
			1);
	adcch_set_interrupt_mode(&adcch_conf, ADCCH_MODE_COMPLETE);
	adcch_enable_interrupt(&adcch_conf);

	adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf);

	// Enable the ADC and start the first conversion.
	adc_enable(&ADCA);
	adc_start_conversion(&ADCA, ADC_CH0);

	do {
		// Sleep until ADC interrupt triggers.
		sleepmgr_enter_sleep();
	} while (1);
}
Пример #10
0
/**
 * \brief Start the next convertion according to \ref adc_mux_index index
 */
static void app_sampling_start_next_conversion(void)
{
	/* Setup ADC to start next one */
	adcch_set_input(&adcch_conf, adc_conv[adc_mux_index],
			ADCCH_NEG_INTERNAL_GND, 0);
	adcch_write_configuration(&LIGHT_SENSOR_ADC_MODULE, ADC_CH0,
			&adcch_conf);
	adc_start_conversion(&LIGHT_SENSOR_ADC_MODULE, ADC_CH0);
}
Пример #11
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
     * - temperature sensor enabled
     * - callback function
     */
    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_enable_internal_input(&adc_conf, ADC_INT_TEMPSENSE);

    adc_write_configuration(&ADCA, &adc_conf);
    adc_set_callback(&ADCA, &adc_handler);

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

    adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf);

    // Get measurement for 85 degrees C (358 kelvin) from calibration data.
    tempsense = adc_get_calibration_data(ADC_CAL_TEMPSENSE);

    // Enable the ADC and start the first conversion.
    adc_enable(&ADCA);
    adc_start_conversion(&ADCA, ADC_CH0);

    do {
        // Sleep until ADC interrupt triggers.
        sleepmgr_enter_sleep();
    } while (1);
}
Пример #12
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 Disables offset and gain corrections
 */
static void main_adc_correction_stop(void)
{
	/* ADC channel configuration structure */
	struct adc_channel_config adcch_conf;

	printf("\n\r* ADC correction disabled\n\r");
	adcch_read_configuration(&ADCA, ADC_CH0, &adcch_conf);
	adcch_disable_correction(&adcch_conf);
	adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf);
}
Пример #14
0
/**
 * \internal
 * \brief Test averaging conversion in 12-bit mode using the DAC
 *
 * These values are then measured using the ADC on the pins that are connected
 * to the DAC channel, and the results are compared and checked to see if they
 * are within the acceptable average of values that passes the test.
 *
 * \param test Current test case.
 */
static void run_averaging_conversion_test(
		const struct test_case *test)
{
	int16_t volt_output;
	int16_t volt_min, volt_max, volt_input;

	/* ADC module configuration structure */
	struct adc_config adc_conf;
	/* ADC channel configuration structure */
	struct adc_channel_config adcch_conf;

	adc_disable(&ADCA);

	/* Change resolution parameter to accept averaging */
	adc_read_configuration(&ADCA, &adc_conf);
	adc_set_conversion_parameters(&adc_conf, ADC_SIGN_ON, ADC_RES_MT12,
			ADC_REF_VCC);
	adc_write_configuration(&ADCA, &adc_conf);

	/* Enable averaging */
	adcch_read_configuration(&ADCA, ADC_CH0, &adcch_conf);
	adcch_enable_averaging(&adcch_conf, ADC_SAMPNUM_1024X);
	adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf);

	adc_enable(&ADCA);
	adc_wait_for_interrupt_flag(&ADCA, ADC_CH0);

	/* Check values */
	for (volt_output = -CONV_MAX_VOLTAGE;
			volt_output <= CONV_MAX_VOLTAGE;
			volt_output += CONV_VOLTAGE_STEP) {
		main_dac_output(volt_output);
		/* first capture */
		volt_input = main_adc_input();
		volt_min = volt_max = volt_input;
		/* several capture */
		for (uint8_t i = 0; i < 5; i++) {
			volt_input = main_adc_input();
			if (volt_min > volt_input) {
				volt_min = volt_input;
			}

			if (volt_max < volt_input) {
				volt_max = volt_input;
			}
		}

		test_assert_true(test,
				(volt_max - volt_min) < CONF_TEST_ACCEPT_DELTA_AVERAGING,
				"ADC result is not in acceptable stable range (Min %dmV, Max %dmV)",
				volt_min, volt_max);
	}
}
Пример #15
0
/**
 * \brief Timer Counter Overflow interrupt callback function
 *
 * This function is called when an overflow interrupt has occurred on
 * TCC0.
 */
static void tcc0_ovf_interrupt_callback(void)
{
	adc_mux_index=0;
	adc_disable(&EXT_VIN_ADC_MODULE);
	adc_set_conversion_parameters(&adc_conf, ADC_SIGN_OFF, ADC_RES_12
			,adc_conv[adc_mux_index].ref);
	adc_write_configuration(&EXT_VIN_ADC_MODULE, &adc_conf);
	adc_enable(&EXT_VIN_ADC_MODULE);
	adcch_set_input(&adcch_conf, adc_conv[adc_mux_index].in
			, ADCCH_NEG_NONE,1);
	adcch_write_configuration(&EXT_VIN_ADC_MODULE, ADC_CH0, &adcch_conf);
	adc_start_conversion(&EXT_VIN_ADC_MODULE, ADC_CH0);
}
Пример #16
0
void ADC_init_funct(void) {
	struct adc_config adc_conf;
	struct adc_channel_config adcch_conf;

	adc_read_configuration(&MY_ADC, &adc_conf);
	adcch_read_configuration(&MY_ADC, CAP_ADC, &adcch_conf);

	adc_set_conversion_parameters(&adc_conf, ADC_SIGN_OFF, ADC_RES_12,ADC_REF_VCC);
	adc_set_conversion_trigger(&adc_conf, ADC_TRIG_MANUAL, 1, 0);
	adc_set_clock_rate(&adc_conf, 100000);
	adcch_set_input(&adcch_conf, ADCCH_POS_PIN3, ADCCH_NEG_NONE, 1);

	adc_write_configuration(&MY_ADC, &adc_conf);
	adcch_write_configuration(&MY_ADC, CAP_ADC, &adcch_conf);
	adc_enable (&MY_ADC);
}
Пример #17
0
void owltemp_init() {
	struct adc_config         adc_conf;
	struct adc_channel_config adcch_conf;

	// Clear the configuration structures.
	memset(&adc_conf, 0, sizeof(struct adc_config));
	memset(&adcch_conf, 0, sizeof(struct adc_channel_config));

	/* Configure the ADC module:
	 * - unsigned, 12-bit results
	 * - bandgap (1 V) voltage reference
	 * - 200 kHz maximum clock rate
	 * - manual conversion triggering
	 * - temperature sensor enabled
	 * - callback function
	 */
	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, 0, 0);
	adc_enable_internal_input(&adc_conf, ADC_INT_TEMPSENSE);

	adc_write_configuration(&ADCA, &adc_conf);
	adc_set_callback(&ADCA, &adc_handler);

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

	adcch_write_configuration(&ADCA, 0, &adcch_conf);

	// Get measurement for 85 degrees C (358 kelvin) from calibration data.
	tempsense = adc_get_calibration_data(ADC_CAL_TEMPSENSE);

	// Enable the ADC and start the first conversion.
	adc_enable(&ADCA);
	adc_start_conversion(&ADCA, ADC_CH0);

}
Пример #18
0
static void adc_init(void)
{
	struct adc_config adc_conf;
	struct adc_channel_config adcch_conf;

	adc_read_configuration(&MY_ADC, &adc_conf);
	adcch_read_configuration(&MY_ADC, MY_ADC_CH, &adcch_conf);

	adc_set_conversion_parameters(&adc_conf, ADC_SIGN_OFF, ADC_RES_12,
	ADC_REF_AREFA);
	adc_set_conversion_trigger(&adc_conf, ADC_TRIG_MANUAL, 1, 0);
	adc_set_clock_rate(&adc_conf, 200000UL);

	adcch_set_input(&adcch_conf, ADCCH_POS_PIN1, ADCCH_NEG_NONE, 1);

	adc_write_configuration(&MY_ADC, &adc_conf);
	adcch_write_configuration(&MY_ADC, MY_ADC_CH, &adcch_conf);
	
	adc_enable(&MY_ADC);
	adc_start_conversion(&MY_ADC, MY_ADC_CH);
}
/**
 * \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);
}
/**
 * \brief Disables over-sampling
 */
static void main_adc_oversampling_stop(void)
{
    /* ADC module configuration structure */
    struct adc_config adc_conf;
    /* ADC channel configuration structure */
    struct adc_channel_config adcch_conf;

    adc_disable(&ADCA);

    /* Set default resolution parameter */
    adc_read_configuration(&ADCA, &adc_conf);
    adc_set_conversion_parameters(&adc_conf, ADC_SIGN_OFF, ADC_RES_12,
                                  ADC_REF_VCCDIV2);
    adc_write_configuration(&ADCA, &adc_conf);

    /* Disable over-sampling */
    adcch_read_configuration(&ADCA, ADC_CH0, &adcch_conf);
    adcch_disable_oversampling(&adcch_conf);
    adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf);

    adc_enable(&ADCA);
    printf("\n\r* ADC over-sampling disabled\n\r");
}
/**
 * \brief Enables over-sampling
 */
static void main_adc_oversampling_start(void)
{
    /* ADC module configuration structure */
    struct adc_config adc_conf;
    /* ADC channel configuration structure */
    struct adc_channel_config adcch_conf;

    adc_disable(&ADCA);

    /* Change resolution parameter to accept over-sampling */
    adc_read_configuration(&ADCA, &adc_conf);
    adc_set_conversion_parameters(&adc_conf, ADC_SIGN_OFF, ADC_RES_MT12,
                                  ADC_REF_VCCDIV2);
    adc_write_configuration(&ADCA, &adc_conf);

    /* Enable over-sampling */
    adcch_read_configuration(&ADCA, ADC_CH0, &adcch_conf);
    adcch_enable_oversampling(&adcch_conf, ADC_SAMPNUM_1024X, 16);
    adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf);

    adc_enable(&ADCA);
    printf("\n\r* ADC over-sampling enabled\n\r");
}
Пример #22
0
/**
 * \brief Enables averaging
 */
static void main_adc_averaging(void)
{
	/* ADC module configuration structure */
	struct adc_config adc_conf;
	/* ADC channel configuration structure */
	struct adc_channel_config adcch_conf;

	adc_disable(&ADCA);

	/* Change resolution parameter to accept averaging */
	adc_read_configuration(&ADCA, &adc_conf);
	adc_set_conversion_parameters(&adc_conf, ADC_SIGN_ON, ADC_RES_MT12,
			ADC_REF_VCC);
	adc_write_configuration(&ADCA, &adc_conf);

	/* Enable averaging */
	adcch_read_configuration(&ADCA, ADC_CH0, &adcch_conf);
	adcch_enable_averaging(&adcch_conf, ADC_SAMPNUM_1024X);
	adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf);

	adc_enable(&ADCA);
	adc_wait_for_interrupt_flag(&ADCA, ADC_CH0);
}
Пример #23
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;
	}
}
Пример #24
0
void app_sampling_init(void)
{
	/* QDec configuration */
	qdec_get_config_defaults(&qdec_config);
	qdec_config_phase_pins(&qdec_config, &PORTA, 6, false, 500);
	qdec_config_enable_rotary(&qdec_config);
	qdec_config_tc(&qdec_config, &TCC5);
	qdec_config_revolution(&qdec_config, 40);
	qdec_enabled(&qdec_config);

	/* ! ADC module configuration */
	struct adc_config adc_conf;

	/* Configure the ADC module:
	 * - signed, 12-bit results
	 * - VCC reference
	 * - 200 kHz maximum clock rate
	 * - manual conversion triggering
	 * - callback function
	 */
	adc_read_configuration(&LIGHT_SENSOR_ADC_MODULE, &adc_conf);
	adc_set_conversion_parameters(&adc_conf, ADC_SIGN_ON, ADC_RES_12,
			ADC_REF_VCC);
	adc_set_clock_rate(&adc_conf, 200000);
	adc_set_conversion_trigger(&adc_conf, ADC_TRIG_MANUAL, 1, 0);
	adc_write_configuration(&LIGHT_SENSOR_ADC_MODULE, &adc_conf);
	adc_set_callback(&LIGHT_SENSOR_ADC_MODULE, &app_sampling_handler);
	adc_enable(&LIGHT_SENSOR_ADC_MODULE);

	/* Configure ADC A channel 0 for light and NTC sensors.
	 * - differantial measurement (V- linked on internal GND)
	 * - gain x0.5
	 * - interrupt flag set on completed conversion
	 * - interrupts enabled
	 */
	adcch_read_configuration(&LIGHT_SENSOR_ADC_MODULE, ADC_CH0,
			&adcch_conf);
	adcch_set_input(&adcch_conf, LIGHT_SENSOR_ADC_INPUT,
			ADCCH_NEG_INTERNAL_GND, 0);
	adcch_set_interrupt_mode(&adcch_conf, ADCCH_MODE_COMPLETE);
	adcch_enable_interrupt(&adcch_conf);
	adcch_write_configuration(&LIGHT_SENSOR_ADC_MODULE, ADC_CH0,
			&adcch_conf);

	fifo_init(&app_sampling_fifo_desc, app_sampling_fifo_buffer,
			APP_SAMPLING_FIFO_SIZE);
	rtc_set_callback(&app_sampling_start);

	/* Display background */
	gfx_mono_draw_line(DISPLAY_SAMPLING_TEXT_POS_X - 3,
			0,
			DISPLAY_SAMPLING_TEXT_POS_X - 3,
			32,
			GFX_PIXEL_SET);
	app_sampling_display_rate();
	gfx_mono_draw_string(DISPLAY_LIGHT_TEXT,
			DISPLAY_LIGHT_TEXT_POS_X,
			DISPLAY_LIGHT_TEXT_POS_Y,
			&sysfont);
	gfx_mono_draw_filled_rect(
			DISPLAY_LIGHT_PROBAR_START_POS_X,
			DISPLAY_LIGHT_PROBAR_START_POS_Y,
			DISPLAY_LIGHT_PROBAR_START_SIZE_X,
			DISPLAY_LIGHT_PROBAR_START_SIZE_Y,
			GFX_PIXEL_SET);
	gfx_mono_draw_filled_rect(
			DISPLAY_LIGHT_PROBAR_STOP_POS_X,
			DISPLAY_LIGHT_PROBAR_STOP_POS_Y,
			DISPLAY_LIGHT_PROBAR_STOP_SIZE_X,
			DISPLAY_LIGHT_PROBAR_STOP_SIZE_Y,
			GFX_PIXEL_SET);

	/* Start a RTC alarm immediatly */
	rtc_set_alarm_relative(0);
}
Пример #25
0
/**
 * \brief This function processes sampled ADC values and calculate
 *        the oversampling result
 *  - Offset error compensation is applied on accumulated ADC value
 *  - After, scaling is done with scaled factor.
 *  - Finally, Analog value at ADC input pin is calculated
 *  - Reset all variable used in ADC ISR and enable ADC interrupt to start
 *    next oversampling Process.
 */
void adc_oversampled(void)
{
	/* ***********Processing and display of oversampled
	 * Input*************
	 **/

	/* Assign sign as +ve (as zero) in default for Rrw ADC count display */
	uint8_t sign_flag = 0;

	/* Offset error Compensation for entire number of samples */
	adc_result_accum_processed = adc_result_accumulator - adc_offset;

	/* Gain error Compensation for entire number of samples */
	adc_result_accum_processed = (adc_result_accum_processed *
			ADC_GAIN_ERROR_FACTOR) >> 16;

	/* Scale the accumulated result to get over sampled Result */
	adc_result_accum_processed = adc_result_accum_processed >>
			ADC_OVER_SAMP_SCALING_FACTOR;

	/* Calculate the analog input voltage value
	 * - Input Analog value = (ADC_Count * Reference
	 * Volt)/(2^adcresolution))
	 */
	v_input = (adc_result_accum_processed) *
			(ADC_OVER_SAMP_REF_VOLT_IN_MICRO);

	v_input = v_input / ADC_OVER_SAMP_MAX_COUNT;

	/* If input is negative, assign sign for display and use absolute value
	 */
	if (v_input < 0) {
		v_input = abs(v_input);
		v_input_ascii_buf[0] = '-';
	} else {
		v_input_ascii_buf[0] = '+';
	}

	/* Convert calculated analog value to ASCII for display */
	convert_to_ascii(&v_input_ascii_buf[ASCII_BUFFER_SIZE - 1], v_input);

	/* Display the result on LCD display */
	gfx_mono_draw_string(v_input_ascii_buf, 0, 10, &sysfont);

	/* If ADC count is negative, assign sign for display and use absolute
	 * value */
	if (adc_result_accum_processed < 0) {
		adc_result_accum_processed = abs(adc_result_accum_processed);
		sign_flag = 1;
	} else {
		sign_flag = 0;
	}

	/* Display oversampled raw ADC count on LCD display */
	display_adccount((int64_t)adc_result_accum_processed, (uint8_t)42,
			sign_flag );

	/* ***********Processing and display of Single Sampled
	 * Input*************
	 **/

	/* Offset error compensation for one sample */
	adc_result_one_sample_processed = adc_result_one_sample -
			adc_offset_one_sample;

	/* Gain error compensation for one sample */
	adc_result_one_sample_processed = (adc_result_one_sample_processed *
			ADC_GAIN_ERROR_FACTOR) >> 16;

	/* Calculate the analog input voltage value without oversampling
	 * - Input analog value = (ADC_Count * Reference
	 * Volt)/(2^adcresolution))
	 */
	v_input_one_sample = (adc_result_one_sample_processed) *
			(ADC_OVER_SAMP_REF_VOLT_IN_MICRO);

	v_input_one_sample = v_input_one_sample / ADC_NO_OVER_SAMP_MAX_COUNT;

	/* If input is negative, assign sign for display and use absolute value
	 */
	if (v_input_one_sample < 0) {
		v_input_one_sample = abs(v_input_one_sample);
		v_input_ascii_buf[0] = '-';
	} else {
		v_input_ascii_buf[0] = '+';
	}

	/* Convert calculated analog value to ASCII for display(no oversampling)
	 */
	convert_to_ascii(&v_input_ascii_buf[ASCII_BUFFER_SIZE - 1],
			v_input_one_sample);

	/* Display the result on LCD display(no oversampling) */
	gfx_mono_draw_string(v_input_ascii_buf, 75, 10, &sysfont);

	/* If ADC count is negative, assign sign for display and use absolute
	 * value */
	if (adc_result_one_sample_processed < 0) {
		adc_result_one_sample_processed = abs(
				adc_result_one_sample_processed);
		sign_flag = 1;
	} else {
		sign_flag = 0;
	}

	/* Display oversampled raw ADC count on LCD display */
	display_adccount((int64_t)adc_result_one_sample_processed,
			(uint8_t)117, sign_flag );

	/*Reset ADC_result accumulator value and ADC_sample count to zero
	 * for next oversampling process
	 */
	adc_result_accumulator = 0;
	adc_result_accum_processed = 0;
	adc_samplecount = 0;

	adc_result_one_sample = 0;
	adc_result_one_sample_processed = 0;

	/* Configure conversion complete interrupt for  ADCB-CH0 to re-start
	 * over sampling
	 */
	adcch_set_interrupt_mode(&adc_ch_conf, ADCCH_MODE_COMPLETE);
	adcch_enable_interrupt(&adc_ch_conf);
	adcch_write_configuration(&ADCB, ADC_CH0, &adc_ch_conf);
}
/**
 * \brief Measures and enables offset and gain corrections
 */
static void main_adc_correction_start(void)
{
	/* ADC channel configuration structure */
	struct adc_channel_config adcch_conf;
	static bool correction_measures_done = false;
	static uint16_t offset_correction;

	/* Expected value for gain correction at 1.9V
	 * expected_value = Max. range (12 bits unsigned) * 1.9V / (VCC / 1.6)
	 */
	const uint16_t expected_value
		= ((1 << 12) * 1900UL) / (3300L * 1000L / 1600L);
	/* Captured value for gain correction */
	static uint16_t captured_value;

	if (correction_measures_done) {
		goto main_adc_correction_enable;
	}

	printf("\n\r*Measure offset correction\n\r");
	printf("Set PA0 pin to GND and press a key to trigge measurement.\n\r");
	printf("Warning on STK600: Remove AREF0 jumper to do it.\n\r");
	getchar();

	/* Capture value for 0 Volt */
	adc_start_conversion(&ADCA, ADC_CH0);
	adc_wait_for_interrupt_flag(&ADCA, ADC_CH0);
	offset_correction = adc_get_unsigned_result(&ADCA, ADC_CH0);

	/* Enable offset correction */
	adcch_read_configuration(&ADCA, ADC_CH0, &adcch_conf);
	adcch_enable_correction(&adcch_conf, offset_correction, 1, 1);
	adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf);

	printf("*Measure Gain correction\n\r");
	printf("Set PA0 pin to 1.9 Volt");
	printf(" and press a key to trigge measurement.\r\n");

	printf("Reminder on STK600: Set AREF0 jumper to do it.\n\r");
	getchar();

	/* Capture value for 1.9 Volts */
	adc_start_conversion(&ADCA, ADC_CH0);
	adc_wait_for_interrupt_flag(&ADCA, ADC_CH0);
	captured_value = adc_get_unsigned_result(&ADCA, ADC_CH0);

	correction_measures_done = true;

main_adc_correction_enable:
	/* Enable offset & gain correction */
	adcch_read_configuration(&ADCA, ADC_CH0, &adcch_conf);
	adcch_enable_correction(&adcch_conf, offset_correction, expected_value,
			captured_value);
	adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf);

	printf("\n\r* ADC correction enabled:  ");
	printf("Offset correction %d,   ", offset_correction);
	if (expected_value > captured_value) {
		printf("Gain correction 1.%03u\n\r", (uint16_t)
				((((uint32_t)expected_value - captured_value)
				* 1000) / captured_value));
	} else {
		printf("Gain correction 0.%03u\n\r", (uint16_t)
				(((uint32_t)expected_value
				* 1000) / captured_value));
	}
}
Пример #27
0
/**
 * \brief Show menu for error insertion and handle user's selection.
 *
 * This function changes device configurations and does some hacks to make
 * the device behave incorrectly.
 *
 * The menu entries are
 *   - Change clock frequency: Changes the peripheral clock divider, simulating
 *     that the clock system has malfunctioned. This should be detected by the
 *     Class B frequency consistency test.
 *
 *   - Mess with test timer: Changes how often periodic tests are performed,
 *     simulating an error with an interrupt timer. This should be detected by
 *     the Class B interrupt monitor.
 *
 *   - Change a Flash section: Changes the string for the menu title stored in
 *     program memory to "Out of cheese", simulating Flash memory corruption.
 *     This can be changed back by selecting the menu item again. This should be
 *     detected by the Class B Flash CRC test.
 *
 *   - Scramble SRAM section: Starts a continuous DMA transfer in the background
 *     to a memory location, simulating transient SRAM corruption. This should
 *     be detected by the periodic and power-on Class B SRAM test.
 *
 *   - Enter infinite loop: Simulates a runaway program counter by looping
 *     forever. This should be detected by the watchdog timer system which is
 *     tested on device power-up.
 *
 *   - Change ADC reference: Enables a callback function for the ADC, which will
 *     change the voltage reference after the next completed conversion. This
 *     will cause the analog IO test to fail when user turns up the power to the
 *     plate.
 */
void oven_classb_error_insertion(void)
{
	uint8_t menu_status;
	struct keyboard_event input;
	struct adc_channel_config adcch_conf;

	/* Initialize menu system */
	gfx_mono_menu_init(&error_menu);

	/* Wait for user to select something in the menu system */
	do {
		do {
			keyboard_get_key_state(&input);
			oven_wdt_periodic_reset();
			/* Wait for key release */
		} while (input.type != KEYBOARD_RELEASE);

		/* Send key to menu system */
		menu_status = gfx_mono_menu_process_key(&error_menu,
				input.keycode);

		oven_wdt_periodic_reset();
	} while (menu_status == GFX_MONO_MENU_EVENT_IDLE);

	/* Handle the user's selection */
	switch (menu_status) {
	case 0:
		/* Change cpu frequency by modifying the prescalers */
		sysclk_set_prescalers(CLK_PSADIV_4_gc, CLK_PSBCDIV_1_1_gc);
		break;

	case 1:
		/* Change timing of the periodic temperature tests */
		OVEN_PERIODIC_TEMPTEST_TC.CTRLA = TC_CLKSEL_DIV256_gc;
		break;

	case 2:
		/* Change flash section. */
		oven_classb_flash_corrupter();
		break;

	case 3:
		/* Disrupt SRAM by setting up the DMA to write to a location on
		 * the heap, triggered by the class B frequency monitor timer
		 */
		PR.PRGEN &= ~PR_DMA_bm;
		DMA.CTRL |= DMA_ENABLE_bm;
		DMA.CH0.TRIGSRC = DMA_CH_TRIGSRC_TCD1_CCA_gc;
		/* Address of Timer D1 CNT base is 0x0960. */
		DMA.CH0.SRCADDR0 = 0x60;
		DMA.CH0.SRCADDR1 = 0x09;
		DMA.CH0.SRCADDR2 = 0x00;

		DMA.CH0.DESTADDR0 = ((uint16_t)&variable_for_sram_error) & 0xFF;
		DMA.CH0.DESTADDR1 = (((uint16_t)&variable_for_sram_error) >> 8)
				& 0xFF;
		DMA.CH0.DESTADDR2 = 0x00;

		DMA.CH0.CTRLA = DMA_CH_BURSTLEN_2BYTE_gc | DMA_CH_REPEAT_bm
				| DMA_CH_ENABLE_bm;
		break;

	case 4:
		/* Enter infinite loop */
		while (1) {
		}
		break;

	case 5:
		/* Set up ADC channel interrupt */
		adc_set_callback(&ADCA, adc_foul_callback);
		adcch_read_configuration(&ADCA, ADC_CH0, &adcch_conf);
		adcch_enable_interrupt(&adcch_conf);
		adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf);

		adcch_read_configuration(&ADCA, ADC_CH2, &adcch_conf);
		adcch_enable_interrupt(&adcch_conf);
		adcch_write_configuration(&ADCA, ADC_CH2, &adcch_conf);
		break;

	case 6:
		/* Back */
		break;

	case GFX_MONO_MENU_EVENT_EXIT:
		/* Fall through to default */
	default:
		/* Nothing, go back. */
		break;
	}
}
Пример #28
0
/**
 * \internal
 * \brief Test correction conversion in 12-bit mode using the DAC
 *
 * These values are then measured using the ADC on the pins that are connected
 * to the DAC channel, and the results are compared and checked to see if they
 * are within the acceptable range of values that passes the test.
 *
 * \param test Current test case.
 */
static void run_correction_conversion_test(
		const struct test_case *test)
{
	int16_t volt_output;
	int16_t volt_input;
	uint16_t error;

	/** Measures and enables offset and gain corrections */

	/* ADC channel configuration structure */
	struct adc_channel_config adcch_conf;
	uint16_t offset_correction;

	/* Expected value for gain correction at 1.9V
	 * expected_value = Max. range * 1.9V / (VCC / 1.6)
	 * Max. range = 12 bits signed = 11 bits unsigned
	 */
	const uint16_t expected_value
		= ((1 << 11) * 1900UL) / (3300L * 1000L / 1600L);
	/* Captured value for gain correction */
	uint16_t captured_value;

	/* DAC Output 0 Volt */
	main_dac_output(0);

	/* Capture value for 0 Volt */
	adc_wait_for_interrupt_flag(&ADCA, ADC_CH0);
	adc_wait_for_interrupt_flag(&ADCA, ADC_CH0);
	offset_correction = adc_get_unsigned_result(&ADCA, ADC_CH0);

	/* Enable offset correction */
	adcch_read_configuration(&ADCA, ADC_CH0, &adcch_conf);
	adcch_enable_correction(&adcch_conf, offset_correction, 1, 1);
	adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf);

	/* DAC Output 1.9 Volts */
	main_dac_output(1900);

	/* Capture value for 1.9 Volts */
	adc_wait_for_interrupt_flag(&ADCA, ADC_CH0);
	adc_wait_for_interrupt_flag(&ADCA, ADC_CH0);
	captured_value = adc_get_unsigned_result(&ADCA, ADC_CH0);

	/* Enable offset & gain correction */
	adcch_enable_correction(&adcch_conf, offset_correction, expected_value,
			captured_value);
	adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf);

	/* Check values */
	for (volt_output = -CONV_MAX_VOLTAGE;
			volt_output <= CONV_MAX_VOLTAGE;
			volt_output += CONV_VOLTAGE_STEP) {
		main_dac_output(volt_output);
		volt_input = main_adc_input();
		if (volt_output > volt_input) {
			error = volt_output - volt_input;
		} else {
			error = volt_input - volt_output;
		}

		test_assert_true(test,
				error < CONF_TEST_ACCEPT_DELTA_CORRECTION,
				"ADC result is outside acceptable range (expected %d, captured %d)",
				volt_output, volt_input);
	}
}
void ADCA_init(void)
{
    struct adc_config adca_conf;
    struct adc_channel_config adca_ch_conf;
    //
    //// Initialize configuration structures.
    //adc_read_configuration(&ADCB, &adcb_conf);
    //
    ///* Configure the ADC module:
    //* - unsigned, 12-bit results
    //* - AREFA voltage reference
    //* - 8000 kHz clock rate
    //* - FreeRun Mode
    //*/
    adc_get_calibration_data(ADC_CAL_ADCA);
    adc_set_conversion_parameters(&adca_conf,ADC_SIGN_OFF,ADC_RES_12,ADC_REF_AREFA);
    adc_set_clock_rate(&adca_conf,125000UL);
    adc_set_conversion_trigger(&adca_conf,ADC_TRIG_FREERUN_SWEEP,1,0);
   // adc_set_config_compare_value(adcb_conf,KCK_MAX_CHARGE_AMP);
    adc_write_configuration(&ADCA,&adca_conf);
    //
    ///* Configure ADC channel 0:
    //* - Input: ADCB4
    //* - interrupts disable
    //*/
    adcch_read_configuration(&ADCA,1, &adca_ch_conf);
    adcch_set_input(&adca_ch_conf,ADCCH_POS_PIN3,ADCCH_NEG_NONE,ADC_CH_GAIN_1X_gc);
    adcch_write_configuration(&ADCA,1,&adca_ch_conf);
    
    ///* Configure ADC channel 1: darim az channel 0 estefade mikonim ehtemalan!
    //* - Input: ADCB5
    //* - Set Interrupt Mode: Below the threshold
    //* - interrupts disable
    ////*/
    //adcch_read_configuration(&ADCA,1, &adca_ch_conf);
    //adcch_set_input(&adcb_ch_conf,ADCCH_POS_PIN5,ADCCH_NEG_NONE,ADC_CH_GAIN_1X_gc);
	////adcch_set_interrupt_mode(&adcb_ch_conf,ADCCH_MODE_ABOVE);
	////adcch_enable_interrupt(&adcb_ch_conf);
    //adcch_write_configuration(&ADCA,1,&adca_ch_conf);
  
	//
    ///* Configure ADC channel 2:
    //* - Input: ADCB6
    //* - interrupts disable
    //*/
    //adcch_read_configuration(&ADCB,2, &adcb_ch_conf);
    //adcch_set_input(&adcb_ch_conf,ADCCH_POS_PIN6,ADCCH_NEG_NONE,ADC_CH_GAIN_1X_gc);
    ////adcch_disable_interrupt(&adcb_ch_conf);
    //adcch_write_configuration(&ADCB,2,&adcb_ch_conf);
    ////
    ///* Configure ADC channel 3:
    //* - Input: ADCB7
    //* - interrupts disable
    //*/
    //adcch_read_configuration(&ADCB,3, &adcb_ch_conf);
    //adcch_set_input(&adcb_ch_conf,ADCCH_POS_PIN7,ADCCH_NEG_NONE,ADC_CH_GAIN_1X_gc);
    //adcch_set_interrupt_mode(&adcb_ch_conf,ADCCH_MODE_ABOVE);
    //adcch_enable_interrupt(&adcb_ch_conf);
    //adcch_write_configuration(&ADCB,3,&adcb_ch_conf);
    //
    adc_enable(&ADCA);
    adc_start_conversion(&ADCA,ADC_CH0);
    //adc_start_conversion(&ADCB,ADC_CH1);
    //adc_start_conversion(&ADCB,ADC_CH2);
    ////adc_start_conversion(&ADCB,ADC_CH3);
}
Пример #30
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);
}