/** * \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_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); /* DAC Output 1.9 Volts */ main_dac_output(1900); /* 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); /* 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\r*** ADC 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 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; } }
void test_adc (void) { uint8_t i = 0; while (1) { /* ADC software trigger per 100ms */ if (_test_mode.trigger_mode == TRIGGER_MODE_SOFTWARE) { if (timer_timeout_reached(&timeout) && !_data.done) { adc_start_conversion(); timer_start_timeout(&timeout, 250); } } if (_test_mode.trigger_mode == TRIGGER_MODE_ADTRG) { if (pio_get_output_data_status(&pin_adtrg[0])) pio_clear(&pin_adtrg[0]); else pio_set(&pin_adtrg[0]); } /* Check if ADC sample is done */ if (_data.done & ADC_DONE_MASK) { for (i = 0; i < NUM_CHANNELS; ++i) { printf(" CH%02d: %04d ", _data.channel[i], (_data.value[i]* VREF/MAX_DIGITAL) ); } printf("\r"); _data.done = 0; } } }
int main(void) { system_init(); //! [setup_init] configure_adc(); //! [setup_init] //! [main] //! [start_conv] adc_start_conversion(&adc_instance); //! [start_conv] //! [get_res] uint16_t result; do { /* Wait for conversion to be done and read out result */ } while (adc_read(&adc_instance, &result) == STATUS_BUSY); //! [get_res] //! [inf_loop] while (1) { /* Infinite loop */ } //! [inf_loop] //! [main] }
/** * \brief Reads a 16-bit analog value on ADC channel 0 and returns it. * * In this application CH0 is set up to read the analog voltage from * a simulated thermometer. * * \return Temperature of the induction element. */ uint16_t ovenctl_get_plate_temperature(void) { adc_start_conversion(&ADCA, ADC_CH0); adc_wait_for_interrupt_flag(&ADCA, ADC_CH0); return adc_get_unsigned_result(&ADCA, ADC_CH0) / 4; }
uint16_t adp_example_adc_get_value(void) { uint16_t result; adc_start_conversion(&adc_instance); while (adc_read(&adc_instance, &result) == STATUS_BUSY); return result; }
/** * \brief Callback function for ADC interrupts * * \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) { int32_t temperature; char out_str[OUTPUT_STR_SIZE]; /* Compute current temperature in Celsius, based on linearization * of the temperature sensor adc data. */ if (result > 697) { temperature = (int8_t)((-0.0295 * result) + 40.5); } if (result > 420) { temperature = (int8_t)((-0.0474 * result) + 53.3); } else { temperature = (int8_t)((-0.0777 * result) + 65.1); } last_temperature = temperature; // Write temperature to display snprintf(out_str, OUTPUT_STR_SIZE, "Temperature: %4d C", last_temperature); gfx_mono_draw_string(out_str, 0, 0, &sysfont); // Start next conversion. adc_start_conversion(adc, ch_mask); }
//for manually reading adc channels uint16_t adc_read(uint8_t channel) { adc_start_conversion(channel); loop_until_bit_is_clear(ADCSRA, ADSC); return ADCW; }
/** * \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 Read multiple samples from ADC. * * Read \c samples samples from the ADC into the buffer \c buffer. * If there is no hardware trigger defined (event action) the * driver will retrigger the ADC conversion whenever a conversion * is complete until \c samples samples has been acquired. To avoid * jitter in the sampling frequency using an event trigger is advised. * * \param[in] module_inst Pointer to the ADC software instance struct * \param[in] samples Number of samples to acquire * \param[out] buffer Buffer to store the ADC samples * * \return Status of the job start. * \retval STATUS_OK The conversion job was started successfully and is * in progress * \retval STATUS_BUSY The ADC is already busy with another job */ enum status_code adc_read_buffer_job( struct adc_module *const module_inst, uint16_t *buffer, uint16_t samples) { Assert(module_inst); Assert(samples); Assert(buffer); if(module_inst->remaining_conversions != 0 || module_inst->job_status == STATUS_BUSY) { return STATUS_BUSY; } module_inst->job_status = STATUS_BUSY; module_inst->remaining_conversions = samples; module_inst->job_buffer = buffer; adc_enable_interrupt(module_inst, ADC_INTERRUPT_RESULT_READY); if(module_inst->software_trigger == true) { adc_start_conversion(module_inst); } return STATUS_OK; }
/** * \brief Test interrupt is getting triggered in various Sleep mode. * * This function put the device in Idle and Power Save sleep mode and check * whether the ADC conversion complete interrupt is executed only in Idle sleep * mode. * The device will wakeup from power save mode when Timer/Counter2 overflow * occur. * * \param test Current test case. */ static void run_sleep_trigger_test(const struct test_case *test) { /* Disable Global interrupt */ cpu_irq_disable(); /* Initialize the lock counts */ sleepmgr_init(); /* Initialize the ADC */ adc_initialisation(); /* Initialize the Timer/Counter2 */ timer2_initialisation(); /* Lock Idle Sleep mode */ sleepmgr_lock_mode(SLEEPMGR_IDLE); /* Clear Timer/Counter2 Register */ TCNT2 = 0; /* Wait for TCNT2 register to get updated */ while (ASSR & (1 << TCN2UB)) { } /* Start ADC Conversion */ adc_start_conversion(); /* Enable Global interrupt */ cpu_irq_enable(); /* Go to sleep in the deepest allowed mode */ sleepmgr_enter_sleep(); /* Unlock Idle Sleep mode */ sleepmgr_unlock_mode(SLEEPMGR_IDLE); /* Lock Power Save mode */ sleepmgr_lock_mode(SLEEPMGR_PSAVE); /* Clear Timer/Counter2 Register */ TCNT2 = 0; /* Wait for TCNT2 register to get updated */ while (ASSR & (1 << TCN2UB)) { } /* Start ADC Conversion */ adc_start_conversion(); /* Go to sleep in the deepest allowed mode */ sleepmgr_enter_sleep(); /* Disable ADC */ adc_disable(); /* Unlock Power Save mode */ sleepmgr_unlock_mode(SLEEPMGR_PSAVE); /* Disable Global interrupt */ cpu_irq_disable(); test_assert_true(test, trigger_count == 2, "ADC interrupt trigger failed."); }
bool microe_touch_service(LcdTouch_t* Touch) { MicroeTouch_t *MikroeTouch = Touch->UsrData; if(!Touch) return false; if(MikroeTouch->touch_conv_finish == true) return true; adc_start_conversion(MikroeTouch->Adc); while(!MikroeTouch->Adc->EndOfConversion){}; switch(MikroeTouch->xy_state) { case 0: MikroeTouch->y_data[MikroeTouch->dbidx] = MikroeTouch->Adc->ConvResult[MikroeTouch->AdcChannel_Y]; break; case 1: MikroeTouch->x_data[MikroeTouch->dbidx] = MikroeTouch->Adc->ConvResult[MikroeTouch->AdcChannel_X]; break; case 2: if(MikroeTouch->Adc->ConvResult[MikroeTouch->AdcChannel_Y] > 1000) { MikroeTouch->IsTSPress = true; } MikroeTouch->touch_conv_finish = true; MikroeTouch->dbidx = ANALOG_TOUCH_FILTER_LEVEL - 1; break; default: MikroeTouch->xy_state = 0; break; } if(MikroeTouch->dbidx == ANALOG_TOUCH_FILTER_LEVEL - 1) { MikroeTouch->xy_state++; if(MikroeTouch->xy_state >= 3) MikroeTouch->xy_state = 0; MikroeTouch->dbidx = 0; switch(MikroeTouch->xy_state) { case 0: gpio.out(MikroeTouch->DriveB, 1); gpio.out(MikroeTouch->DriveA, 0); break; case 1: gpio.out(MikroeTouch->DriveA, 1); gpio.out(MikroeTouch->DriveB, 0); break; case 2: gpio.out(MikroeTouch->DriveA, 0); gpio.out(MikroeTouch->DriveB, 0); break; default: MikroeTouch->xy_state = 0; break; } } else MikroeTouch->dbidx++; return MikroeTouch->touch_conv_finish; }
/** * \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(); 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); }
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); }
uint16_t getLightSens() { uint16_t result = 0; adc_start_conversion(&adc1); while(adc_get_status(&adc1) != ADC_STATUS_RESULT_READY); adc_read(&adc1, &result); result = result * 16; adc_clear_status(&adc1, ADC_STATUS_RESULT_READY); return result; }
static void _adc_interrupt_handler(const uint8_t instance) { struct adc_module *module = _adc_instances[instance]; /* get interrupt flags and mask out enabled callbacks */ uint32_t flags = module->hw->INTFLAG.reg; if (flags & ADC_INTFLAG_RESRDY) { if ((module->enabled_callback_mask & (1 << ADC_CALLBACK_READ_BUFFER)) && (module->registered_callback_mask & (1 << ADC_CALLBACK_READ_BUFFER))) { /* clear interrupt flag */ module->hw->INTFLAG.reg = ADC_INTFLAG_RESRDY; while (adc_is_syncing(module)) { /* Wait for synchronization */ } /* store ADC result in job buffer */ *(module->job_buffer++) = module->hw->RESULT.reg; if (--module->remaining_conversions > 0) { if (module->software_trigger == true) { adc_start_conversion(module); } } else { if (module->job_status == STATUS_BUSY) { /* job is complete. update status,disable interrupt *and call callback */ module->job_status = STATUS_OK; adc_disable_interrupt(module, ADC_INTERRUPT_RESULT_READY); (module->callback[ADC_CALLBACK_READ_BUFFER])(module); } } } } if (flags & ADC_INTFLAG_WINMON) { module->hw->INTFLAG.reg = ADC_INTFLAG_WINMON; if ((module->enabled_callback_mask & (1 << ADC_CALLBACK_WINDOW)) && (module->registered_callback_mask & (1 << ADC_CALLBACK_WINDOW))) { (module->callback[ADC_CALLBACK_WINDOW])(module); } } if (flags & ADC_INTFLAG_OVERRUN) { module->hw->INTFLAG.reg = ADC_INTFLAG_OVERRUN; if ((module->enabled_callback_mask & (1 << ADC_CALLBACK_ERROR)) && (module->registered_callback_mask & (1 << ADC_CALLBACK_ERROR))) { (module->callback[ADC_CALLBACK_ERROR])(module); } } }
/** * \internal * \brief Setup Function: ADC window mode test. * * This function initializes the ADC in window mode. * Upper and lower threshold values are provided. * It also registers & enables callback for window detection. * * \param test Current test case. */ static void setup_adc_window_mode_test(const struct test_case *test) { enum status_code status = STATUS_ERR_IO; interrupt_flag = false; /* Set 0.5V DAC output */ dac_chan_write(&dac_inst, DAC_CHANNEL_0, DAC_VAL_HALF_VOLT); delay_ms(1); /* Skip test if ADC initialization failed */ test_assert_true(test, adc_init_success, "Skipping test due to failed initialization"); /* Disable ADC before initialization */ adc_disable(&adc_inst); struct adc_config config; adc_get_config_defaults(&config); config.positive_input = ADC_POSITIVE_INPUT_PIN2; config.negative_input = ADC_NEGATIVE_INPUT_GND; #if (SAML21) config.reference = ADC_REFERENCE_INTREF; config.clock_prescaler = ADC_CLOCK_PRESCALER_DIV16; #else config.reference = ADC_REFERENCE_INT1V; #endif config.clock_source = GCLK_GENERATOR_3; #if !(SAML21) config.gain_factor = ADC_GAIN_FACTOR_1X; #endif config.resolution = ADC_RESOLUTION_12BIT; config.freerunning = true; config.window.window_mode = ADC_WINDOW_MODE_BETWEEN_INVERTED; config.window.window_lower_value = (ADC_VAL_DAC_HALF_OUTPUT - ADC_OFFSET); config.window.window_upper_value = (ADC_VAL_DAC_HALF_OUTPUT + ADC_OFFSET); /* Re-initialize & enable ADC */ status = adc_init(&adc_inst, ADC, &config); test_assert_true(test, status == STATUS_OK, "ADC initialization failed"); status = adc_enable(&adc_inst); test_assert_true(test, status == STATUS_OK, "ADC enabling failed"); /* Register and enable window mode callback */ adc_register_callback(&adc_inst, adc_user_callback, ADC_CALLBACK_WINDOW); adc_enable_callback(&adc_inst, ADC_CALLBACK_WINDOW); /* Start ADC conversion */ adc_start_conversion(&adc_inst); }
int main(void) { system_init(); delay_init(); //! [setup_init] configure_adc(); //! [setup_init] //! [main] //! [start_conv] adc_start_conversion(&adc_instance); //! [start_conv] //! [get_res] uint16_t result=0; configure_console(); //! [get_res] //! [inf_loop] while (1) { /* Infinite loop */ //adc_read(&adc_instance, &result); do { /* Wait for conversion to be done and read out result */ } while (adc_read(&adc_instance, &result) == STATUS_BUSY); printf("The result is %d\n",result); uint32_t far = 9.0/5.0*((float)result*.0002441406*6.0/.01)+32.0; printf(" The temp is %d", far); adc_clear_status(&adc_instance,adc_get_status(&adc_instance)); adc_start_conversion(&adc_instance); delay_ms(500); } //! [inf_loop] //! [main] }
void adc_start(void) { // Clear ready flag adcComplete = 0; // Reset channel adcChannel = adcChannelMin; // Enable ADC conversion complete interrupt ADCSRA |= _BV(ADIE); // Start first conversion adc_start_conversion(adcChannel); }
uint16_t adcReadX() { PORTA_DIR = 0b00110001; PORTA_OUT = 0b00010001; delay_ms(10); adc_start_conversion(&ADCA, 1); delay_ms(10); uint16_t pos = adc_get_unsigned_result(&ADCA, 1); PORTA_DIR = 0; return pos; }
/** * \brief Captures a values on ADC * * \return value on ADC pins (mV) */ static uint16_t main_adc_input(void) { uint16_t sample; adc_start_conversion(&ADCA, ADC_CH0); adc_wait_for_interrupt_flag(&ADCA, ADC_CH0); sample = adc_get_unsigned_result(&ADCA, ADC_CH0); /* Conversion sample to mV : * mV = sample * (VCC / 1.6) / Max. range */ return ((uint32_t)sample * (3300L * 1000L / 1600L)) / (1 << 12); }
/** * \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); }
/** * \brief Wrapper function for getting and ADC sample * * \param adc_ch which channel to get the ADC samples from * /returns 16-bit signed ADC result */ static int16_t adc_get_sample(uint8_t adc_ch) { int16_t result = 0; adc_start_conversion(&CALIBRATION_ADC, adc_ch); adc_wait_for_interrupt_flag(&CALIBRATION_ADC, adc_ch); result = adc_get_result(&CALIBRATION_ADC, adc_ch); adc_clear_interrupt_flag(&CALIBRATION_ADC, adc_ch); return result; }
/** * \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; } }
/** * \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) { uint32_t temperature; /* Compute current temperature in kelvin, based on the factory * calibration measurement of the temperature sensor. The calibration * has been done at 85 degrees Celsius, which corresponds to 358 kelvin. */ temperature = (uint32_t)result * 358; temperature /= tempsense; // Store temperature in global variable. last_temperature = temperature & 0xffff; // Start next conversion. adc_start_conversion(adc, (1 << channel)); }
int main(void){ char xbeebuffer[100]; int adcSample; /**Setup Xbee*/ PORTD.DIR = 0b00001000; PORTF.DIR = 3; /**Setup interrupts*/ PMIC.CTRL |= PMIC_LOLVLEX_bm | PMIC_MEDLVLEX_bm | PMIC_HILVLEX_bm | PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm; sei(); USART_InterruptDriver_Initialize(&xbee, &USARTD0, USART_DREINTLVL_LO_gc); USART_Format_Set(xbee.usart, USART_CHSIZE_8BIT_gc, USART_PMODE_DISABLED_gc, false); USART_RxdInterruptLevel_Set(xbee.usart, USART_RXCINTLVL_HI_gc); USART_Baudrate_Set(&USARTD0, 12 , 0); USART_Rx_Enable(xbee.usart); USART_Tx_Enable(xbee.usart); ADC_Ch_InputMode_and_Gain_Config(&ADC_BK.CH0, ADC_CH_INPUTMODE_DIFF_gc, ADC_DRIVER_CH_GAIN_NONE); // differential mode, no gain ADC_Ch_InputMux_Config(&ADC_BK.CH0, pin, ADC_CH_MUXNEG_PIN1_gc); ADC_Reference_Config(&ADC_BK, ADC_REFSEL_VCC_gc); // use Vcc/1.6 as ADC reference ADC_ConvMode_and_Resolution_Config(&ADC_BK, ADC_ConvMode_Signed, ADC_RESOLUTION_12BIT_gc); ADC_Prescaler_Config(&ADC_BK, ADC_PRESCALER_DIV32_gc); while(1){ if(readdata){ readdata = 0; if(input == 'r'){ adc_start_conversion(&ADCA, ADC_CH0); adc_wait_for_interrupt_flag(&ADCA, ADC_CH0); adcSample = adcch_get_signed_result(&ADCA, 0); sprintf(xbeebuffer, " %d\n\r", adcSample); sendstring(&xbee, xbeebuffer); } } } }
void ADC_TIMER_COMPA(void) { //reset the counter ADC_TIMER_RESET(); //make sure that data is not read before all channels are sampled adcReady = 0; //reset the current ADC channel adcChannel = 0; //enable the ADC Conversion Complete interrupt ADCSRA |= _BV(ADIE); //start the first conversion adc_start_conversion(adcChannel); }
bool adcCheck() { uint16_t threashold = 500; // around 200 is a sensible value PORTA_DIR = 0b11000001; PORTA_OUT = 0b11000001; // set pulldown on pin 4 PORTA.PIN4CTRL = PORT_OPC_PULLDOWN_gc; adc_start_conversion(&ADCA, 2); // measure if delay_ms(10); uint16_t value = adc_get_unsigned_result(&ADCA, 2); PORTA.PIN4CTRL = 0; if(value > threashold) return false; return true; }
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); }