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); }
/** * \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); }
/** * \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)); } }
/** * \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); }
/** * \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); }
/** * \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; } }
/** * \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; } }
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; }
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); }
/** * \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); }
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); }
/** * \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); }
/** * \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); } }
/** * \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); }
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); }
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); }
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"); }
/** * \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); }
/** * \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; } }
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); }
/** * \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)); } }
/** * \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; } }
/** * \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); }
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); }