void analog_init(void) { VREF_TRM = 0x60; VREF_SC = 0xE1; // enable 1.2 volt ref // SIM_SCGC6 |= SIM_SCGC6_ADC0; #if F_BUS == 48000000 ADC0_CFG1 = ADC_CFG1_ADIV(3) + ADC_CFG1_ADLSMP + ADC_CFG1_MODE(3) + ADC_CFG1_ADICLK(1); #elif F_BUS == 24000000 ADC0_CFG1 = ADC_CFG1_ADIV(3) + ADC_CFG1_ADLSMP + ADC_CFG1_MODE(3) + ADC_CFG1_ADICLK(0); #else #error #endif //return; ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(1); ADC0_SC2 = ADC_SC2_REFSEL(0); // vcc/ext ref //ADC0_SC2 = ADC_SC2_REFSEL(1); // 1.2V ref ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(3); // avg 32 samples ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(0); // avg 4 samples ADC0_SC3 = 0; // no averaging //calibrating = 0; //return; ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(3); // begin cal calibrating = 1; }
void BSP_BatterCheckInit (void) { unsigned short cal_var; SIM->SCGC5 |= SIM_SCGC5_PORTB_MASK; SIM->SCGC6 |= SIM_SCGC6_ADC0_MASK; BAT_PORT->PCR[BAT_PORT_Pin] &= ~PORT_PCR_MUX_MASK; BAT_PORT->PCR[BAT_PORT_Pin] |= PORT_PCR_MUX(0); BAT_ADC->CFG1 &= ~(ADC_CFG1_MODE_MASK); BAT_ADC->CFG1 |= ADC_CFG1_MODE (3); // BAT_ADC->CFG1 &= ~(ADC_CFG1_ADICLK_MASK); BAT_ADC->CFG1 |= (ADC_CFG1_ADICLK (0)); // BAT_ADC->CFG1 &= ~(ADC_CFG1_ADLSMP_MASK); // BAT_ADC->CFG1 &= ~(ADC_CFG1_ADIV_MASK); BAT_ADC->CFG1 |= ADC_CFG1_ADIV (3); // BAT_ADC->CFG2 = 0; // BAT_ADC->CFG2 |= (ADACKEN_DISABLED|ADHSC_HISPEED |ADC_CFG2_ADLSTS(ADLSTS_20)); BAT_ADC->CV1 = 0x1234u; BAT_ADC->CV2 = 0x5678u; BAT_ADC->SC2 = (ACFE_DISABLED|ACFGT_GREATER |ACREN_ENABLED|DMAEN_DISABLED |ADC_SC2_REFSEL(REFSEL_EXT)); BAT_ADC->SC3 = (CAL_OFF|ADCO_SINGLE|AVGE_ENABLED |ADC_SC3_AVGS(AVGS_32)); BAT_ADC->PGA = (PGAEN_DISABLED|PGACHP_NOCHOP|PGALP_NORMAL |ADC_PGA_PGAG(PGAG_64)); BAT_ADC->SC1[0] &= ~ADC_SC1_DIFF_MASK;// BAT_ADC->SC2 &= ~ADC_SC2_ADTRG_MASK; BAT_ADC->SC3 &= ( ~ADC_SC3_ADCO_MASK & ~ADC_SC3_AVGS_MASK ); BAT_ADC->SC3 |= ( ADC_SC3_AVGE_MASK | ADC_SC3_AVGS(AVGS_32) ); BAT_ADC->SC3 |= ADC_SC3_CAL_MASK ; while((BAT_ADC->SC1[0] & ADC_SC1_COCO_MASK) == 0); if((BAT_ADC->SC3 & ADC_SC3_CALF_MASK) == CALF_FAIL){ }else{ cal_var = 0x00; cal_var = BAT_ADC->CLP0; cal_var += BAT_ADC->CLP1; cal_var += BAT_ADC->CLP2; cal_var += BAT_ADC->CLP3; cal_var += BAT_ADC->CLP4; cal_var += BAT_ADC->CLPS; cal_var = cal_var/2; cal_var |= 0x8000; // Set MSB BAT_ADC->PG = ADC_PG_PG(cal_var); // Calculate minus-side calibration cal_var = 0x00; cal_var = BAT_ADC->CLM0; cal_var += BAT_ADC->CLM1; cal_var += BAT_ADC->CLM2; cal_var += BAT_ADC->CLM3; cal_var += BAT_ADC->CLM4; cal_var += BAT_ADC->CLMS; cal_var = cal_var/2; cal_var |= 0x8000; // Set MSB BAT_ADC->MG = ADC_MG_MG(cal_var); BAT_ADC->SC3 &= ~ADC_SC3_CAL_MASK; } }
/** adc_init * \brief initialize and calibrate ADC0 module * \brief 48MHz IPBus clock; ADC clock = 48M/2/8 = 3MHz * \brief Total conversion time: 56N+4ADCK * \brief given sampling rate Fs = 6.4K, 156us/sample, 156*3= 468 ADCK * \author FSL * \param none * \return none * \warning assumes 48MHz IPBus clock */ void adc_init(void) { uint8_t cal_ok; SIM_SCGC6 |= SIM_SCGC6_ADC0_MASK; #ifdef CMSIS NVIC_EnableIRQ(ADC0_IRQn); #else enable_irq(INT_ADC0 - 16); #endif /* 48MHz IPBus clock * ADC clock = 48M/2/8 = 3MHz * Total conversion time: 56N+4ADCK * Given sampling rate Fs = 6.4K, 156us/sample, 156*3= 468 ADCK * the maximum h/w average number = 8 * use h/w average number = 4 * Total conversion time: 56*4+4 = 228 ADC clocks,76us * There are 468-228 = 240 ADC clocks (ie. 80us) free for post processing */ // Initialize ADC0 // Do calibration first with 32 h/w averages Master_Adc_Config.CONFIG1 = ADLPC_NORMAL | ADC_CFG1_ADIV(ADIV_8) | ADLSMP_LONG | ADC_CFG1_MODE(MODE_16) | ADC_CFG1_ADICLK(ADICLK_BUS_2); Master_Adc_Config.CONFIG2 = MUXSEL_ADCA | ADACKEN_ENABLED | ADHSC_HISPEED | ADC_CFG2_ADLSTS(ADLSTS_20) ; Master_Adc_Config.COMPARE1 = 0x1234u ; Master_Adc_Config.COMPARE2 = 0x5678u ; Master_Adc_Config.STATUS2 = ADTRG_SW | ACFE_DISABLED | ACFGT_GREATER | ACREN_ENABLED | DMAEN_DISABLED | ADC_SC2_REFSEL(REFSEL_EXT); Master_Adc_Config.STATUS3 = CAL_OFF | ADCO_SINGLE | AVGE_ENABLED | ADC_SC3_AVGS(AVGS_32); // Master_Adc_Config.PGA = PGAEN_DISABLED | PGACHP_NOCHOP | PGALP_NORMAL | ADC_PGA_PGAG(PGAG_64); Master_Adc_Config.STATUS1A = AIEN_OFF | DIFF_SINGLE | ADC_SC1_ADCH(31); Master_Adc_Config.STATUS1B = AIEN_OFF | DIFF_SINGLE | ADC_SC1_ADCH(31); ADC_Config_Alt(ADC0_BASE_PTR, &Master_Adc_Config); // config ADC cal_ok = ADC_Cal(ADC0_BASE_PTR); // do the calibration if (cal_ok != 0) printf("ADC calibration error"); ADC_Read_Cal(ADC0_BASE_PTR,&CalibrationStore[1]); // store the cal // Now do normal ADC configuration with 4 h/w averages and h/w trigger from PDB Master_Adc_Config.CONFIG1 = ADLPC_NORMAL | ADC_CFG1_ADIV(ADIV_8) | ADLSMP_LONG | ADC_CFG1_MODE(MODE_12) | ADC_CFG1_ADICLK(ADICLK_BUS_2); Master_Adc_Config.CONFIG2 = MUXSEL_ADCB | ADACKEN_ENABLED | ADHSC_HISPEED | ADC_CFG2_ADLSTS(ADLSTS_20) ; Master_Adc_Config.COMPARE1 = 0x1234u ; Master_Adc_Config.COMPARE2 = 0x5678u ; Master_Adc_Config.STATUS2 = !ADTRG_HW | ACFE_DISABLED | ACFGT_GREATER | ACREN_DISABLED | DMAEN_DISABLED | ADC_SC2_REFSEL(REFSEL_EXT); Master_Adc_Config.STATUS3 = CAL_OFF | ADCO_SINGLE | AVGE_ENABLED | ADC_SC3_AVGS(AVGS_4); // Master_Adc_Config.PGA = PGAEN_DISABLED | PGACHP_NOCHOP | PGALP_NORMAL | ADC_PGA_PGAG(PGAG_64); Master_Adc_Config.STATUS1A = !AIEN_ON | DIFF_SINGLE | ADC_SC1_ADCH(31); Master_Adc_Config.STATUS1B = !AIEN_ON | DIFF_SINGLE | ADC_SC1_ADCH(31); ADC_Config_Alt(ADC0_BASE_PTR, &Master_Adc_Config); // config the ADC again to default conditions }
void analogReadAveraging(unsigned int num) { if (calibrating) wait_for_cal(); if (num <= 1) { num = 0; ADC0_SC3 = 0; } else if (num <= 4) { num = 4; ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(0); #ifdef HAS_KINETIS_ADC1 ADC1_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(0); #endif } else if (num <= 8) { num = 8; ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(1); #ifdef HAS_KINETIS_ADC1 ADC1_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(1); #endif } else if (num <= 16) { num = 16; ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(2); #ifdef HAS_KINETIS_ADC1 ADC1_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(2); #endif } else { num = 32; ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(3); #ifdef HAS_KINETIS_ADC1 ADC1_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(3); #endif } analog_num_average = num; }
/* adc_cal * Calibrates the adc * Returns 0 if successful calibration * Returns 1 otherwise * */ int adc_cal(void) { ADC0_CFG1 |= (ADC_CFG1_MODE(0) | // 12 bits mode ADC_CFG1_ADICLK(1)| // Input Bus Clock divided by 2 (20-25 MHz out of reset (FEI mode) / 2) ADC_CFG1_ADIV(2)) ; // Clock divide by 4 (2.5-3 MHz) ADC0_SC3 |= ADC_SC3_AVGE_MASK | // Enable HW average ADC_SC3_AVGS(3) | // Set HW average of 32 samples ADC_SC3_CAL_MASK; // Start calibration process while(ADC0_SC3 & ADC_SC3_CAL_MASK); // Wait for calibration to end if(ADC0_SC3 & ADC_SC3_CALF_MASK) // Check for successful calibration return 1; uint16_t calib = 0; // calibration variable calib += ADC0_CLPS + ADC0_CLP4 + ADC0_CLP3 + ADC0_CLP2 + ADC0_CLP1 + ADC0_CLP0; calib /= 2; calib |= 0x8000; // Set MSB ADC0_PG = calib; calib = 0; calib += ADC0_CLMS + ADC0_CLM4 + ADC0_CLM3 + ADC0_CLM2 + ADC0_CLM1 + ADC0_CLM0; calib /= 2; calib |= 0x8000; // Set MSB ADC0_MG = calib; return 0; }
/* ** =================================================================== ** Method : ADC0_Init (component Init_ADC) ** Description : ** This method initializes registers of the ADC module ** according to the Peripheral Initialization settings. ** Call this method in user code to initialize the module. By ** default, the method is called by PE automatically; see "Call ** Init method" property of the component for more details. ** Parameters : None ** Returns : Nothing ** =================================================================== */ void ADC0_Init(void) { /* SIM_SCGC6: ADC0=1 */ SIM_SCGC6 |= SIM_SCGC6_ADC0_MASK; /* ADC0_CFG1: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,ADLPC=0,ADIV=0,ADLSMP=0,MODE=0,ADICLK=0 */ ADC0_CFG1 = ADC_CFG1_ADIV(0x00) | ADC_CFG1_MODE(0x00) | ADC_CFG1_ADICLK(0x00); /* ADC0_CFG2: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,ADACKEN=0,ADHSC=0,ADLSTS=0 */ ADC0_CFG2 &= (uint32_t)~(uint32_t)( ADC_CFG2_ADACKEN_MASK | ADC_CFG2_ADHSC_MASK | ADC_CFG2_ADLSTS(0x03) | 0xFFFFFFE0U ); /* ADC0_CV1: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CV=0 */ ADC0_CV1 = ADC_CV1_CV(0x00); /* ADC0_CV2: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CV=0 */ ADC0_CV2 = ADC_CV2_CV(0x00); /* ADC0_OFS: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,OFS=4 */ ADC0_OFS = ADC_OFS_OFS(0x04); /* ADC0_SC2: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,ADACT=0,ADTRG=0,ACFE=0,ACFGT=0,ACREN=0,DMAEN=0,REFSEL=0 */ ADC0_SC2 = ADC_SC2_REFSEL(0x00); /* ADC0_SC3: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CAL=0,CALF=0,??=0,??=0,ADCO=0,AVGE=0,AVGS=0 */ ADC0_SC3 = ADC_SC3_AVGS(0x00); /* ADC0_SC1A: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,COCO=0,AIEN=0,DIFF=0,ADCH=0x1F */ ADC0_SC1A = ADC_SC1_ADCH(0x1F); /* ADC0_SC1B: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,COCO=0,AIEN=0,DIFF=0,ADCH=0x1F */ ADC0_SC1B = ADC_SC1_ADCH(0x1F); }
/* adc_init() * Calibrates and initializes adc to perform single conversions and generate * DMA requests at the end of the conversion * * */ void adc_init(void) { // Enable clocks SIM_SCGC6 |= SIM_SCGC6_ADC0_MASK; // ADC0 clock // Calibrate ADC adc_cal(); // Configure ADC ADC0_CFG1 = 0; // Reset register ADC0_CFG1 = (ADC_CFG1_MODE(3) | // 12 bits mode see table ADC_CFG1_ADICLK(0)| // Input Bus Clock (20-25 MHz out of reset (FEI mode)) ADC_CFG1_ADIV(1)|ADC_CFG1_ADLSMP_MASK) ; // Clock divide by 2 (10-12.5 MHz) ADC0_SC1A |= ADC_SC1_AIEN_MASK; // Interrupt enable ADC0_CFG2=ADC_CFG2_ADHSC_MASK |ADC_CFG2_MUXSEL_MASK; //high speed conversion ADC0_SC3=ADC_SC3_AVGE_MASK|ADC_SC3_AVGS(3);//hardware avg- 32 sampels //ADC0_CV1=250; enable_irq(INT_ADC0-16); set_irq_priority(INT_ADC0-16,2); //ADC0_SC2 |= ADC_SC2_DMAEN_MASK; // DMA Enable //ADC0_SC2=ADC_SC2_ADTRG_MASK; //hardware triger //ADC0_SC3 = 0; // Reset SC3 //ADC0_SC1A = ADC_SC1_ADCH(x); //adx chnner see table ADC0_SC1A = ADC_SC1_ADCH(7)|ADC_SC1_AIEN_MASK; }
int adc_init(adc_t line) { /* make sure the given line is valid */ if (line >= ADC_NUMOF) { return -1; } /* prepare the device: lock and power on */ prep(line); /* configure the connected pin mux */ if (adc_config[line].pin != GPIO_UNDEF) { gpio_init_port(adc_config[line].pin, GPIO_AF_ANALOG); } /* The ADC requires at least 2 MHz module clock for full accuracy, and less * than 12 MHz */ /* For the calibration it is important that the ADC clock is <= 4 MHz */ uint32_t adiv; if (CLOCK_BUSCLOCK > (ADC_MAX_CLK << 3)) { #if KINETIS_HAVE_ADICLK_BUS_DIV_2 /* Some CPUs, e.g. MK60D10, MKW22D5, provide an additional divide by two * divider for the bus clock as CFG1[ADICLK] = 0b01 */ adiv = ADC_CFG1_ADIV(3) | ADC_CFG1_ADICLK(1); #else /* Newer CPUs seem to have replaced this with various alternate clock * sources instead */ adiv = ADC_CFG1_ADIV(3); #endif } else { unsigned int i = 0; while ((i < 3) && (CLOCK_BUSCLOCK > (ADC_MAX_CLK << i))) { ++i; } adiv = ADC_CFG1_ADIV(i); } /* set configuration register 1: clocking and precision */ /* Set long sample time */ dev(line)->CFG1 = ADC_CFG1_ADLSMP_MASK | adiv; /* select ADxxb channels, longest sample time (20 extra ADC cycles) */ dev(line)->CFG2 = ADC_CFG2_MUXSEL_MASK | ADC_CFG2_ADLSTS(0); /* select software trigger, external ref pins */ dev(line)->SC2 = ADC_SC2_REFSEL(0); /* select hardware average over 32 samples */ dev(line)->SC3 = ADC_SC3_AVGE_MASK | ADC_SC3_AVGS(3); /* set an (arbitrary) input channel, single-ended mode */ dev(line)->SC1[0] = ADC_SC1_ADCH(0); /* perform calibration routine */ int res = kinetis_adc_calibrate(dev(line)); done(line); return res; }
uint8 ADC_Cal (ADC_MemMapPtr adcmap) { /*~~~~~~~~~~~~~~~~~~~~*/ /*~~~~~~~~~~~~~~~~~~~~*/ /*~~~~~~~~~~~~~~~~~~~~*/ /*~~~~~~~~~~~~~~~~~~~~*/ /*~~~~~~~~~~~~~~~~~~~~*/ /*~~~~~~~~~~~~~~~~~~~~*/ unsigned short cal_var; /*~~~~~~~~~~~~~~~~~~~~*/ /*~~~~~~~~~~~~~~~~~~~~*/ /*~~~~~~~~~~~~~~~~~~~~*/ /*~~~~~~~~~~~~~~~~~~~~*/ /*~~~~~~~~~~~~~~~~~~~~*/ /*~~~~~~~~~~~~~~~~~~~~*/ ADC_SC2_REG(adcmap) &= ~ADC_SC2_ADTRG_MASK; // Enable Software Conversion Trigger for Calibration Process - ADC0_SC2 = ADC0_SC2 | ADC_SC2_ADTRGW(0); ADC_SC3_REG(adcmap) &= (~ADC_SC3_ADCO_MASK &~ADC_SC3_AVGS_MASK); // set single conversion, clear avgs bitfield for next writing ADC_SC3_REG(adcmap) |= (ADC_SC3_AVGE_MASK | ADC_SC3_AVGS(AVGS_32)); // Turn averaging ON and set at max value ( 32 ) ADC_SC3_REG(adcmap) |= ADC_SC3_CAL_MASK; // Start CAL while((ADC_SC1_REG(adcmap, A) & ADC_SC1_COCO_MASK) == COCO_NOT); // Wait calibration end if((ADC_SC3_REG(adcmap) & ADC_SC3_CALF_MASK) == CALF_FAIL) { return(1); // Check for Calibration fail error and return } // Calculate plus-side calibration cal_var = 0x00; cal_var = ADC_CLP0_REG(adcmap); cal_var += ADC_CLP1_REG(adcmap); cal_var += ADC_CLP2_REG(adcmap); cal_var += ADC_CLP3_REG(adcmap); cal_var += ADC_CLP4_REG(adcmap); cal_var += ADC_CLPS_REG(adcmap); cal_var = cal_var / 2; cal_var |= 0x8000; // Set MSB ADC_PG_REG(adcmap) = ADC_PG_PG(cal_var); // Calculate minus-side calibration cal_var = 0x00; cal_var = ADC_CLM0_REG(adcmap); cal_var += ADC_CLM1_REG(adcmap); cal_var += ADC_CLM2_REG(adcmap); cal_var += ADC_CLM3_REG(adcmap); cal_var += ADC_CLM4_REG(adcmap); cal_var += ADC_CLMS_REG(adcmap); cal_var = cal_var / 2; cal_var |= 0x8000; // Set MSB ADC_MG_REG(adcmap) = ADC_MG_MG(cal_var); ADC_SC3_REG(adcmap) &= ~ADC_SC3_CAL_MASK; /* Clear CAL bit */ return(0); }
void analog_init(void) { uint32_t num; VREF_TRM = 0x60; VREF_SC = 0xE1; // enable 1.2 volt ref if (analog_config_bits == 8) { ADC0_CFG1 = ADC0_CFG1_24MHZ + ADC_CFG1_MODE(0); ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3); } else if (analog_config_bits == 10) { ADC0_CFG1 = ADC0_CFG1_12MHZ + ADC_CFG1_MODE(2) + ADC_CFG1_ADLSMP; ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3); } else if (analog_config_bits == 12) { ADC0_CFG1 = ADC0_CFG1_12MHZ + ADC_CFG1_MODE(1) + ADC_CFG1_ADLSMP; ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2); } else { ADC0_CFG1 = ADC0_CFG1_12MHZ + ADC_CFG1_MODE(3) + ADC_CFG1_ADLSMP; ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2); } if (analog_reference_internal) { ADC0_SC2 = ADC_SC2_REFSEL(1); // 1.2V ref } else { ADC0_SC2 = ADC_SC2_REFSEL(0); // vcc/ext ref } num = analog_num_average; if (num <= 1) { ADC0_SC3 = ADC_SC3_CAL; // begin cal } else if (num <= 4) { ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(0); } else if (num <= 8) { ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(1); } else if (num <= 16) { ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(2); } else { ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(3); } calibrating = 1; }
void init_ADC16(void){ // Turn on the ADC0 clock as well as the PDB clocks to test ADC triggered by PDB SIM_SCGC6 |= (SIM_SCGC6_ADC0_MASK ); // SIM_SCGC6 |= SIM_SCGC6_PDB_MASK ; pdb PMC_REGSC |= PMC_REGSC_BGBE_MASK ; // setup the initial ADC default configuration Master_Adc_Config.CONFIG1 = ADLPC_LOW | ADC_CFG1_ADIV(ADIV_1) | ADLSMP_LONG | ADC_CFG1_MODE(MODE_16) | ADC_CFG1_ADICLK(ADICLK_BUS); Master_Adc_Config.CONFIG2 = MUXSEL_ADCA | ADACKEN_DISABLED | ADHSC_HISPEED | ADC_CFG2_ADLSTS(ADLSTS_20) ; Master_Adc_Config.COMPARE1 = 0x1234u ; // can be anything Master_Adc_Config.COMPARE2 = 0x5678u ; // can be anything // since not using // compare feature Master_Adc_Config.STATUS2 = ADTRG_SW | ACFE_DISABLED | ACFGT_GREATER | ACREN_DISABLED | DMAEN_DISABLED | ADC_SC2_REFSEL(REFSEL_EXT); Master_Adc_Config.STATUS3 = CAL_OFF | ADCO_SINGLE | !AVGE_ENABLED | ADC_SC3_AVGS(AVGS_4); Master_Adc_Config.STATUS1A = !AIEN_ON | DIFF_SINGLE | ADC_SC1_ADCH(31); // Configure ADC as it will be used, but becuase ADC_SC1_ADCH is 31, // the ADC will be inactive. Channel 31 is just disable function. // There really is no channel 31. ADC_Config_Alt(ADC0_BASE_PTR, &Master_Adc_Config); // config ADC // Calibrate the ADC in the configuration in which it will be used: ADC_Cal(ADC0_BASE_PTR); // do the calibration // The structure still has the desired configuration. So restore it. // Why restore it? The calibration makes some adjustments to the // configuration of the ADC. The are now undone: // config the ADC again to desired conditions ADC_Config_Alt(ADC0_BASE_PTR, &Master_Adc_Config); }
/* Set the number of averages: 0, 4, 8, 16 or 32. * */ void ADC::setAveraging(uint8_t num) { if (calibrating) wait_for_cal(); if (num <= 1) { num = 0; ADC0_SC3 &= !ADC_SC3_AVGE; } else if (num <= 4) { num = 4; ADC0_SC3 |= ADC_SC3_AVGE + ADC_SC3_AVGS(0); } else if (num <= 8) { num = 8; ADC0_SC3 |= ADC_SC3_AVGE + ADC_SC3_AVGS(1); } else if (num <= 16) { num = 16; ADC0_SC3 |= ADC_SC3_AVGE + ADC_SC3_AVGS(2); } else { num = 32; ADC0_SC3 |= ADC_SC3_AVGE + ADC_SC3_AVGS(3); } analog_num_average = num; }
//------------------------------------------------------------ // Configuration du convertisseur AD //------------------------------------------------------------ void iAd_Config(void) { // Lets calibrate the ADC. 1st setup how the channel will be used. disable_irq(INT_ADC1-16); // ADC configuration register 1 (ADCx_CFG1) // K10 Sub-Family Reference Manual, Rev. 6, Nov 2011 page 757 // ADLPC=0, Normal power configuration // ADIV=0,The divide ratio is 1 and the clock rate is (input clock)/1 // ADLSMP=0,short sample time // MODE=11,It is single-ended 16-bit conversion // ADICLK=0,Bus clock divided by 1 --> 50MHz ADC1_CFG1=0; ADC1_CFG1|=(ADC_CFG1_ADIV(0)|ADC_CFG1_MODE(3)|ADC_CFG1_ADICLK(0)); // Configuration register 2 (ADCx_CFG2) // K10 Sub-Family Reference Manual, Rev. 6, Nov 2011 page 759 // MUXSEL=0,ADxxa channels are selected // ADACKEN=0,Asynchronous clock output disabled // ADHSC=1,high speed conversion sequence selected // ADLSTS=3,2 extra ADCK cycles; 6 ADCK cycles total sample time ADC1_CFG2=0|ADC_CFG2_ADHSC_MASK|ADC_CFG2_ADLSTS(3); // --> une conversion 5us --> 128 pixels: 640us // Status and control register 2 (ADCx_SC2) // K10 Sub-Family Reference Manual, Rev. 6, Nov 2011 page 762 // ADTRG=0,Software trigger selected // ACFE=0,Compare function disabled // ACFGT=0,Configures less than threshold, outside range not inclusive and inside range not inclusive functionality // based on the values placed in the CV1 and CV2 registers // ACREN=0,Range function disabled. Only the compare value 1 register (CV1) is compared // DMAEN=0,DMA is disabled // REFSEL=0,Default voltage reference pin pair (external pins VREFH and VREFL) ADC1_SC2=0; // Status and control register 2 (ADCx_SC3) // K10 Sub-Family Reference Manual, Rev. 6, Nov 2011 page 764 // ADCO=0, One conversion or one set of conversions if the hardware average function is enabled (AVGE=1) after initiating a conversion. // AVGE=0, Hardware average function disabled // AVGS=0, 4 samples averaged ADC1_SC3=0|ADC_SC3_AVGE_MASK|ADC_SC3_AVGS(0); // ADC status and control registers 1 (ADCx_SC1n) // K10 Sub-Family Reference Manual, Rev. 6, Nov 2011 page 754 // AIEN=0,Conversion complete interrupt disabled // DIFF=0,Differential mode enable -> Single-ended conversions and input channels are selected // ADCH=0x03,Input channel select -> POT1 ADC1_SC1A=0; ADC1_SC1A=0|(ADC_SC1_ADCH(3)); }
void InitADC_12Bit() { SIM_SCGC6 |= SIM_SCGC6_ADC0_MASK; // setup the initial ADC default configuration to get setup for calibration Master_Adc_Config.CONFIG1 = ADLPC_NORMAL | ADC_CFG1_ADIV(ADIV_4) | ADLSMP_LONG | ADC_CFG1_MODE(MODE_12) | ADC_CFG1_ADICLK(ADICLK_BUS); Master_Adc_Config.CONFIG2 = MUXSEL_ADCA | ADACKEN_DISABLED | ADHSC_HISPEED | ADC_CFG2_ADLSTS(ADLSTS_20) ; Master_Adc_Config.COMPARE1 = 0x1234u ; // can be anything Master_Adc_Config.COMPARE2 = 0x5678u ; // can be anything // since not using // compare feature Master_Adc_Config.STATUS2 = ACFE_DISABLED | ACFGT_GREATER | ACREN_ENABLED | DMAEN_DISABLED | ADC_SC2_REFSEL(REFSEL_EXT); Master_Adc_Config.STATUS3 = CAL_OFF | ADCO_SINGLE | AVGE_ENABLED | ADC_SC3_AVGS(AVGS_16); Master_Adc_Config.STATUS1A = AIEN_OFF | DIFF_SINGLE | ADC_SC1_ADCH(31); Master_Adc_Config.STATUS1B = AIEN_OFF | DIFF_SINGLE | ADC_SC1_ADCH(31); // Configure ADC as it will be used, but becuase ADC_SC1_ADCH is 31, // the ADC will be inactive. Channel 31 is just disable function. // There really is no channel 31. ADC_Config_Alt(ADC0_BASE_PTR, &Master_Adc_Config); // config ADC // Calibrate the ADC in the configuration in which it will be used: ADC_Cal(ADC0_BASE_PTR); // do the calibration // The structure still has the desired configuration. So restore it. // Why restore it? The calibration makes some adjustments to the // configuration of the ADC. The are now undone: // config the ADC again to desired conditions ADC_Config_Alt(ADC0_BASE_PTR, &Master_Adc_Config); // ***************************************************************************** // ADC0 using the PDB trigger in ping pong // ***************************************************************************** // use interrupts, single ended mode, and real channel numbers now: ADC_Config_Alt(ADC0_BASE_PTR, &Master_Adc_Config); // config ADC0 }
adc::adc(channel ch_, resolution r_) { n_channel = ch_; //tact ADC0 SIM->SCGC6 |= SIM_SCGC6_ADC0_MASK; //Set busclock ADC0->CFG1 &= ~ADC_CFG1_ADICLK_MASK; //Set divider - 8 ADC0->CFG1 |= ADC_CFG1_ADIV(3); ADC0->SC3 |= ADC_SC3_AVGE_MASK|ADC_SC3_AVGS(3); ADC0->SC2 &= ~ ADC_SC2_ADTRG_MASK; ADC0->SC3 |= ADC_SC3_CAL_MASK ; while (!(ADC0->SC1[0]&ADC_SC1_COCO_MASK)); //Settings pins /*pin.setPort (pin_def [n_channel][0]); pin.setOutPin (pin_def [n_channel][1], 0);*/ ADC0->CFG1|= ADC_CFG1_ADLSMP_MASK|ADC_CFG1_MODE(r_); }
bool init_adc () { //tact ADC0 SIM->SCGC6 |= SIM_SCGC6_ADC0_MASK; //Set busclock ADC0->CFG1 &= ~ADC_CFG1_ADICLK_MASK; //Set divider - 8 ADC0->CFG1 |= ADC_CFG1_ADIV(3); ADC0->SC3 |= ADC_SC3_AVGE_MASK|ADC_SC3_AVGS(3); ADC0->SC2 &= ~ ADC_SC2_ADTRG_MASK; ADC0->SC3 |= ADC_SC3_CAL_MASK ; while (!(ADC0->SC1[0]&ADC_SC1_COCO_MASK)); if (ADC0->SC3&ADC_SC3_CALF_MASK) return false; calibr = ADC0->CLP0+ADC0->CLP1+ADC0->CLP2+ADC0->CLP3+ADC0->CLP4+ADC0->CLPS; calibr >>=1; ADC0->CFG1|= ADC_CFG1_ADLSMP_MASK|ADC_CFG1_MODE(2); return true; }
void CIO::startInt() { // Initialise ADC0 conversion to be triggered by the PDB ADC0_CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) | ADC_CFG1_MODE(1) | ADC_CFG1_ADLSMP; // Single-ended 12 bits, long sample time ADC0_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2); // Select channels ADxxxb ADC0_SC2 = ADC_SC2_REFSEL(1) | ADC_SC2_ADTRG; // Voltage ref internal, hardware trigger ADC0_SC3 = ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples ADC0_SC1A = ADC_SC1_AIEN | 5; // Enable ADC interrupt, use A0 NVIC_ENABLE_IRQ(IRQ_ADC0); // Setup PDB for ADC0 at 24 kHz SIM_SCGC6 |= SIM_SCGC6_PDB; // Enable PDB clock #if F_BUS == 60000000 // 60 MHz for the Teensy 3.5/3.6 PDB0_MOD = 2500; // Timer period for 60 MHz bus #else // 48 MHz for the Teensy 3.1/3.2 PDB0_MOD = 2000; // Timer period for 48 MHz bus #endif PDB0_IDLY = 0; // Interrupt delay PDB0_CH0C1 = PDB_CH0C1_TOS | PDB_CH0C1_EN; // Enable pre-trigger PDB0_SC = PDB_SC_TRGSEL(15) | PDB_SC_PDBEN | PDB_SC_PDBIE | PDB_SC_CONT | PDB_SC_PRESCALER(7) | PDB_SC_MULT(1) | PDB_SC_LDOK; PDB0_SC |= PDB_SC_SWTRIG; // Software trigger (reset and restart counter) #if defined(SEND_RSSI_DATA) // Initialise ADC1 conversion to be triggered by the PDB // Setup interrupt on ADC1 conversion finished // Setup PDB for ADC1 at 24 kHz #endif // Initialise the DAC SIM_SCGC2 |= SIM_SCGC2_DAC0; DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // 1.2V VDDA is DACREF_2 digitalWrite(PIN_PTT, m_pttInvert ? HIGH : LOW); digitalWrite(PIN_COSLED, LOW); digitalWrite(PIN_LED, HIGH); }
////Initialize ADC Function. Needs to be placed somewhere?? void AnalogInputPin::InitADCs() { // setup the initial ADC default configuration Master_Adc_Config.CONFIG1 = ADLPC_NORMAL // Normal power, (not low power) | ADC_CFG1_ADIV(ADIV_4) // Clock divider | ADLSMP_LONG // Take a long time to sample | ADC_CFG1_MODE(MODE_16) // 16 bit mode | ADC_CFG1_ADICLK(ADICLK_BUS); // use the bus clock Master_Adc_Config.CONFIG2 = MUXSEL_ADCB // use channel A | ADACKEN_DISABLED // Asynch clock disabled? | ADHSC_NORMAL // Asynch clock setting | ADC_CFG2_ADLSTS(ADLSTS_20) ; Master_Adc_Config.COMPARE1 = 0x1234u ; // can be anything Master_Adc_Config.COMPARE2 = 0x5678u ; // can be anything // since not using // compare feature Master_Adc_Config.STATUS2 = ADTRG_SW // Software triggered conversion | ACFE_DISABLED // Disable comparator (if enabled only registers as an anlog reading if it is greater than a certain value) | ACFGT_GREATER // comparator setting | ACREN_DISABLED // Compare Function Range disabled | DMAEN_DISABLED // Disable DMA | ADC_SC2_REFSEL(REFSEL_EXT); // external voltage reference Master_Adc_Config.STATUS3 = CAL_OFF // Calibration begins off | ADCO_SINGLE // Take a single reading | AVGE_ENABLED // Enable averaging | ADC_SC3_AVGS(AVGS_32); // Average 32 samples Master_Adc_Config.PGA = PGAEN_DISABLED // PGA disabled | PGACHP_NOCHOP // no chopping for PGA? | PGALP_NORMAL // Normal (not low power mode) | ADC_PGA_PGAG(PGAG_64); // PGA gain of 64 // Set up channel as all ones for configuration Master_Adc_Config.STATUS1A = AIEN_OFF | DIFF_SINGLE | ADC_SC1_ADCH(31); Master_Adc_Config.STATUS1B = AIEN_OFF | DIFF_SINGLE | ADC_SC1_ADCH(31); // Configure ADC as it will be used, but becuase ADC_SC1_ADCH is 31, // the ADC will be inactive. Channel 31 is just disable function. // There really is no channel 31. ADC_Config_Alt(ADC0_BASE_PTR, &Master_Adc_Config); // config ADC ADC_Config_Alt(ADC1_BASE_PTR, &Master_Adc_Config); // config ADC // Calibrate the ADC in the configuration in which it will be used: ADC_Cal(ADC1_BASE_PTR); // do the calibration ADC_Cal(ADC0_BASE_PTR); // do the calibration // The structure still has the desired configuration. So restore it. // Why restore it? The calibration makes some adjustments to the // configuration of the ADC. The are now undone: // config the ADC again to desired conditions ADC_Config_Alt(ADC1_BASE_PTR, &Master_Adc_Config); ADC_Config_Alt(ADC0_BASE_PTR, &Master_Adc_Config); //Load Encoder ADC Config (A bit different from Master) Encoder_Adc_Config = Master_Adc_Config; Encoder_Adc_Config.CONFIG1 = ADLPC_NORMAL // Normal power, (not low power) | ADC_CFG1_ADIV(ADIV_4) // Clock divider | ADLSMP_LONG // Take a long time to sample | ADC_CFG1_MODE(MODE_16) // 16 bit mode | ADC_CFG1_ADICLK(ADICLK_BUS); // use the bus clock Encoder_Adc_Config.STATUS3 = CAL_OFF // Calibration begins off | ADCO_SINGLE // Take a single reading | AVGE_ENABLED // Enable averaging | ADC_SC3_AVGS(AVGS_4); // Average 4 samples }
int adc_init() { adc_pixelIndex = 0; // disable ADC irq - not ready yet disable_irq(ADC_IRQ_NUM); // turn on clock to ADC0 SIM_SCGC6 |= (SIM_SCGC6_ADC0_MASK); // to setup SW trigger on FTM2 SIM_SOPT7 = SIM_SOPT7_ADC0TRGSEL(10); // to calibrate the ADC module unsigned short cal_var; cal_var = 0x0000; // add the plus-side calibration results cal_var += ADC_CLP0_REG(ADC0_BASE_PTR); cal_var += ADC_CLP1_REG(ADC0_BASE_PTR); cal_var += ADC_CLP2_REG(ADC0_BASE_PTR); cal_var += ADC_CLP3_REG(ADC0_BASE_PTR); cal_var += ADC_CLP4_REG(ADC0_BASE_PTR); cal_var += ADC_CLPS_REG(ADC0_BASE_PTR); cal_var /= 2; cal_var |= 0x8000; // store value in plus-side gain calibration register (PG) ADC_PG_REG(ADC0_BASE_PTR) = ADC_PG_PG(cal_var); cal_var = 0x0000; // add the minus-side calibration results cal_var += ADC_CLM0_REG(ADC0_BASE_PTR); cal_var += ADC_CLM1_REG(ADC0_BASE_PTR); cal_var += ADC_CLM2_REG(ADC0_BASE_PTR); cal_var += ADC_CLM3_REG(ADC0_BASE_PTR); cal_var += ADC_CLM4_REG(ADC0_BASE_PTR); cal_var += ADC_CLMS_REG(ADC0_BASE_PTR); cal_var /= 2; cal_var |= 0x8000; // store value in minus-side gain calibration register (MG) ADC_MG_REG(ADC0_BASE_PTR) = ADC_MG_MG(cal_var); ADC_SC3_REG(ADC0_BASE_PTR) &= ~ADC_SC3_CAL_MASK; // to set the configuration register 1 (CFG1) to select the mode of // operation, clock source, clock divide, and configuration for low // power or long sample time ADC_CFG1_REG(ADC0_BASE_PTR) = ADLPC_NORMAL | ADC_CFG1_ADIV(ADIV_1) | ADLSMP_SHORT | ADC_CFG1_MODE(MODE_8) | ADC_CFG1_ADICLK(ADICLK_BUS); // to set the configuration register 2 (CFG2) to select the special // high-speed configuration for very high speed conversions and // select the long sample time duration during long sample mode ADC_CFG2_REG(ADC0_BASE_PTR) = MUXSEL_ADCA | ADACKEN_DISABLED | ADHSC_HISPEED | ADC_CFG2_ADLSTS(ADLSTS_2); // to configure the status and control register 2 (SC2) ADC_SC2_REG(ADC0_BASE_PTR) = ADTRG_SW | ACFE_DISABLED | ACFGT_GREATER | ACREN_DISABLED | DMAEN_DISABLED | ADC_SC2_REFSEL(REFSEL_EXT); // to configure the status and control register 3 (SC3) // enable hw averaging, 16 samples taken ADC_SC3_REG(ADC0_BASE_PTR) = CAL_OFF | ADCO_SINGLE | AVGE_ENABLED | ADC_SC3_AVGS(AVGS_16); // to configure the status and control register 1 (SC1) // enable the interrupt, single-ended conversion, on AD18 ADC_SC1_REG(ADC0_BASE_PTR, A)= AIEN_ON | DIFF_SINGLE | ADC_SC1_ADCH(18); // to configure the PGA register ADC_PGA_REG(ADC0_BASE_PTR) = PGAEN_DISABLED | PGACHP_NOCHOP | PGALP_NORMAL | ADC_PGA_PGAG(PGAG_64); // enable ADC irq enable_irq(ADC_IRQ_NUM); return ADC_RET_SUCCESS; }
//------------------------------------------------------------ // Calibration du convertisseur AD // Retour: true = OK, false = KO //------------------------------------------------------------ bool iAd_Cal(void) { UInt16 aCalVar=0; bool aRet; // Max ADC clock -> 4MHz ADC1_CFG1&=((~ADC_CFG1_ADIV_MASK)&(~ADC_CFG1_ADICLK_MASK)); ADC1_CFG1|=(ADC_CFG1_ADIV(3)|ADC_CFG1_MODE(1)|ADC_CFG1_ADICLK(1)|ADC_CFG1_ADLSMP_MASK); // Enable Software Conversion Trigger for Calibration Process ADC1_SC2&=(~ADC_SC2_ADTRG_MASK); // Set single conversion, clear avgs bitfield for next writing ADC1_SC3&= ((~ADC_SC3_ADCO_MASK) & (~ADC_SC3_AVGS_MASK)); // Turn averaging ON and set at max value ( 32 ) ADC1_SC3|= (ADC_SC3_AVGE_MASK | ADC_SC3_AVGS(3) ); // Start CAL ADC1_SC3 |= ADC_SC3_CAL_MASK ; // Wait calibration end while ( (ADC1_SC1A & ADC_SC1_COCO_MASK ) == false ); // Check for Calibration fail error and return if ((ADC1_SC3&ADC_SC3_CALF_MASK) == ADC_SC3_CALF_MASK) { aRet=false; // Clear CAL bit ADC1_SC3&= (~ADC_SC3_CAL_MASK); } else { // Calculate plus-side calibration aCalVar = 0x00; aCalVar = ADC1_CLP0; aCalVar += ADC1_CLP1; aCalVar += ADC1_CLP2; aCalVar += ADC1_CLP3; aCalVar += ADC1_CLP4; aCalVar += ADC1_CLPS; aCalVar = aCalVar/2; aCalVar |= 0x8000; // Set MSB ADC1_PG= ADC_PG_PG(aCalVar); // Calculate minus-side calibration aCalVar = 0x00; aCalVar = ADC1_CLM0; aCalVar += ADC1_CLM1; aCalVar += ADC1_CLM2; aCalVar += ADC1_CLM3; aCalVar += ADC1_CLM4; aCalVar += ADC1_CLMS; aCalVar = aCalVar/2; aCalVar |= 0x8000; // Set MSB ADC1_MG = ADC_MG_MG(aCalVar); // Clear CAL bit ADC1_SC3&= (~ADC_SC3_CAL_MASK); // Return OK aRet=true; } return aRet; }
void AudioInputAnalogStereo::init(uint8_t pin0, uint8_t pin1) { uint32_t tmp; //pinMode(32, OUTPUT); //pinMode(33, OUTPUT); // Configure the ADC and run at least one software-triggered // conversion. This completes the self calibration stuff and // leaves the ADC in a state that's mostly ready to use analogReadRes(16); analogReference(INTERNAL); // range 0 to 1.2 volts #if F_BUS == 96000000 || F_BUS == 48000000 || F_BUS == 24000000 analogReadAveraging(8); ADC1_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(1); #else analogReadAveraging(4); ADC1_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(0); #endif // Note for review: // Probably not useful to spin cycles here stabilizing // since DC blocking is similar to te external analog filters tmp = (uint16_t) analogRead(pin0); tmp = ( ((int32_t) tmp) << 14); hpf_x1[0] = tmp; // With constant DC level x1 would be x0 hpf_y1[0] = 0; // Output will settle here when stable tmp = (uint16_t) analogReadADC1(pin1); tmp = ( ((int32_t) tmp) << 14); hpf_x1[1] = tmp; // With constant DC level x1 would be x0 hpf_y1[1] = 0; // Output will settle here when stable // set the programmable delay block to trigger the ADC at 44.1 kHz //if (!(SIM_SCGC6 & SIM_SCGC6_PDB) //|| (PDB0_SC & PDB_CONFIG) != PDB_CONFIG //|| PDB0_MOD != PDB_PERIOD //|| PDB0_IDLY != 1 //|| PDB0_CH0C1 != 0x0101) { SIM_SCGC6 |= SIM_SCGC6_PDB; PDB0_IDLY = 1; PDB0_MOD = PDB_PERIOD; PDB0_SC = PDB_CONFIG | PDB_SC_LDOK; PDB0_SC = PDB_CONFIG | PDB_SC_SWTRIG; PDB0_CH0C1 = 0x0101; PDB0_CH1C1 = 0x0101; //} // enable the ADC for hardware trigger and DMA ADC0_SC2 |= ADC_SC2_ADTRG | ADC_SC2_DMAEN; ADC1_SC2 |= ADC_SC2_ADTRG | ADC_SC2_DMAEN; // set up a DMA channel to store the ADC data dma0.begin(true); dma1.begin(true); // ADC0_RA = 0x4003B010 // ADC1_RA = 0x400BB010 dma0.TCD->SADDR = &ADC0_RA; dma0.TCD->SOFF = 0; dma0.TCD->ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1); dma0.TCD->NBYTES_MLNO = 2; dma0.TCD->SLAST = 0; dma0.TCD->DADDR = left_buffer; dma0.TCD->DOFF = 2; dma0.TCD->CITER_ELINKNO = sizeof(left_buffer) / 2; dma0.TCD->DLASTSGA = -sizeof(left_buffer); dma0.TCD->BITER_ELINKNO = sizeof(left_buffer) / 2; dma0.TCD->CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR; dma1.TCD->SADDR = &ADC1_RA; dma1.TCD->SOFF = 0; dma1.TCD->ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1); dma1.TCD->NBYTES_MLNO = 2; dma1.TCD->SLAST = 0; dma1.TCD->DADDR = right_buffer; dma1.TCD->DOFF = 2; dma1.TCD->CITER_ELINKNO = sizeof(right_buffer) / 2; dma1.TCD->DLASTSGA = -sizeof(right_buffer); dma1.TCD->BITER_ELINKNO = sizeof(right_buffer) / 2; dma1.TCD->CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR; dma0.triggerAtHardwareEvent(DMAMUX_SOURCE_ADC0); //dma1.triggerAtHardwareEvent(DMAMUX_SOURCE_ADC1); dma1.triggerAtTransfersOf(dma0); dma1.triggerAtCompletionOf(dma0); update_responsibility = update_setup(); dma0.enable(); dma1.enable(); dma0.attachInterrupt(isr0); dma1.attachInterrupt(isr1); }
void analog_init(void) { uint32_t num; #if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) VREF_TRM = 0x60; VREF_SC = 0xE1; // enable 1.2 volt ref #endif if (analog_config_bits == 8) { ADC0_CFG1 = ADC_CFG1_8BIT + ADC_CFG1_MODE(0); ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3); #ifdef HAS_KINETIS_ADC1 ADC1_CFG1 = ADC_CFG1_8BIT + ADC_CFG1_MODE(0); ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3); #endif } else if (analog_config_bits == 10) { ADC0_CFG1 = ADC_CFG1_10BIT + ADC_CFG1_MODE(2) + ADC_CFG1_ADLSMP; ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3); #ifdef HAS_KINETIS_ADC1 ADC1_CFG1 = ADC_CFG1_10BIT + ADC_CFG1_MODE(2) + ADC_CFG1_ADLSMP; ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3); #endif } else if (analog_config_bits == 12) { ADC0_CFG1 = ADC_CFG1_12BIT + ADC_CFG1_MODE(1) + ADC_CFG1_ADLSMP; ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2); #ifdef HAS_KINETIS_ADC1 ADC1_CFG1 = ADC_CFG1_12BIT + ADC_CFG1_MODE(1) + ADC_CFG1_ADLSMP; ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2); #endif } else { ADC0_CFG1 = ADC_CFG1_16BIT + ADC_CFG1_MODE(3) + ADC_CFG1_ADLSMP; ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2); #ifdef HAS_KINETIS_ADC1 ADC1_CFG1 = ADC_CFG1_16BIT + ADC_CFG1_MODE(3) + ADC_CFG1_ADLSMP; ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2); #endif } #if defined(__MK20DX128__) if (analog_reference_internal) { ADC0_SC2 = ADC_SC2_REFSEL(1); // 1.2V ref } else { ADC0_SC2 = ADC_SC2_REFSEL(0); // vcc/ext ref } #elif defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) if (analog_reference_internal) { ADC0_SC2 = ADC_SC2_REFSEL(1); // 1.2V ref ADC1_SC2 = ADC_SC2_REFSEL(1); // 1.2V ref } else { ADC0_SC2 = ADC_SC2_REFSEL(0); // vcc/ext ref ADC1_SC2 = ADC_SC2_REFSEL(0); // vcc/ext ref } #elif defined(__MKL26Z64__) if (analog_reference_internal) { ADC0_SC2 = ADC_SC2_REFSEL(0); // external AREF } else { ADC0_SC2 = ADC_SC2_REFSEL(1); // vcc } #endif num = analog_num_average; if (num <= 1) { ADC0_SC3 = ADC_SC3_CAL; // begin cal #ifdef HAS_KINETIS_ADC1 ADC1_SC3 = ADC_SC3_CAL; // begin cal #endif } else if (num <= 4) { ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(0); #ifdef HAS_KINETIS_ADC1 ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(0); #endif } else if (num <= 8) { ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(1); #ifdef HAS_KINETIS_ADC1 ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(1); #endif } else if (num <= 16) { ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(2); #ifdef HAS_KINETIS_ADC1 ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(2); #endif } else { ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(3); #ifdef HAS_KINETIS_ADC1 ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(3); #endif } calibrating = 1; }
void CIO::startInt() { // Initialise the DAC SIM_SCGC2 |= SIM_SCGC2_DAC0; DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // 3.3V VDDA is DACREF_2 // Initialise ADC0 SIM_SCGC6 |= SIM_SCGC6_ADC0; ADC0_CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) | // Single-ended 12 bits, long sample time ADC_CFG1_MODE(1) | ADC_CFG1_ADLSMP; ADC0_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2); // Select channels ADxxxb ADC0_SC2 = ADC_SC2_REFSEL(0) | ADC_SC2_ADTRG; // Voltage ref external, hardware trigger ADC0_SC3 = ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples ADC0_SC3 |= ADC_SC3_CAL; while (ADC0_SC3 & ADC_SC3_CAL) // Wait for calibration ; uint16_t sum0 = ADC0_CLPS + ADC0_CLP4 + ADC0_CLP3 + // Plus side gain ADC0_CLP2 + ADC0_CLP1 + ADC0_CLP0; sum0 = (sum0 / 2U) | 0x8000U; ADC0_PG = sum0; ADC0_SC1A = ADC_SC1_AIEN | PIN_ADC; // Enable ADC interrupt, use A0 NVIC_ENABLE_IRQ(IRQ_ADC0); #if defined(SEND_RSSI_DATA) // Initialise ADC1 SIM_SCGC3 |= SIM_SCGC3_ADC1; ADC1_CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) | // Single-ended 12 bits, long sample time ADC_CFG1_MODE(1) | ADC_CFG1_ADLSMP; ADC1_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2); // Select channels ADxxxb ADC1_SC2 = ADC_SC2_REFSEL(0); // Voltage ref external, software trigger ADC1_SC3 = ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples ADC1_SC3 |= ADC_SC3_CAL; while (ADC1_SC3 & ADC_SC3_CAL) // Wait for calibration ; uint16_t sum1 = ADC1_CLPS + ADC1_CLP4 + ADC1_CLP3 + // Plus side gain ADC1_CLP2 + ADC1_CLP1 + ADC1_CLP0; sum1 = (sum1 / 2U) | 0x8000U; ADC1_PG = sum1; #endif #if defined(EXTERNAL_OSC) // Set ADC0 to trigger from the LPTMR at 24 kHz SIM_SOPT7 = SIM_SOPT7_ADC0ALTTRGEN | // Enable ADC0 alternate trigger SIM_SOPT7_ADC0TRGSEL(14); // Trigger ADC0 by LPTMR0 CORE_PIN13_CONFIG = PORT_PCR_MUX(3); SIM_SCGC5 |= SIM_SCGC5_LPTIMER; // Enable Low Power Timer Access LPTMR0_CSR = 0; // Disable LPTMR0_PSR = LPTMR_PSR_PBYP; // Bypass prescaler/filter LPTMR0_CMR = (EXTERNAL_OSC / 24000) - 1; // Frequency divided by CMR + 1 LPTMR0_CSR = LPTMR_CSR_TPS(2) | // Pin: 0=CMP0, 1=xtal, 2=pin13 LPTMR_CSR_TMS; // Mode Select, 0=timer, 1=counter LPTMR0_CSR |= LPTMR_CSR_TEN; // Enable #else // Setup PDB for ADC0 at 24 kHz SIM_SCGC6 |= SIM_SCGC6_PDB; // Enable PDB clock PDB0_MOD = (F_BUS / 24000) - 1; // Timer period - 1 PDB0_IDLY = 0; // Interrupt delay PDB0_CH0C1 = PDB_CHnC1_TOS | PDB_CHnC1_EN; // Enable pre-trigger for ADC0 PDB0_SC = PDB_SC_TRGSEL(15) | PDB_SC_PDBEN | // SW trigger, enable interrupts, continuous mode PDB_SC_PDBIE | PDB_SC_CONT | PDB_SC_LDOK; // No prescaling PDB0_SC |= PDB_SC_SWTRIG; // Software trigger (reset and restart counter) #endif digitalWrite(PIN_PTT, m_pttInvert ? HIGH : LOW); digitalWrite(PIN_COSLED, LOW); digitalWrite(PIN_LED, HIGH); }
uint8_t Hw_Trig_Test(void) { // Notes: // PDB settings : continous mode, started by sotware trigger. // This means that once the software "pulls the trigger" by setting a certain bit, the PDB starts counting // and handing out four triggers per cycle of its counter. // PDB settings: CH0_DLY0, CH0_DLY1 , CH1_DLY0, CH1_DLY1 // set to different values to distinguish effect on ADCx_Ry register // need to provide 4 different voltages to convert at two ADC0 and two ADC1 input channels // PDB counter clock prescaled to allow time for printf's and slow down things to they are visible, each trigger. // Using adiclk= BUS , and adidiv/4 to get 12,5MHz on Tower demonstration. // visibility of PDB start trigger is obtained by generating a toggling edge on // GPIOxx with PDBisr set to trigger immediatly at zero value of PDB counter. // Conversion end of each ADC and channel within the ADC ( A,B ) will be done by // toggling second GPIO pin inside ADCisr ( this pin is also reset by PDB isr ) // GPIO PIN to low voltage .. this macro sets the PIN low. PIN_LOW // Initialize PIN1 and PIN2 GPIO outputs Init_Gpio2(); // Disable ADC and PDB interrupts disable_irq(ADC0_irq_no) ; // not ready for this interrupt yet. Plug vector first. disable_irq(ADC1_irq_no) ; // not ready for this interrupt yet. Plug vector first. disable_irq(PDB_irq_no) ; // not ready for this interrupt yet. Plug vector first. // Dynamic interrupt vector modification whilst those interruts are disabled __VECTOR_RAM[73] = (uint32)adc0_isr; // plug isr into vector table in case not there already __VECTOR_RAM[74] = (uint32)adc1_isr; // plug isr into vector table in case not there already __VECTOR_RAM[88] = (uint32)pdb_isr; // plug isr into vector table in case not there already // The System Integration Module largely determines the role of the different ball map locations on Kinetis. // When an external pin is used, the System Integration Module should be consulted and invoked as needed. // System integration module registers start with SIM_ // Turn on the ADC0 and ADC1 clocks as well as the PDB clocks to test ADC triggered by PDB SIM_SCGC6 |= (SIM_SCGC6_ADC0_MASK ); SIM_SCGC3 |= (SIM_SCGC3_ADC1_MASK ); SIM_SCGC6 |= SIM_SCGC6_PDB_MASK ; // Configure System Integration Module for defaults as far as ADC SIM_SOPT7 &= ~(SIM_SOPT7_ADC1ALTTRGEN_MASK | // selects PDB not ALT trigger SIM_SOPT7_ADC1PRETRGSEL_MASK | SIM_SOPT7_ADC0ALTTRGEN_MASK | // selects PDB not ALT trigger SIM_SOPT7_ADC0ALTTRGEN_MASK) ; SIM_SOPT7 = SIM_SOPT7_ADC0TRGSEL(0); // applies only in case of ALT trigger, in which case // PDB external pin input trigger for ADC SIM_SOPT7 = SIM_SOPT7_ADC1TRGSEL(0); // same for both ADCs ///////////////////////////////////////////////////////////////////////////////////////// //PDB configured below 以下是PDB配置 // Configure the Peripheral Delay Block (PDB): // enable PDB, pdb counter clock = busclock / 20 , continous triggers, sw trigger , and use prescaler too PDB0_SC = PDB_SC_CONT_MASK // Contintuous, rather than one-shot, mode | PDB_SC_PDBEN_MASK // PDB enabled | PDB_SC_PDBIE_MASK // PDB Interrupt Enable | PDB_SC_PRESCALER(0x5) // Slow down the period of the PDB for testing | PDB_SC_TRGSEL(0xf) // Trigger source is Software Trigger to be invoked in this file | PDB_SC_MULT(2); // Multiplication factor 20 for the prescale divider for the counter clock // the software trigger, PDB_SC_SWTRIG_MASK is not triggered at this time. PDB0_IDLY = 0x0000; // need to trigger interrupt every counter reset which happens when modulus reached PDB0_MOD = 0xffff; // largest period possible with the slections above, so slow you can see each conversion. // channel 0 pretrigger 0 and 1 enabled and delayed PDB0_CH0C1 = PDB_C1_EN(0x01) | PDB_C1_TOS(0x01) | PDB_C1_EN(0x02) | PDB_C1_TOS(0x02) ; PDB0_CH0DLY0 = ADC0_DLYA ; PDB0_CH0DLY1 = ADC0_DLYB ; // channel 1 pretrigger 0 and 1 enabled and delayed PDB0_CH1C1 = PDB_C1_EN(0x01) | PDB_C1_TOS(0x01) | PDB_C1_EN(0x02) | PDB_C1_TOS(0x02) ; PDB0_CH1DLY0 = ADC1_DLYA ; PDB0_CH1DLY1 = ADC1_DLYB ; PDB0_SC = PDB_SC_CONT_MASK // Contintuous, rather than one-shot, mode | PDB_SC_PDBEN_MASK // PDB enabled | PDB_SC_PDBIE_MASK // PDB Interrupt Enable | PDB_SC_PRESCALER(0x5) // Slow down the period of the PDB for testing | PDB_SC_TRGSEL(0xf) // Trigger source is Software Trigger to be invoked in this file | PDB_SC_MULT(2) // Multiplication factor 20 for the prescale divider for the counter clock | PDB_SC_LDOK_MASK; // Need to ok the loading or it will not load certain regsiters! // the software trigger, PDB_SC_SWTRIG_MASK is not triggered at this time. //PDB configured above 以上是PDB配置 ///////////////////////////////////////////////////////////////////////////////////////// //ADC configured below 以下是ADC配置 // setup the initial ADC default configuration Master_Adc_Config.CONFIG1 = ADLPC_NORMAL | ADC_CFG1_ADIV(ADIV_4) | ADLSMP_LONG | ADC_CFG1_MODE(MODE_16) | ADC_CFG1_ADICLK(ADICLK_BUS); Master_Adc_Config.CONFIG2 = MUXSEL_ADCA | ADACKEN_DISABLED | ADHSC_HISPEED | ADC_CFG2_ADLSTS(ADLSTS_20) ; Master_Adc_Config.COMPARE1 = 0x1234u ; // can be anything Master_Adc_Config.COMPARE2 = 0x5678u ; // can be anything // since not using // compare feature Master_Adc_Config.STATUS2 = ADTRG_HW | ACFE_DISABLED | ACFGT_GREATER | ACREN_ENABLED | DMAEN_DISABLED | ADC_SC2_REFSEL(REFSEL_EXT); Master_Adc_Config.STATUS3 = CAL_OFF | ADCO_SINGLE | AVGE_ENABLED | ADC_SC3_AVGS(AVGS_32); Master_Adc_Config.PGA = PGAEN_DISABLED | PGACHP_NOCHOP | PGALP_NORMAL | ADC_PGA_PGAG(PGAG_64); Master_Adc_Config.STATUS1A = AIEN_OFF | DIFF_SINGLE | ADC_SC1_ADCH(31); Master_Adc_Config.STATUS1B = AIEN_OFF | DIFF_SINGLE | ADC_SC1_ADCH(31); // Configure ADC as it will be used, but becuase ADC_SC1_ADCH is 31, // the ADC will be inactive. Channel 31 is just disable function. // There really is no channel 31. ADC_Config_Alt(ADC0_BASE_PTR, &Master_Adc_Config); // config ADC // Calibrate the ADC in the configuration in which it will be used: ADC_Cal(ADC0_BASE_PTR); // do the calibration // The structure still has the desired configuration. So restore it. // Why restore it? The calibration makes some adjustments to the // configuration of the ADC. The are now undone: // config the ADC again to desired conditions ADC_Config_Alt(ADC0_BASE_PTR, &Master_Adc_Config); // REPEAT for BOTH ADC's. However we will only 'use' the results from // the ADC wired to the Potentiometer on the Kinetis Tower Card. // Repeating for ADC1: ADC_Config_Alt(ADC1_BASE_PTR, &Master_Adc_Config); // config ADC ADC_Cal(ADC1_BASE_PTR); // do the calibration // ADC_Read_Cal(ADC1_BASE_PTR,&CalibrationStore[0]); // store the cal // config the ADC again to default conditions ADC_Config_Alt(ADC1_BASE_PTR, &Master_Adc_Config); // ***************************************************************************** // ADC0 and ADC1 using the PDB trigger in ping pong // ***************************************************************************** // use interrupts, single ended mode, and real channel numbers now: Master_Adc_Config.STATUS1A = AIEN_ON | DIFF_SINGLE | ADC_SC1_ADCH(ADC0_CHANA); Master_Adc_Config.STATUS1B = AIEN_ON | DIFF_SINGLE | ADC_SC1_ADCH(ADC0_CHANB); ADC_Config_Alt(ADC0_BASE_PTR, &Master_Adc_Config); // config ADC0 Master_Adc_Config.STATUS1A = AIEN_ON | DIFF_SINGLE | ADC_SC1_ADCH(ADC1_CHANA); Master_Adc_Config.STATUS1B = AIEN_ON | DIFF_SINGLE | ADC_SC1_ADCH(ADC1_CHANB); ADC_Config_Alt(ADC1_BASE_PTR, &Master_Adc_Config); // config ADC1 // Note that three different balls are being sampled: // ADC0_CHANA not used in this demo, but readings are shown // ADC0_CHANB not used in this demo, but readings are shown // ADC1_CHANA POT channel set the same as the following for demo: 20 // ADC1_CHANB POT channel set the same as the above for demo: 20 // The potentiometer is only on ADC1. That is the one used // to calculate the change of the potentiometer below. while(char_present()) in_char(); // flush terminal buffer printf ("\n\n\n"); printf("********************************************************\n"); printf("* Running ADC0 & ADC1 HARDWARE TRIGGER by PDB *\n"); printf("* The one PDB is triggering both ADC0 and ADC1 *\n"); printf("* ADC1 A,B is the POT. Vary the POT setting. *\n"); printf("* Hit any key to exit (ADC0 readings not used) *\n"); printf("********************************************************\n"); printf ("\n\n"); // Enable the ADC and PDB interrupts in NVIC enable_irq(ADC0_irq_no) ; // ready for this interrupt. enable_irq(ADC1_irq_no) ; // ready for this interrupt. enable_irq(PDB_irq_no) ; // ready for this interrupt. // In case previous test did not end with interrupts enabled, enable used ones. EnableInterrupts ; cycle_flags=0; PDB0_SC |= PDB_SC_SWTRIG_MASK ; // kick off the PDB - just once //The system is now working!!!! The PDB is *continuously* triggering ADC // conversions. Now, to display the results! The line above // was the SOFTWARE TRIGGER... // The demo will continue as long as no character is pressed on the terminal. while(!char_present()) // as long as no operater intervention, keep running this: { while( cycle_flags != ( ADC0A_DONE | ADC0B_DONE | ADC1A_DONE | ADC1B_DONE )); // wait for one complete cycle printf("R0A=%6d R0B=%6d R1A=%6d R1B=%6d POT=%6d\r", result0A,result0B,result1A,result1B, exponentially_filtered_result1); } // disable the PDB PDB0_SC = 0 ; // Disable the ADC and PDB interrupts in NVIC disable_irq(ADC0_irq_no) ; // through with this interrupt. disable_irq(ADC1_irq_no) ; // through with this interrupt. disable_irq(PDB_irq_no) ; // through with this interrupt. printf ("\n\n\n"); printf("********************************************************\n"); printf("* Demonstration ended at operator request *\n"); printf("* ADC0 & ADC1 PDB TRIGGER DEMO COMPLETE *\n"); printf("********************************************************\n"); printf ("\n\n"); return 0; }
void InitADC1() { tADC_Config Master_Adc1_Config; SIM_SCGC3 |= (SIM_SCGC3_ADC1_MASK); //Lets calibrate the ADC. 1st setup how the channel will be used. disable_irq(INT_ADC1-16); Master_Adc1_Config.CONFIG1 = ADLPC_NORMAL //No low power mode | ADC_CFG1_ADIV(ADIV_4) //divide input by 4 | ADLSMP_LONG //long sample time | ADC_CFG1_MODE(MODE_8)//single ended 8-bit conversion | ADC_CFG1_ADICLK(ADICLK_BUS); Master_Adc1_Config.CONFIG2 = MUXSEL_ADCA // select the A side of the ADC channel. | ADACKEN_DISABLED | ADHSC_HISPEED | ADC_CFG2_ADLSTS(ADLSTS_2);//Extra long sample Time (20 extra clocks) Master_Adc1_Config.COMPARE1 = 00000; // Comparators don't matter for calibration Master_Adc1_Config.COMPARE1 = 0xFFFF; Master_Adc1_Config.STATUS2 = ADTRG_HW //hardware triggers for calibration | ACFE_DISABLED //disable comparator | ACFGT_GREATER | ACREN_ENABLED | DMAEN_DISABLED //Disable DMA | ADC_SC2_REFSEL(REFSEL_EXT); //External Reference Master_Adc1_Config.STATUS3 = CAL_OFF | ADCO_SINGLE | AVGE_ENABLED | ADC_SC3_AVGS(AVGS_4); Master_Adc1_Config.PGA = 0; // Disable the PGA // Configure ADC as it will be used, but because ADC_SC1_ADCH is 31, // the ADC will be inactive. Channel 31 is just disable function. // There really is no channel 31. Master_Adc1_Config.STATUS1A = AIEN_ON | DIFF_SINGLE | ADC_SC1_ADCH(31); // Master_Adc_Config.STATUS1B = AIEN_OFF | DIFF_SINGLE | ADC_SC1_ADCH(31); ADC_Config_Alt(ADC1_BASE_PTR, &Master_Adc1_Config); // config ADC // Calibrate the ADC in the configuration in which it will be used: ADC_Cal(ADC1_BASE_PTR); // do the calibration Master_Adc1_Config.STATUS2 = ACFE_DISABLED //disable comparator | ACFGT_GREATER | ACREN_ENABLED | DMAEN_DISABLED //Disable DMA | ADC_SC2_REFSEL(REFSEL_EXT); //External Reference Master_Adc1_Config.STATUS3 = CAL_OFF | ADCO_SINGLE; ADC_Config_Alt(ADC1_BASE_PTR, &Master_Adc1_Config); }
void adc_init(void) { SIM_SCGC3 |= SIM_SCGC3_ADC1_MASK; ADC1_CFG1 = ADC_CFG1_MODE(ADC_CFG1_MODE_12_13_BIT); ADC1_SC3 = ADC_SC3_AVGE_MASK | ADC_SC3_AVGS(ADC_SC3_AVGS_32_SAMPLES); }
void AudioInputAnalogStereo::init(uint8_t pin0, uint8_t pin1) { uint32_t i, sum0=0, sum1=0; //pinMode(32, OUTPUT); //pinMode(33, OUTPUT); // Configure the ADC and run at least one software-triggered // conversion. This completes the self calibration stuff and // leaves the ADC in a state that's mostly ready to use analogReadRes(16); analogReference(INTERNAL); // range 0 to 1.2 volts #if F_BUS == 96000000 || F_BUS == 48000000 || F_BUS == 24000000 analogReadAveraging(8); ADC1_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(1); #else analogReadAveraging(4); ADC1_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(0); #endif // Actually, do many normal reads, to start with a nice DC level for (i=0; i < 1024; i++) { sum0 += analogRead(pin0); sum1 += analogReadADC1(pin1); } for (i = 0; i < 16; i++) { left_dc_average_hist[i] = sum0 >> 10; right_dc_average_hist[i] = sum1 >> 10; } // set the programmable delay block to trigger the ADC at 44.1 kHz //if (!(SIM_SCGC6 & SIM_SCGC6_PDB) //|| (PDB0_SC & PDB_CONFIG) != PDB_CONFIG //|| PDB0_MOD != PDB_PERIOD //|| PDB0_IDLY != 1 //|| PDB0_CH0C1 != 0x0101) { SIM_SCGC6 |= SIM_SCGC6_PDB; PDB0_IDLY = 1; PDB0_MOD = PDB_PERIOD; PDB0_SC = PDB_CONFIG | PDB_SC_LDOK; PDB0_SC = PDB_CONFIG | PDB_SC_SWTRIG; PDB0_CH0C1 = 0x0101; PDB0_CH1C1 = 0x0101; //} // enable the ADC for hardware trigger and DMA ADC0_SC2 |= ADC_SC2_ADTRG | ADC_SC2_DMAEN; ADC1_SC2 |= ADC_SC2_ADTRG | ADC_SC2_DMAEN; // set up a DMA channel to store the ADC data dma0.begin(true); dma1.begin(true); // ADC0_RA = 0x4003B010 // ADC1_RA = 0x400BB010 dma0.TCD->SADDR = &ADC0_RA; dma0.TCD->SOFF = 0; dma0.TCD->ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1); dma0.TCD->NBYTES_MLNO = 2; dma0.TCD->SLAST = 0; dma0.TCD->DADDR = left_buffer; dma0.TCD->DOFF = 2; dma0.TCD->CITER_ELINKNO = sizeof(left_buffer) / 2; dma0.TCD->DLASTSGA = -sizeof(left_buffer); dma0.TCD->BITER_ELINKNO = sizeof(left_buffer) / 2; dma0.TCD->CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR; dma1.TCD->SADDR = &ADC1_RA; dma1.TCD->SOFF = 0; dma1.TCD->ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1); dma1.TCD->NBYTES_MLNO = 2; dma1.TCD->SLAST = 0; dma1.TCD->DADDR = right_buffer; dma1.TCD->DOFF = 2; dma1.TCD->CITER_ELINKNO = sizeof(right_buffer) / 2; dma1.TCD->DLASTSGA = -sizeof(right_buffer); dma1.TCD->BITER_ELINKNO = sizeof(right_buffer) / 2; dma1.TCD->CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR; dma0.triggerAtHardwareEvent(DMAMUX_SOURCE_ADC0); //dma1.triggerAtHardwareEvent(DMAMUX_SOURCE_ADC1); dma1.triggerAtTransfersOf(dma0); dma1.triggerAtCompletionOf(dma0); update_responsibility = update_setup(); dma0.enable(); dma1.enable(); dma0.attachInterrupt(isr0); dma1.attachInterrupt(isr1); }