void ADC_init(ADC_name_t adc_name, ADC_prescaler_t prescaler, ADC_refference_t refference, ADC_conv_mode_t mode, ADC_freerun_t freerun, ADC_sweep_t sweep) { ADC_t * ADCx; ///< Wskaźnik na odpowiedni ADC if(adc_name == ADC_A) ADCx = &ADCA; else ADCx = &ADCB; ADCx->PRESCALER = prescaler; //ustawienie preskalera if(refference == ADC_REF_INT1V) //ustawienie napięcia referencyjnego { ADCx->REFCTRL = ADC_REF_INT1V | ADC_CH_MUXINT_BANDGAP_gc; //ustaw napięcie referencyjnego 1V i włącz BANDGAP dla wewnętrznego źródła 1V } else ADCx->REFCTRL = refference; ADCx_refsource_mV[ADC_A] = ADCA_ref_source_val_mV; ADCx_refsource_mV[ADC_B] = ADCB_ref_source_val_mV; if(freerun == ADC_FREERUN_ENABLE) //ustawienie trybu freerun ADCx->CTRLB |= ADC_FREERUN_bm; else ADCx->CTRLB &= ~ADC_FREERUN_bm; if(mode == ADC_MODE_SIGNED) //ustawienie trybu pomiaru { ADCx->CTRLB |= ADC_CONMODE_bm; ADCx_resolution[adc_name] = 2048; //dla trybu signed rozdzielczosć wynosi 2048 ADCx_delta_mV[adc_name] = 0; } else { ADCx->CTRLB &= ~ADC_CONMODE_bm; ADCx_resolution[adc_name] = 4096; //dla trybu unsigned rozdzielczosc 4096 ADCx_delta_mV[adc_name] = ADCx_refsource_mV[adc_name]*0,05; //delta dla unsigned wynosi 5% napięcia referencyjnego (dokumentacja) } ADCx->EVCTRL = sweep; //włączenie triggera dla wybranych kanałów ADC (dla freerun) ADCA.CALL = ReadCalibrationByte(PRODSIGNATURES_ADCACAL0); //czytanie z flasha i zapisywanie do rejestru bajtów kalibracyjnych ADCA.CALH = ReadCalibrationByte(PRODSIGNATURES_ADCACAL1); ADCB.CALL = ReadCalibrationByte(PRODSIGNATURES_ADCACAL0); ADCB.CALH = ReadCalibrationByte(PRODSIGNATURES_ADCACAL1); }
/* * Switch to 32MHz clock */ void switch_to_32MHz_clock(void) { DFLLRC32M.CALA = ReadCalibrationByte(PROD_SIGNATURES_START + RCOSC32MA_offset); // Load calibration value for 32M RC Oscillator DFLLRC32M.CALB = ReadCalibrationByte(PROD_SIGNATURES_START + RCOSC32M_offset); // Load calibration value for 32M RC Oscillator OSC.CTRL |= OSC_RC32MEN_bm; // Enable 32MHz oscillator while((OSC.STATUS & OSC_RC32MRDY_bm) == 0); // Wait for stable oscillator CCP = CCP_IOREG_gc; // Inform process we change a protected register CLK.CTRL = CLK_SCLKSEL_RC32M_gc; // Switch to 32MHz OSC.CTRL &= (~OSC_RC2MEN_bm); // Disable the default 2Mhz oscillator OSC.XOSCCTRL = OSC_XOSCSEL_32KHz_gc; // Choose 32kHz external crystal OSC.CTRL |= OSC_XOSCEN_bm; // Enable external oscillator while((OSC.STATUS & OSC_XOSCRDY_bm) == 0); // Wait for stable 32kHz clock OSC.DFLLCTRL = OSC_RC32MCREF_XOSC32K_gc; // Select the 32kHz clock as calibration ref for our 32M DFLLRC32M.CTRL = DFLL_ENABLE_bm; // Enable DFLL for RC32M }
/* * Initialize the DAC */ void init_dac(void) { dacdprintf_P(PSTR("-----------------------\r\n")); dacdprintf_P(PSTR("DAC init\r\n\r\n")); DACB.CH0GAINCAL = ReadCalibrationByte(PROD_SIGNATURES_START + DACB0GAINCAL_offset); // Set correct calibration values DACB.CH0OFFSETCAL = ReadCalibrationByte(PROD_SIGNATURES_START + DACB0OFFCAL_offset); // Set correct calibration values DACB.CH1GAINCAL = ReadCalibrationByte(PROD_SIGNATURES_START + DACB1GAINCAL_offset); // Set correct calibration values DACB.CH1OFFSETCAL = ReadCalibrationByte(PROD_SIGNATURES_START + DACB1OFFCAL_offset); // Set correct calibration values disable_vbias_dac(); // Disable VBIAS output disable_opampin_dac(); // Disable OPAMPIN output DACB.CTRLA = DAC_ENABLE_bm; // Enable DAC DACB.CTRLB = DAC_CHSEL_DUAL_gc; // Enable both channels DACB.CTRLC = DAC_REFSEL_AREFB_gc; // Use external VREF (1.24V) dacdprintf_P(PSTR("DAC initialized\r\n")); }
void calibrate_ADC(void) { ADCA.CALL = ReadCalibrationByte( offsetof(NVM_PROD_SIGNATURES_t, ADCACAL0) ); ADCA.CALH = ReadCalibrationByte( offsetof(NVM_PROD_SIGNATURES_t, ADCACAL1) ); }
void adc_init(void) { // ADC Clock was disabled initially in sysclk_init() // Must re-activate the ADC clock before configuring its registers (we're using ADCA) PR.PRPA &= ~0x02; // Clear ADC bit in Power Reduction Port A Register // Calibration values are stored at production time // Load stored bytes into the calibration registers // First NVM read is junk and must be thrown away ADCA.CALL = ReadCalibrationByte( offsetof(NVM_PROD_SIGNATURES_t, ADCACAL0) ); ADCA.CALH = ReadCalibrationByte( offsetof(NVM_PROD_SIGNATURES_t, ADCACAL1) ); ADCA.CALL = ReadCalibrationByte( offsetof(NVM_PROD_SIGNATURES_t, ADCACAL0) ); ADCA.CALH = ReadCalibrationByte( offsetof(NVM_PROD_SIGNATURES_t, ADCACAL1) ); ////////////////////////////////////////////////////////////////////// //ADCA.CH0.CTRL // 7 6 5 4 3 2 1 0 // | START | - | - | GAIN[2:0] | INPUTMODE[1:0] | // 0 0 0 0 0 0 0 0 // Place ADC channel in single-ended mode // Gain set to 1 ADCA.CH0.CTRL = ADC_CH_INPUTMODE0_bm; // 0x01 ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// //ADCA.CH0.MUXCTRL // 7 6 5 4 3 2 1 0 // | - | MUXPOS[3:0] | MUXNEG[2:0] | // 0 0 0 0 0 0 0 0 // Connect potentiometer (PB1) to positive input // MUXNEG bits are ignored in single-ended mode ADCA.CH0.MUXCTRL = ADC_CH_MUXINT0_bm; // 0x08 ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// //ADCA.CTRLA // 7 6 5 4 3 2 1 0 // | - | CURRLIMIT[1:0] | CONVMODE | FREERUN | RESOLUTION[1:0] | - | // 0 0 0 0 0 0 0 0 // Apply no limit to ADC sample rate // Put ADC in signed mode // Disable Free-run mode (single conversion upon trigger) // Resolution set to 12-bit, right justified (11-bit effective in signed mode) ADCA.CTRLA = ADC_CONMODE_bm; // 0x10 ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// //ADCA.PRESCALER // 7 6 5 4 3 2 1 0 // | - | - | - | - | | PRESCALER[2:0] | // 0 0 0 0 0 0 0 0 // The ADC runs off of the CPU_per clock // In sys_clk_init() the internal 2MHz RC osc was used to source a 16 MHz PLL // The PLL is then divided using Prescalers A, B, and C setting CPU_per to 8 MHz // According to AVR1300, the ADC clock should run in the range 100 kHz ~ approx 1.4 MHz // Set ADC clock to 125kHz: CPU_per/64 => 8MHz/64 = 125kHz ADCA.PRESCALER = ADC_PRESCALER2_bm; // 0x04 ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// //ADCA.REFCTRL // 7 6 5 4 3 2 1 0 // | - | REFSEL[2:0] | - | - | BANDGAP | TEMPREF | // 0 0 0 0 0 0 0 0 // Set Vref to Vcc/1.6. This gives 3.3/1.6 = approx 2.06V // With effectively 11-bit resolution, this means each LSB // will represent approximately 1 mV. ADCA.REFCTRL = ADC_REFSEL0_bm; // 0x10 ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// //ADCA.EVCTRL // 7 6 5 4 3 2 1 0 // | - | - | - | EVSEL[1:0] | EVACT[2:0] | // 0 0 0 0 0 0 0 0 // Not implementing Event System so ensure EVCTRL is reading zeros ADCA.EVCTRL = 0x00; ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// //ADCA.INTFLAGS // 7 6 5 4 3 2 1 0 // | - | - | - | - | - | - | - | CH0IF | // 0 0 0 0 0 0 0 0 // Ensure the ADC complete flag is cleared (by writing a '1' to it) ADCA.INTFLAGS = ADC_CH0IF_bm; // 0x01 ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// //ADCA.CH0.INTCTRL // 7 6 5 4 3 2 1 0 // | - | - | - | - | INTMODE[1:0] | INTLVL[1:0] | // 0 0 0 0 0 0 0 0 // Configure interrupt on conversion complete with high priority ADCA.CH0.INTCTRL = ADC_CH_INTLVL1_bm | ADC_CH_INTLVL0_bm; // 0x03 ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// //ADCA.CTRLA // 7 6 5 4 3 2 1 0 // | - | - | - | - | - | CH0START | FLUSH | ENABLE | // 0 0 0 0 0 0 0 0 // Enable ADC, module B ADCA.CTRLA = ADC_ENABLE_bm; // 0x01 ////////////////////////////////////////////////////////////////////// }
void adcInit() { ADCA.CALL = ReadCalibrationByte( offsetof(NVM_PROD_SIGNATURES_t, ADCACAL0) ); ADCA.CALH = ReadCalibrationByte( offsetof(NVM_PROD_SIGNATURES_t, ADCACAL1) ); ADCA.CTRLB = ADC_CURRLIMIT_NO_gc | ADC_CONMODE_bm | //enable signed mode ADC_FREERUN_bm | ADC_RESOLUTION_12BIT_gc ; ADCA.REFCTRL = ADC_REFSEL_VCC_gc; //utilize the vref of vcc/1.6 = 2.0625 V ADCA.PRESCALER = ADC_PRESCALER_DIV512_gc; //set all the adc channels to be single ended inputs ADCA.CH0.CTRL = ADC_CH_INPUTMODE_SINGLEENDED_gc; ADCA.CH1.CTRL = ADC_CH_INPUTMODE_SINGLEENDED_gc; ADCA.CH2.CTRL = ADC_CH_INPUTMODE_SINGLEENDED_gc; ADCA.CH3.CTRL = ADC_CH_INPUTMODE_SINGLEENDED_gc; //analog channels 0-3 will correlate to the analog pins 0-3 on port A ADCA.CH0.MUXCTRL = ADC_CH_MUXPOS_PIN0_gc; ADCA.CH1.MUXCTRL = ADC_CH_MUXPOS_PIN1_gc; ADCA.CH2.MUXCTRL = ADC_CH_MUXPOS_PIN2_gc; ADCA.CH3.MUXCTRL = ADC_CH_MUXPOS_PIN3_gc; //initialize conversion complete interrupts on all ADCA channel inputs ADCA.CH0.INTCTRL = ADC_CH_INTMODE_COMPLETE_gc | ADC_CH_INTLVL_LO_gc; ADCA.CH1.INTCTRL = ADC_CH_INTMODE_COMPLETE_gc | ADC_CH_INTLVL_LO_gc; ADCA.CH2.INTCTRL = ADC_CH_INTMODE_COMPLETE_gc | ADC_CH_INTLVL_LO_gc; ADCA.CH3.INTCTRL = ADC_CH_INTMODE_COMPLETE_gc | ADC_CH_INTLVL_LO_gc; ADCA.EVCTRL = ADC_SWEEP_0123_gc; //enable ADCA, and start conversions on all channels ADCA.CTRLA = ADC_ENABLE_bm | ADC_CH0START_bm | ADC_CH1START_bm | ADC_CH2START_bm | ADC_CH3START_bm ; ADCB.CALL = ReadCalibrationByte( offsetof(NVM_PROD_SIGNATURES_t, ADCBCAL0) ); ADCB.CALH = ReadCalibrationByte( offsetof(NVM_PROD_SIGNATURES_t, ADCBCAL1) ); ADCB.CTRLB = ADC_CURRLIMIT_NO_gc | ADC_CONMODE_bm | //enable signed mode ADC_FREERUN_bm | ADC_RESOLUTION_12BIT_gc ; ADCB.REFCTRL = ADC_REFSEL_VCC_gc; //utilize the vref of vcc/1.6 = 2.0625 V ADCB.PRESCALER = ADC_PRESCALER_DIV512_gc; //set all the adc channels to be single ended inputs ADCB.CH0.CTRL = ADC_CH_INPUTMODE_SINGLEENDED_gc; ADCB.CH1.CTRL = ADC_CH_INPUTMODE_SINGLEENDED_gc; ADCB.CH2.CTRL = ADC_CH_INPUTMODE_SINGLEENDED_gc; ADCB.CH3.CTRL = ADC_CH_INPUTMODE_SINGLEENDED_gc; //analog channels 0-3 will correlate to the analog pins 4-7 on port A ADCB.CH0.MUXCTRL = ADC_CH_MUXPOS_PIN12_gc; ADCB.CH1.MUXCTRL = ADC_CH_MUXPOS_PIN13_gc; ADCB.CH2.MUXCTRL = ADC_CH_MUXPOS_PIN14_gc; ADCB.CH3.MUXCTRL = ADC_CH_MUXPOS_PIN15_gc; //initialize conversion complete interrupts on all ADCA channel inputs ADCB.CH0.INTCTRL = ADC_CH_INTMODE_COMPLETE_gc | ADC_CH_INTLVL_LO_gc; ADCB.CH1.INTCTRL = ADC_CH_INTMODE_COMPLETE_gc | ADC_CH_INTLVL_LO_gc; ADCB.CH2.INTCTRL = ADC_CH_INTMODE_COMPLETE_gc | ADC_CH_INTLVL_LO_gc; ADCB.CH3.INTCTRL = ADC_CH_INTMODE_COMPLETE_gc | ADC_CH_INTLVL_LO_gc; ADCB.EVCTRL = ADC_SWEEP_0123_gc; //enable ADCB ADCB.CTRLA = ADC_ENABLE_bm | ADC_CH0START_bm | ADC_CH1START_bm | ADC_CH2START_bm | ADC_CH3START_bm ; PMIC.CTRL |= PMIC_LOLVLEN_bm | PMIC_RREN_bm; }