示例#1
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));
	}
}
示例#2
0
/**
 * \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;
}
/**
 * \brief Captures a values on ADC
 *
 * \return value on ADC pins (mV)
 */
static int16_t main_adc_input(void)
{
	int16_t sample;

	/* Ignore two averaging conversions
	 * which can include two differents voltage
	 */
	adc_wait_for_interrupt_flag(&ADCA, ADC_CH0);
	adc_wait_for_interrupt_flag(&ADCA, ADC_CH0);

	/* Capture averaging */
	adc_wait_for_interrupt_flag(&ADCA, ADC_CH0);
	sample = adc_get_signed_result(&ADCA, ADC_CH0);

	/* Conversion sample to mV :
	 * mV = sample * (VCC / 1.6) / Max. range
	 */
	return ((int32_t)sample * (3300L * 1000L / 1600L)) / (1 << 11);
}
/**
 * \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 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);
}
示例#6
0
/**
 * \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;
}
示例#7
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;
	}
}
示例#8
0
int main(void)
{
	const usart_serial_options_t usart_serial_options = {
		.baudrate   = CONF_TEST_BAUDRATE,
		.charlength = CONF_TEST_CHARLENGTH,
		.paritytype = CONF_TEST_PARITY,
		.stopbits   = CONF_TEST_STOPBITS,
	};

	/* Usual initializations */
	board_init();
	sysclk_init();
	sleepmgr_init();
	irq_initialize_vectors();
	cpu_irq_enable();
	stdio_serial_init(CONF_TEST_USART, &usart_serial_options);

	printf("\x0C\n\r-- ADC Averaging Example --\n\r");
	printf("-- Compiled: %s %s --\n\r\n\r", __DATE__, __TIME__);

	printf("Commands:\n\r");
	printf("- key 'a' to enable averaging\n\r");
	printf("- key 'd' to disable averaging\n\r");

	/* ADC initialization */
	main_adc_init();
	main_adc_averaging_stop();

	while (1) {
		if (usart_rx_is_complete(CONF_TEST_USART)) {
			char key = getchar();
			if (key == 'a') {
				main_adc_averaging_start();
			}

			if (key == 'd') {
				main_adc_averaging_stop();
			}
		}

		/* Wait sample with or without average */
		uint16_t sample;
		adc_wait_for_interrupt_flag(&ADCA, ADC_CH0);
		sample = adc_get_unsigned_result(&ADCA, ADC_CH0);
		printf("ADC Value: %4u\r", sample);
	}
}
示例#9
0
文件: xmeganew.c 项目: OpenGelo/iarc
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);



			}
		}
	}
}
示例#10
0
/**
 * \brief This function get the offset of the ADCB when it is configured
 *	      in signed mode
 *  \note The ADC must be configured and enabled before this function is run.
 * \return Offset on the ADCB
 */
static int8_t adc_offset_get_signed(void)
{
	int16_t offset = 0;
	uint8_t i;

	/* Sum four samples */
	for (i = 0; i < 4; i++) {
		/* Do one conversion to find offset */
		adc_start_conversion(&ADCB, ADC_CH0);
		adc_wait_for_interrupt_flag(&ADCB, ADC_CH0);

		/* Accumulate conversion results */
		offset += adc_get_result(&ADCB, ADC_CH0);
	}

	/* Return mean value */
	return ((int8_t)(offset / 4));
}
示例#11
0
/**
 * \brief Get mean sample value
 *
 * Performs 2 to the power of \ref OVERSAMPLING_FACTOR successive conversions,
 * and computes the mean value of the resulting sample values.
 *
 * \return Mean sample value.
 */
static uint16_t get_mean_sample_value(void)
{
	uint32_t sum = 0;
	uint16_t i;

	// Sum the configured number of samples.
	for (i = 0; i < (1 << OVERSAMPLING_FACTOR); i++) {
		adc_start_conversion(&ADCA, ADC_CH0);
		adc_wait_for_interrupt_flag(&ADCA, ADC_CH0);

		sum += adc_get_result(&ADCA, ADC_CH0);
	}

	// Compute sample mean by scaling down according to oversampling factor.
	sum >>= OVERSAMPLING_FACTOR;

	return sum;
}
示例#12
0
int read_cap_level(uint16_t avg_no) {
	int32_t adcresult = 0;

	for (uint16_t i = 0; i < avg_no; i++) {
		ADC_set_input_config (ADCCH_POS_PIN6); //connect ADC to ADC1 which is shorted to VDD.

		ioport_set_pin_dir(TOUCH_ADC_POS_PIN, IOPORT_DIR_OUTPUT);
		ioport_set_pin_level(TOUCH_ADC_POS_PIN, false); //set measurement pin to GND

		PORTA.PIN0CTRL = PORT_OPC_TOTEM_gc; //totem pole
		ioport_set_pin_dir(TOUCH_ADC_POS_PIN, IOPORT_DIR_INPUT); //input

		ADC_set_input_config (ADCCH_POS_PIN3); //connect ADC to ADC3 which is sensor previously charged to VDD.

		adc_start_conversion(&MY_ADC, CAP_ADC);
		adc_wait_for_interrupt_flag(&MY_ADC, CAP_ADC);
		adcresult += adc_get_result(&MY_ADC, CAP_ADC);
	}
	return adcresult / avg_no;

}
/**
 * \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);
}
示例#14
0
int read_cap_level_ref(uint16_t avg_no) {
	int32_t adcresult = 0;

	for (uint16_t i = 0; i < avg_no; i++) {
		ADC_set_input_config (ADCCH_POS_PIN6); //connect ADC to ADC1 which is shorted to VDD.

		ioport_set_pin_dir(TOUCH_ADC_REF_PIN, IOPORT_DIR_OUTPUT);
		ioport_set_pin_level(TOUCH_ADC_REF_PIN, false); //set measurement pin to GND
		_delay_us(10); //make sure it is discharged

		PORTA.PIN2CTRL = PORT_OPC_TOTEM_gc; //totem pole
		ioport_set_pin_dir(TOUCH_ADC_REF_PIN, IOPORT_DIR_INPUT); //input

		ADC_set_input_config (ADCCH_POS_PIN2); //connect ADC to ADC2 which is not connected to anything
		_delay_us(10);

		adc_start_conversion(&MY_ADC, CAP_ADC);
		adc_wait_for_interrupt_flag(&MY_ADC, CAP_ADC);
		adcresult += adc_get_result(&MY_ADC, CAP_ADC);
	}
	return adcresult / avg_no;

}
示例#15
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);
}
int main(void)
{
    const usart_serial_options_t usart_serial_options = {
        .baudrate   = CONF_TEST_BAUDRATE,
        .charlength = CONF_TEST_CHARLENGTH,
        .paritytype = CONF_TEST_PARITY,
        .stopbits   = CONF_TEST_STOPBITS,
    };
    char binary[16 + 1];
    uint8_t i;
    bool oversampling_is_enabled;

    /* Usual initializations */
    board_init();
    sysclk_init();
    sleepmgr_init();
    irq_initialize_vectors();
    cpu_irq_enable();
    stdio_serial_init(CONF_TEST_USART, &usart_serial_options);

    printf("\x0C\n\r-- ADC Over-sampling Example --\n\r");
    printf("-- Compiled: %s %s --\n\r\n\r", __DATE__, __TIME__);

    printf("Commands:\n\r");
    printf("- key 'o' to enable over-sampling\n\r");
    printf("- key 'd' to disable over-sampling\n\r");

    /* ADC initializations */
    main_adc_init();
    main_adc_oversampling_stop();
    oversampling_is_enabled = false;

    while (1) {
        if (usart_rx_is_complete(CONF_TEST_USART)) {
            char key = getchar();
            if (key == 'o') {
                main_adc_oversampling_start();
                oversampling_is_enabled = true;
            }

            if (key == 'd') {
                main_adc_oversampling_stop();
                oversampling_is_enabled = false;
            }
        }

        /* Wait sample with or without over-sampling */
        uint16_t sample;
        adc_wait_for_interrupt_flag(&ADCA, ADC_CH0);
        sample = adc_get_unsigned_result(&ADCA, ADC_CH0);
        if (!oversampling_is_enabled) {
            sample <<= 4;
        }

        i = 15;
        do {
            binary[i] = '0' + (sample & 1);
            sample >>= 1;
        } while (i--);
        binary[16] = 0;
        printf("ADC Value: %sb\r", binary);
    }
}
示例#17
0
void alphasense_adc_getValue( void )
{
	//ALPHASENSE_STATS * const ps = &g_internal;
	struct adc_config adc_conf;
	struct adc_channel_config adcch_conf;
	uint8_t inputgain = 1;//, elements = 20;
	//char szBUF[64];
	
	// DISABLE jtag - it locks the upper 4 pins of PORT B
	CCP       = CCP_IOREG_gc;    // Secret handshake
	MCU.MCUCR = 0b00000001;
	
	PORTB.PIN0CTRL = PORT_OPC_TOTEM_gc; // Auxiliary Electrode
	PORTB.PIN2CTRL = PORT_OPC_TOTEM_gc; // Working Electrode
	PORTB.PIN6CTRL = PORT_OPC_TOTEM_gc; // GND x offset
	
	adc_read_configuration(&ALPHASENSE_ADC, &adc_conf);
	adcch_read_configuration(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH, &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, 200000UL);
	adc_write_configuration(&ALPHASENSE_ADC, &adc_conf);
	
	
	adcch_set_input(&adcch_conf, ADCCH_POS_PIN6, ADCCH_NEG_NONE, inputgain);
	adcch_write_configuration(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH, &adcch_conf);
	adc_enable(&ALPHASENSE_ADC);
	adc_start_conversion(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH);
	adc_wait_for_interrupt_flag(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH);
	adc_start_conversion(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH);
	adc_wait_for_interrupt_flag(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH);
	const int16_t off = adc_get_result(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH);
	adc_disable(&ALPHASENSE_ADC);
	//sprintf_P(szBUF,PSTR("Offset: %u\t"),off);
	//debug_string(NORMAL,szBUF,false);
	
	
	//adcch_set_input(&adcch_conf, ADCCH_POS_BANDGAP, ADCCH_NEG_NONE, inputgain);
	//adcch_write_configuration(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH, &adcch_conf);
	//adc_enable(&ALPHASENSE_ADC);
	//adc_start_conversion(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH);
	//adc_wait_for_interrupt_flag(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH);
	//const uint16_t gain = adc_get_result(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH);
	//adc_disable(&ALPHASENSE_ADC);
	////sprintf_P(szBUF,PSTR("gain: %u\t"),gain);
	////debug_string(NORMAL,szBUF,false);
	
	
	adcch_set_input(&adcch_conf, ADCCH_POS_PIN0, ADCCH_NEG_NONE, inputgain);
	adcch_write_configuration(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH, &adcch_conf);
	adc_enable(&ALPHASENSE_ADC);
	adc_start_conversion(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH);
	adc_wait_for_interrupt_flag(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH);
	adc_start_conversion(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH);
	adc_wait_for_interrupt_flag(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH);
	const int16_t adc_w = adc_get_result(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH)-off;
	adc_disable(&ALPHASENSE_ADC);
	//sprintf_P(szBUF,PSTR("ADC_WORK: %u\t"),adc_w);
	//debug_string(NORMAL,szBUF,false);
	
	adcch_set_input(&adcch_conf, ADCCH_POS_PIN2, ADCCH_NEG_NONE, inputgain);
	adcch_write_configuration(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH, &adcch_conf);
	adc_enable(&ALPHASENSE_ADC);
	adc_start_conversion(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH);
	adc_wait_for_interrupt_flag(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH);
	adc_start_conversion(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH);
	adc_wait_for_interrupt_flag(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH);
	const int16_t adc_a = adc_get_result(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH)-off;
	adc_disable(&ALPHASENSE_ADC);
	//sprintf_P(szBUF,PSTR("ADC_AUX: %u\r\n"),adc_a);
	//debug_string(NORMAL,szBUF,false);	
	
	
	
	//adc_enable(&ALPHASENSE_ADC);
	//
	//for (int i=0;i<elements;i++)
	//{
		//adc_start_conversion(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH);
		//adc_wait_for_interrupt_flag(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH);
		//adc_start_conversion(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH);
		//adc_wait_for_interrupt_flag(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH);
		//result[i]=adc_get_result(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH);
//
	//}
	
	//adc_disable(&ALPHASENSE_ADC);
	
	PORTB.PIN0CTRL = PORT_OPC_PULLUP_gc;
	PORTB.PIN2CTRL = PORT_OPC_PULLUP_gc;
	PORTB.PIN6CTRL = PORT_OPC_PULLUP_gc;
	
	g_recordingData_Alphasense = true;
	g_partialSumWork+=(int32_t)adc_w;
	g_partialSumAux+=(int32_t)adc_a;
	g_partialCount_Alphasense++;
	g_recordingData_Alphasense = false;
	
	//sprintf_P(szBUF,PSTR("Sample: %u\tPartialSumWork: %lu\tPartialSumAux: %lu\r\n"),g_partialCount, g_partialSumWork,g_partialSumAux);
	//debug_string(NORMAL,szBUF,false);
	
	//ps->working = adc_w;
	//ps->aux = adc_a;
}
/**
 * \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));
	}
}
示例#19
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);
	}
}
示例#20
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);
}