Beispiel #1
0
/**
 * Name         : adc_init
 *
 * Synopsis     : void adc_init	(void)
 *
 * Description  : Initialize the main system clock
 * 
 */
void adc_init	(void)
{
	/////////////////FROM XPLAINED 1505////////////////////////////////
	// Variable for use when we read the result from an ADC channel
	//PORTQ.PIN2CTRL = (PORTQ.PIN2CTRL & ~PORT_OPC_gm) | PORT_OPC_PULLDOWN_gc; // This pin must be grounded to "enable" NTC-resistor
	/* Move stored calibration values to ADC B */
	ADC_CalibrationValues_Load(&ADCA);
	/* Set up ADC A to have signed conversion mode and 8 bit resolution. */
	ADC_ConvMode_and_Resolution_Config(&ADCA, true, ADC_RESOLUTION_12BIT_gc);
	// The ADC has different voltage reference options, controlled by the REFSEL bits in the
	// REFCTRL register. Here the internal reference is selected
	ADC_Reference_Config(&ADCA, ADC_REFSEL_VCC_gc);
	// The clock into the ADC decides the maximum sample rate and the conversion time, and
	// this is controlled by the PRESCALER bits in the PRESCALER register. Here, the
	// Peripheral Clock is divided by 8 ( gives 250 KSPS with 2Mhz clock )
	ADC_Prescaler_Config(&ADCA, ADC_PRESCALER_DIV8_gc);
	// The used Virtual Channel (CH0) must be set in the correct mode
	// In this task we will use single ended input, so this mode is selected
	/* Setup channel 0 to have single ended input. */
	ADC_Ch_InputMode_and_Gain_Config(&ADCA.CH0,
	ADC_CH_INPUTMODE_SINGLEENDED_gc,
	ADC_CH_GAIN_1X_gc);
	ADC_Ch_InputMode_and_Gain_Config(&ADCA.CH1,
	ADC_CH_INPUTMODE_SINGLEENDED_gc,
	ADC_CH_GAIN_1X_gc);
	ADC_Ch_InputMode_and_Gain_Config(&ADCA.CH2,
	ADC_CH_INPUTMODE_SINGLEENDED_gc,
	ADC_CH_GAIN_1X_gc);
	
	// Setting up the which pins to convert.
	// Note that the negative pin is internally connected to ground
	//ADC_Ch_InputMux_Config(&ADCB.CH0, ADC_CH_MUXPOS_PIN9_gc, ADC_CH_MUXNEG_PIN1_gc);
	ADCA.CH0.MUXCTRL |= ADC_CH_MUXPOS_PIN0_gc;
	ADCA.CH1.MUXCTRL |= ADC_CH_MUXPOS_PIN1_gc;
	ADCA.CH2.MUXCTRL |= ADC_CH_MUXPOS_PIN2_gc;
	
	// Before the ADC can be used it must be enabled
	ADC_Enable(&ADCA);
	
	// Wait until the ADC is ready
	ADC_Wait_8MHz(&ADCA);
	// In the while(1) loop, a conversion is started on CH0 and the 8 MSB of the result is
	// output on the LEDPORT when the conversion is done
	/* Get offset value for ADC B. */
	adcx.offset = ADC_Offset_Get_Signed(&ADCA, &(ADCA.CH0), true);
	adcy.offset = ADC_Offset_Get_Signed(&ADCA, &(ADCA.CH1), true);
	adcz.offset = ADC_Offset_Get_Signed(&ADCA, &(ADCA.CH2), true);
		
}
Beispiel #2
0
//-----------------------------------------------------------------------------
// functions
//-----------------------------------------------------------------------------
void adc_init(void) {
/*
	Note: port_init() must be run before this function, so that the inputs are
	set correctly.
	
	We are using both ADCs. So everything will be set up for ADCA && ADCB.
*/

// Load the production calibration data into each ADC.
// This data was taken by Atmel and is stored in the micro.
// This function takes care of the whole process for you.
	ADC_CalibrationValues_Load(&ADCA);
	ADC_CalibrationValues_Load(&ADCB);
	
// Set the mode of operation for each ADC
// Signed operation mode is required for the differential configuration.
	ADC_ConvMode_and_Resolution_Config(&ADCA,signed_y,ADC_RESOLUTION_12BIT_gc);
	ADC_ConvMode_and_Resolution_Config(&ADCB,signed_y,ADC_RESOLUTION_12BIT_gc);
	
// Set ADC clocks
// 32MHz / 128 = 250KHz
// I currently have no explanation for this choice
// Atmel documentation states that you need to stay within the recommended
// ADC frequencies, but I cannot find the specific numbers.
	ADC_Prescaler_Config(&ADCA, ADC_PRESCALER_DIV128_gc);
	ADC_Prescaler_Config(&ADCB, ADC_PRESCALER_DIV128_gc);
	
// Select reference to be external reference on PIN0 for A and B
	ADC_Reference_Config(&ADCA, ADC_REFSEL_AREFA_gc);
	ADC_Reference_Config(&ADCB, ADC_REFSEL_AREFB_gc);

// Setup all channels to have differential input and 1X gain
	ADC_Ch_InputMode_and_Gain_Config(&ADCA.CH0,ADC_CH_INPUTMODE_DIFF_gc,
	                                  ADC_CH_GAIN_1X_gc); // V1
	ADC_Ch_InputMode_and_Gain_Config(&ADCA.CH1,ADC_CH_INPUTMODE_DIFF_gc,
	                                  ADC_CH_GAIN_1X_gc); // V2
	ADC_Ch_InputMode_and_Gain_Config(&ADCA.CH2,ADC_CH_INPUTMODE_DIFF_gc,
	                                  ADC_CH_GAIN_1X_gc); // reference
									  
	ADC_Ch_InputMode_and_Gain_Config(&ADCB.CH0,ADC_CH_INPUTMODE_DIFF_gc,
	                                  ADC_CH_GAIN_1X_gc); // I1
	ADC_Ch_InputMode_and_Gain_Config(&ADCB.CH1,ADC_CH_INPUTMODE_DIFF_gc,
	                                  ADC_CH_GAIN_1X_gc); // I2
	ADC_Ch_InputMode_and_Gain_Config(&ADCB.CH2,ADC_CH_INPUTMODE_DIFF_gc,
	                                  ADC_CH_GAIN_1X_gc); // reference								  									 								  

// Select the input pins for each ADC.
/*
	See AnodV2.1.sch eagle file:
	V1 - A1
	V2 - A2
	I1 - B1
	I2 - B2
	Ref - A0,A3,B0,B3
*/
	ADC_Ch_InputMux_Config(&ADCA.CH0, ADC_CH_MUXPOS_PIN1_gc, \
									  ADC_CH_MUXNEG_PIN3_gc); // V1
	ADC_Ch_InputMux_Config(&ADCA.CH1, ADC_CH_MUXPOS_PIN2_gc, \
									  ADC_CH_MUXNEG_PIN3_gc); // V2
	ADC_Ch_InputMux_Config(&ADCA.CH2, ADC_CH_MUXPOS_PIN3_gc, \
									  ADC_CH_MUXNEG_PIN3_gc); // Offset calib
			
	ADC_Ch_InputMux_Config(&ADCB.CH0, ADC_CH_MUXPOS_PIN1_gc, \
									  ADC_CH_MUXNEG_PIN3_gc); // V1
	ADC_Ch_InputMux_Config(&ADCB.CH1, ADC_CH_MUXPOS_PIN2_gc, 
									  ADC_CH_MUXNEG_PIN3_gc); // V2
	ADC_Ch_InputMux_Config(&ADCB.CH2, ADC_CH_MUXPOS_PIN3_gc,
									  ADC_CH_MUXNEG_PIN3_gc); // Offset calib

// Configure the ADCA.CH2 interrupt.
// This will trip once a reading on channel 2 has been completely resolved.
// I am assuming the chan 0 and 1 of both ADCs will have their results completed
// when chan 2 is done. This is based from the Xmega A manual (sect 25)									  
	ADC_Ch_Interrupts_Config(&ADCA.CH1, ADC_CH_INTMODE_COMPLETE_gc, \
									    ADC_CH_INTLVL_LO_gc);

//Enable ADCs
	ADC_Enable(&ADCA);
	ADC_Enable(&ADCB);								

// Wait until common mode voltage is stable so tha bypass transients are not passed.
// What is the difference between the 32 and 8 MHz versions, 
// and which one do I want?
	ADC_Wait_32MHz(&ADCA);
	ADC_Wait_32MHz(&ADCB);									  

// The TCD0 timer will periodically trigger an event that will  create an event
// on channel 0. (Xmega A manual sect 6)
	eflags.setEventSource = EVSYS_SetEventSource(0, EVSYS_CHMUX_TCD0_OVF_gc);
	TC0_ConfigClockSource(&TCD0, TC_CLKSEL_DIV8_gc);
	TCD0.PER = 200; // 1/f = 1/(32MHz/DIVx/PER) --- 200---50us---20KHz

// This is moved to the adc_test() fun. May want to enable it here later.
	// enable timer overflow int and set priority to low.
	//TCD0.INTCTRLA = TC_OVFINTLVL_LO_gc; 

// An event on eventChan 0 will trigger a sweep of chan 0,1 in ADCA && ADCB.
// I do not know what would happen if an event happened on eventChan 1,2,3.
	ADC_Events_Config(&ADCA, ADC_EVSEL_0123_gc, ADC_EVACT_SWEEP_gc);	
	ADC_Events_Config(&ADCB, ADC_EVSEL_0123_gc, ADC_EVACT_SWEEP_gc);
	ADC_SweepChannels_Config(&ADCA, ADC_SWEEP_01_gc);
	ADC_SweepChannels_Config(&ADCB, ADC_SWEEP_01_gc);
	
	
// Calibration routine for the ADCs
// Find offset with two pins shorted together.
// Steve also found the offset for the current with 0 current flowing into them,
// but did not do an equivalent for voltage. I will leave this out for now.
	offset_A = ADC_Offset_Get_Signed(&ADCA, &(ADCA.CH2), true);
	offset_B = ADC_Offset_Get_Signed(&ADCB, &(ADCB.CH2), true);
}