void configure_adc_temp(void) { struct adc_config conf_adc; adc_get_config_defaults(&conf_adc); conf_adc.clock_source = GCLK_GENERATOR_1; conf_adc.clock_prescaler = ADC_CLOCK_PRESCALER_DIV16; conf_adc.reference = ADC_REFERENCE_INT1V; conf_adc.positive_input = ADC_POSITIVE_INPUT_TEMP; conf_adc.negative_input = ADC_NEGATIVE_INPUT_GND; conf_adc.sample_length = ADC_TEMP_SAMPLE_LENGTH; adc_init(&adc_instance, ADC, &conf_adc); ADC->AVGCTRL.reg = ADC_AVGCTRL_ADJRES(2) | ADC_AVGCTRL_SAMPLENUM_4; adc_enable(&adc_instance); }
/*=== internal functions =========================================================================*/ static void samr21_adc_init(sensor_type_t sensor) { uint8_t refsel1, refsel2; refsel1 = ADC->REFCTRL.bit.REFSEL; // generic Clock selection ID.. 0x1E = GCLK_ADC (page103 - Datasheet) GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_ADC | GCLK_CLKCTRL_GEN_GCLK3 | GCLK_CLKCTRL_CLKEN; while (GCLK->STATUS.bit.SYNCBUSY); //Power Manager - enable ADC (Page 122 - Datasheet) PM->APBCMASK.reg |= PM_APBCMASK_ADC; ADC->CTRLA.reg = ADC_CTRLA_ENABLE; WAIT_ADC_SYNC(); switch (sensor) { case TEMPERATURE: // 1 Volt Reference for Temperature Measurement ADC->REFCTRL.reg = ADC_REFCTRL_REFSEL_INT1V; // sync-asynchronicity of CLK_ADC_APB and GLK_ADC=>some registers need sync WAIT_ADC_SYNC(); // case Temperature-measurement - select Temp-sensor-Inputs ADC->INPUTCTRL.reg = ADC_INPUTCTRL_MUXNEG_GND | ADC_INPUTCTRL_MUXPOS_TEMP; WAIT_ADC_SYNC(); // Temperature Sensor Output in VREF-Register enable SYSCTRL->VREF.reg = (SYSCTRL->VREF.reg & ~0x03) | SYSCTRL_VREF_TSEN; WAIT_ADC_SYNC(); break; #if BOARD==SAMR21_XPLAINED_PRO case IO_SUPPLY: ADC->REFCTRL.reg = ADC_REFCTRL_REFSEL_INT1V; WAIT_ADC_SYNC(); ADC->INPUTCTRL.reg = ADC_INPUTCTRL_MUXNEG_GND | ADC_INPUTCTRL_MUXPOS_SCALEDIOVCC; WAIT_ADC_SYNC(); SYSCTRL->VREF.bit.BGOUTEN = 0; SYSCTRL->VREF.bit.TSEN = 0; WAIT_ADC_SYNC(); break; case ANALOG_PIN: PORT->Group[0].DIRCLR.reg = PORT_PA07; PORT->Group[0].PINCFG[7].reg |= PORT_PINCFG_PMUXEN; PORT->Group[0].PMUX[7 / 2].bit.PMUXO |= PORT_PMUX_PMUXO_B_Val; ADC->REFCTRL.reg = ADC_REFCTRL_REFSEL_INTVCC1; WAIT_ADC_SYNC(); ADC->INPUTCTRL.reg = ADC_INPUTCTRL_MUXNEG_IOGND | ADC_INPUTCTRL_MUXPOS_PIN7; WAIT_ADC_SYNC(); SYSCTRL->VREF.bit.BGOUTEN = 1; SYSCTRL->VREF.bit.TSEN = 0; break; #endif default: /* Invalid sensor value */ return; } // Pre scaler & Resolution Selection (8MHz / 8 = 1Mhz used at page 1071 for temp. meas.) ADC->CTRLB.reg = ADC_CTRLB_PRESCALER_DIV8 | ADC_CTRLB_RESSEL_12BIT; // adjusting Result + Average Control 1...1024 samples possible ADC->AVGCTRL.reg = ADC_AVGCTRL_ADJRES(4) | ADC_AVGCTRL_SAMPLENUM_32; WAIT_ADC_SYNC(); // sampling Time length Control ADC->SAMPCTRL.reg = ADC_SAMPCTRL_SAMPLEN(4); WAIT_ADC_SYNC(); // calibration values uint32_t lin0 = (*((uint32_t *)ADC_FUSES_LINEARITY_0_ADDR) & ADC_FUSES_LINEARITY_0_Msk) >> ADC_FUSES_LINEARITY_0_Pos; uint32_t lin1 = (*((uint32_t *)ADC_FUSES_LINEARITY_1_ADDR) & ADC_FUSES_LINEARITY_1_Msk) >> ADC_FUSES_LINEARITY_1_Pos; uint32_t bias = (*((uint32_t *)ADC_FUSES_BIASCAL_ADDR) & ADC_FUSES_BIASCAL_Msk) >> ADC_FUSES_BIASCAL_Pos; ADC->CALIB.bit.LINEARITY_CAL = (lin1 << 5) | lin0; ADC->CALIB.bit.BIAS_CAL = bias; refsel2 = ADC->REFCTRL.bit.REFSEL; if (refsel1 != refsel2) { /* * refer to datasheet: * 30.6.2 Basic Operation * 30.6.2.1 Initialization * Before enabling the ADC, the asynchronous clock source must be selected and enabled, and * the ADC reference must be configured. The first conversion after the reference is changed * must not be used. */ adc_get_value(); } }
/* * Arduino Zero board initialization * * Good to know: * - At reset, ResetHandler did the system clock configuration. Core is running at 48MHz. * - Watchdog is disabled by default, unless someone plays with NVM User page * - During reset, all PORT lines are configured as inputs with input buffers, output buffers and pull disabled. */ void init( void ) { uint32_t ul ; // Set Systick to 1ms interval, common to all Cortex-M variants if ( SysTick_Config( SystemCoreClock / 1000 ) ) { // Capture error while ( 1 ) ; } // Clock PORT for Digital I/O // PM->APBBMASK.reg |= PM_APBBMASK_PORT ; // // // Clock EIC for I/O interrupts // PM->APBAMASK.reg |= PM_APBAMASK_EIC ; // Clock SERCOM for Serial PM->APBCMASK.reg |= PM_APBCMASK_SERCOM0 | PM_APBCMASK_SERCOM1 | PM_APBCMASK_SERCOM2 | PM_APBCMASK_SERCOM3 | PM_APBCMASK_SERCOM4 | PM_APBCMASK_SERCOM5 ; // Clock TC/TCC for Pulse and Analog PM->APBCMASK.reg |= PM_APBCMASK_TCC0 | PM_APBCMASK_TCC1 | PM_APBCMASK_TCC2 | PM_APBCMASK_TC3 | PM_APBCMASK_TC4 | PM_APBCMASK_TC5 ; // Clock ADC/DAC for Analog PM->APBCMASK.reg |= PM_APBCMASK_ADC ;//| PM_APBCMASK_DAC ; // Setup all pins (digital and analog) in INPUT mode (default is nothing) for ( ul = 0 ; ul < NUM_DIGITAL_PINS ; ul++ ) { pinMode( ul, INPUT ) ; } // Initialize Analog Controller // Setting clock while(GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY); GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( GCM_ADC ) | // Generic Clock ADC GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source GCLK_CLKCTRL_CLKEN ; while( ADC->STATUS.bit.SYNCBUSY == 1 ); // Wait for synchronization of registers between the clock domains ADC->CTRLB.reg = ADC_CTRLB_PRESCALER_DIV512 | // Divide Clock by 512. ADC_CTRLB_RESSEL_10BIT; // 10 bits resolution as default ADC->SAMPCTRL.reg = 0x3f; // Set max Sampling Time Length while( ADC->STATUS.bit.SYNCBUSY == 1 ); // Wait for synchronization of registers between the clock domains ADC->INPUTCTRL.reg = ADC_INPUTCTRL_MUXNEG_GND; // No Negative input (Internal Ground) // Averaging (see datasheet table in AVGCTRL register description) ADC->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_1 | // 1 sample only (no oversampling nor averaging) ADC_AVGCTRL_ADJRES(0x0ul); // Adjusting result by 0 analogReference( AR_DEFAULT ) ; // Analog Reference is AREF pin (3.3v) // Initialize DAC // Setting clock // while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY ); // GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( GCM_DAC ) | // Generic Clock ADC // GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source // GCLK_CLKCTRL_CLKEN ; // while ( DAC->STATUS.bit.SYNCBUSY == 1 ); // Wait for synchronization of registers between the clock domains // DAC->CTRLB.reg = DAC_CTRLB_REFSEL_AVCC | // Using the 3.3V reference // DAC_CTRLB_EOEN ; // External Output Enable (Vout) }
/* * Arduino Zero board initialization * * Good to know: * - At reset, ResetHandler did the system clock configuration. Core is running at 48MHz. * - Watchdog is disabled by default, unless someone plays with NVM User page * - During reset, all PORT lines are configured as inputs with input buffers, output buffers and pull disabled. */ void init( void ) { #if 0 ////// 사용하지 않음 uint32_t ul ; // Set Systick to 1ms interval, common to all Cortex-M variants if ( SysTick_Config( SystemCoreClock / 1000 ) ) { // Capture error while ( 1 ) ; } // Clock PORT for Digital I/O // PM->APBBMASK.reg |= PM_APBBMASK_PORT ; // // Clock EIC for I/O interrupts // PM->APBAMASK.reg |= PM_APBAMASK_EIC ; // Clock SERCOM for Serial PM->APBCMASK.reg |= PM_APBCMASK_SERCOM0 | PM_APBCMASK_SERCOM1 | PM_APBCMASK_SERCOM2 | PM_APBCMASK_SERCOM3 | PM_APBCMASK_SERCOM4 | PM_APBCMASK_SERCOM5 ; // Clock TC/TCC for Pulse and Analog PM->APBCMASK.reg |= PM_APBCMASK_TCC0 | PM_APBCMASK_TCC1 | PM_APBCMASK_TCC2 | PM_APBCMASK_TC3 | PM_APBCMASK_TC4 | PM_APBCMASK_TC5 | PM_APBCMASK_TC6 | PM_APBCMASK_TC7 ; // Clock ADC/DAC for Analog PM->APBCMASK.reg |= PM_APBCMASK_ADC | PM_APBCMASK_DAC ; // Setup all pins (digital and analog) in INPUT mode (default is nothing) for ( ul = 0 ; ul < NUM_DIGITAL_PINS ; ul++ ) { pinMode( ul, INPUT ) ; } // Initialize Analog Controller // Setting clock GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( GCM_ADC ) | // Generic Clock ADC GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source GCLK_CLKCTRL_CLKEN ; // Setting CTRLB ADC->CTRLB.reg = ADC_CTRLB_PRESCALER_DIV128 | // Divide Clock by 128. ADC_CTRLB_RESSEL_10BIT; // Result on 10 bits ADC->INPUTCTRL.reg = ADC_INPUTCTRL_MUXNEG_GND | // No Negative input (Internal Ground) ADC_INPUTCTRL_GAIN_1X; // Gain setted to 1 // Averaging (see table 31-2 p.816 datasheet) ADC->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_2 | // 2 samples ADC_AVGCTRL_ADJRES(0x01ul); // Adjusting result by 1 ADC->SAMPCTRL.reg = 0x3f; ADC->REFCTRL.reg = ADC_REFCTRL_REFSEL_INTVCC1; // Reference intvcc1 [default] ADC->CTRLA.bit.ENABLE = 1; // Enable ADC while( ADC->STATUS.bit.SYNCBUSY == 1 ) { // Waiting for synchroinization } // Initialize DAC // Setting clock GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( GCM_DAC ) | // Generic Clock ADC GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source GCLK_CLKCTRL_CLKEN ; DAC->CTRLB.reg = DAC_CTRLB_REFSEL_AVCC | // Using the 3.3V reference DAC_CTRLB_EOEN; // External Output Enable (Vout) DAC->DATA.reg = 0x3FFul; #endif ////// 사용하지 않음 }