示例#1
0
/*  This function get the offset of the ADC
 *
 *   This function makes an internal coupling to the same pin and calculate
 *   the internal offset in the ADC.
 *
 *  \note This function only return the low byte of the 12-bit convertion,
 *        because the offset should never be more than +-8 LSB off.
 *
 *  \param adc Pointer to the ADC to calculate offset from.
 *
 *  \return Offset on the selected ADC
 */
uint8_t ADC_Offset_Get(ADC_t * adc)
{
	uint8_t offset;

  	// Set up ADC to get offset.  
  	ADC_ConvMode_and_Resolution_Config(adc, true, ADC_RESOLUTION_12BIT_gc);

	ADC_Prescaler_Config(adc , ADC_PRESCALER_DIV8_gc);

	ADC_Referance_Config(adc , ADC_REFSEL_INT1V_gc);

	ADC_Ch_InputMode_and_Gain_Config(&(adc->CH0),
	                                 ADC_CH_INPUTMODE_DIFF_gc,
	                                 ADC_CH_GAIN_1X_gc);

	ADC_Ch_InputMux_Config(&(adc->CH0), ADC_CH_MUXPOS_PIN0_gc, ADC_CH_MUXNEG_PIN0_gc);

	// Enable ADC.  
	ADC_Enable(adc);

	// Wait until ADC is ready.  
	ADC_Wait_32MHz(adc);

	// Do one conversion to find offset.  
	ADC_Ch_Conversion_Start(&(adc->CH0));

	do{
	}while(!ADC_Ch_Conversion_Complete(&(adc->CH0)));
	offset = ADC_ResultCh_GetLowByte(&(adc->CH0), 0x00);

	// Disable ADC.  
	ADC_Disable(adc);

	return offset;
}
示例#2
0
uint16_t readADC(){
    uint16_t ADC_result = 0;
    int8_t offset;
 	/* Move stored calibration values to ADC B */
	ADC_CalibrationValues_Load(&ADCA);
   
    /* Set up ADC B to have signed conversion mode and 12 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 decide 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_DIFF_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(&ADCA.CH0, ADC_CH_MUXPOS_PIN0_gc, ADC_CH_MUXNEG_PIN1_gc);
  

    // Before the ADC can be used it must be enabled 
	ADC_Enable(&ADCA);


    // Wait until the ADC is ready
    ADC_Wait_32MHz(&ADCA);

    // In the while(1) loop, a conversion is started on CH0 and the 8 MSB of the result is
    // ouput on the LEDPORT when the conversion is done   

	/* Get offset value for ADC B.  */
	offset = ADC_Offset_Get_Unsigned(&ADCA, &(ADCA.CH0), true);  
	
	for(int i = 0; i<5; i++){
	
         ADC_Ch_Conversion_Start(&ADCA.CH0);
           
         while(!ADC_Ch_Conversion_Complete(&ADCA.CH0));
                
            //ADCB.INTFLAGS = ADC_CH0IF_bm;     // Clear CH0IF by writing a one to it
         ADC_result += ADCA.CH0RES;// - offset;
    }
    
    return ADC_result/5;
}
void adc_temp_init(void)
{
	// enable 1V reference and temperature modules
	ADC_BandgapReference_Enable(&ADCB);
	ADC_TempReference_Enable(&ADCB);

	// load calibration from signature bytes
	ADC_CalibrationValues_Load(&ADCB);

	// Conversion mode and resolution (12 bit right-aligned)
	ADC_ConvMode_and_Resolution_Config(&ADCB, 
		ADC_ConvMode_Unsigned, ADC_RESOLUTION_12BIT_gc);

	// prescaler from system clock (fastest)
	ADC_Prescaler_Config(&ADCB, ADC_PRESCALER_DIV4_gc);

	// internal 1V reference
	ADC_Reference_Config(&ADCB, ADC_REFSEL_INT1V_gc);

	// channel 0 for temperature
	ADC_Ch_InputMode_and_Gain_Config(&ADCB.CH0,
	                                 ADC_CH_INPUTMODE_INTERNAL_gc,
                                     ADC_CH_GAIN_1X_gc);

	ADC_Ch_InputMux_Config(&ADCB.CH0, ADC_CH_MUXINT_TEMP_gc, ADC_CH_MUXNEG_PIN0_gc);

	// channel 1 for VCC/10
	ADC_Ch_InputMode_and_Gain_Config(&ADCB.CH1,
	                                 ADC_CH_INPUTMODE_INTERNAL_gc,
                                     ADC_CH_GAIN_1X_gc);

	ADC_Ch_InputMux_Config(&ADCB.CH1, ADC_CH_MUXINT_SCALEDVCC_gc, ADC_CH_MUXNEG_PIN0_gc);

	ADC_Enable(&ADCB);

	ADC_Wait_8MHz(&ADCB);
}
示例#4
0
void InitADC( ADC_t *ADC_Pointer )
{
    // Initialize sweep for channel 0, 1, 2 and 3
    ADC_SweepChannels_Config( ADC_Pointer, ADC_SWEEP_0123_gc );

    // Setup event to start synchronized sweep
    ADC_Events_Config( ADC_Pointer, ADC_EVSEL_0123_gc, ADC_EVACT_SYNCHSWEEP_gc );

    // Initialize the four channels to convert in single ended mode
    ADC_Ch_InputMode_and_Gain_Config( &ADC_Pointer->CH0, ADC_CH_INPUTMODE_SINGLEENDED_gc, ADC_CH_GAIN_1X_gc );
    ADC_Ch_InputMode_and_Gain_Config( &ADC_Pointer->CH1, ADC_CH_INPUTMODE_SINGLEENDED_gc, ADC_CH_GAIN_1X_gc );
    ADC_Ch_InputMode_and_Gain_Config( &ADC_Pointer->CH2, ADC_CH_INPUTMODE_SINGLEENDED_gc, ADC_CH_GAIN_1X_gc );
    ADC_Ch_InputMode_and_Gain_Config( &ADC_Pointer->CH3, ADC_CH_INPUTMODE_SINGLEENDED_gc, ADC_CH_GAIN_1X_gc );

    // Route the channels to different pins
    // Note that in Single Ended Mode, there is no negative input
    ADC_Ch_InputMux_Config( &ADC_Pointer->CH0, ADC_CH_MUXPOS_PIN1_gc, 0 );
    ADC_Ch_InputMux_Config( &ADC_Pointer->CH1, ADC_CH_MUXPOS_PIN2_gc, 0 );
    ADC_Ch_InputMux_Config( &ADC_Pointer->CH2, ADC_CH_MUXPOS_PIN3_gc, 0 );
    ADC_Ch_InputMux_Config( &ADC_Pointer->CH3, ADC_CH_MUXPOS_PIN4_gc, 0 );
           
    // Sample rate is CPUFREQ / 32. @ 2 MHz this equals 62,5ksps
	ADC_Prescaler_Config( ADC_Pointer, ADC_PRESCALER_DIV32_gc);
   
    // Set up ADCx  to have unsigned conversion mode and 8 bit resolution
  	ADC_ConvMode_and_Resolution_Config( ADC_Pointer, false, ADC_RESOLUTION_8BIT_gc );
    
    // Set reference voltage on ADCx to be VCC/1.6 V
	ADC_Reference_Config( ADC_Pointer, ADC_REFSEL_VCC_gc );
   
    // Enable the ADC
	ADC_Enable( ADC_Pointer );
     
    // Wait until common mode voltage is stable. Default clk is 2MHz and
    // therefore within the maximum frequency to use this function. 
    ADC_Wait_8MHz( ADC_Pointer );
}
示例#5
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);



			}
		}
	}
}
void adc_init(void)
{
	ADC_CalibrationValues_Load(&ADCA);
	ADC_ConvMode_and_Resolution_Config(&ADCA, 
		ADC_ConvMode_Unsigned, ADC_RESOLUTION_12BIT_gc);

	ADC_Prescaler_Config(&ADCA, ADC_PRESCALER_DIV16_gc);

	ADC_Reference_Config(&ADCA, ADC_REFSEL_VCC_gc);

	ADC_Ch_InputMode_and_Gain_Config(&ADCA.CH0,
	                                 ADC_CH_INPUTMODE_SINGLEENDED_gc,
                                     ADC_CH_GAIN_1X_gc);

	ADC_Ch_InputMux_Config(&ADCA.CH0, ADC_CH_MUXPOS_PIN7_gc, ADC_CH_MUXNEG_PIN0_gc);

	ADC_Enable(&ADCA);

	ADC_Wait_8MHz(&ADCA);
}
int main(void)
{
	// Add code to sweep CH0 and CH1 in free running mode
	// Use the function call in the adc_driver.h
	ADC_SweepChannels_Config( &ADCB, ADC_SWEEP_01_gc);


	//Enable internal temperature sensor, to be used by CH1
	ADC_TempReference_Enable(&ADCB);

	// Setup CH1 to have single ended input as in task1 and task2
	ADC_Ch_InputMode_and_Gain_Config(&ADCB.CH0,
	                                 ADC_CH_INPUTMODE_SINGLEENDED_gc,
	                                 ADC_CH_GAIN_1X_gc);

	// Set input to CH0 in ADC B to be PIN 1
	ADC_Ch_InputMux_Config(&ADCB.CH0,
	                       ADC_CH_MUXPOS_PIN1_gc,
	                       0);

	// Setup CH1 to read internal signal
	ADC_Ch_InputMode_and_Gain_Config(&ADCB.CH1,
	                                 ADC_CH_INPUTMODE_INTERNAL_gc,
	                                 ADC_CH_GAIN_1X_gc);

	// CH1 is set up to measure the internal temperature sensor
	ADC_Ch_InputMux_Config(&ADCB.CH1,
	                       ADC_CH_MUXINT_TEMP_gc,
	                       0);

	// Set up ADC B to have unsigned conversion mode and 12 bit resolution
	ADC_ConvMode_and_Resolution_Config(&ADCB, false, ADC_RESOLUTION_12BIT_gc);

	// Set reference voltage on ADC B to be VCC/1.6 V
	ADC_Reference_Config(&ADCB, ADC_REFSEL_VCC_gc);

	// Sample rate is CPUFREQ/16.
	ADC_Prescaler_Config(&ADCB, ADC_PRESCALER_DIV16_gc);

	// Enable ADC B
	ADC_Enable(&ADCB);

	// Wait until common mode voltage is stable. Default clk is 2MHz and
	// therefore within the maximum frequency to use this function.
	ADC_Wait_8MHz(&ADCB);

	// Enable ADC B free running mode
	ADC_FreeRunning_Enable(&ADCB);

	// Set the LEDPORT as output
	LEDPORT.DIR = 0xFF;

	while(1) {
		// When CH1IF is set, both conversions are done since CH0 is started first
		// Wait for CH1IF to be set
		do {
		} while ((ADCB.INTFLAGS & ADC_CH1IF_bm) != ADC_CH1IF_bm);

		// Clear CH1 Interrupt Flag
		ADCB.INTFLAGS |= ADC_CH1IF_bm;

		// Read the CH0 result register, 12 bit unsigned (0-4095)
		ADC_result_CH0 = ADCB.CH0RES;
		// Read the CH1 result register
		ADC_result_CH1 = ADCB.CH1RES;

		// Shift CH0 result to get the 4 MSB of the input signal on the 4 LSB of the LEDs
		ADC_result_CH0 >>= 8;
		// Shift CH1 result to get the 4 MSB of the temperature on the 4 MSB of the LEDs
		// Also downscale it to 4 bit. Try touching the Xmega to warm it up.
		ADC_result_CH1 = ((ADC_result_CH1 - 1) / 16);
		ADC_result_CH1 <<= 4;

		// Output on the LEDs, the 4 MSB is the internal temperature reading,
		// and the 4 LSB is the single ended input reading,
		LEDPORT.OUT = ~( (ADC_result_CH1 & 0x00F0) | (ADC_result_CH0 & 0x000F));
	}
}
示例#8
0
文件: adc.c 项目: mldelibero/anodBrd
//-----------------------------------------------------------------------------
// 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);
}