K64F internal ADC channels: bandgap, VREF, temperature sensor derived from teensy 3.1 firmware analog.c
K64F internal ADC channels: bandgap, VREF, temperature sensor derived from teensy 3.1 firmware analog.c
main.cpp
- Committer:
- manitou
- Date:
- 2015-11-19
- Revision:
- 2:71d82e4b3777
- Parent:
- 1:9a99de9cc5d5
File content as of revision 2:71d82e4b3777:
// k64f internal ADC channels 3.7.1.3.1 // temp sensor ADC0 26 slope 1.62mv/C 716mv @25C // bandgap ADC0 27 1.0v // VREFout ADC1 18 1.195v // DAC0 ADC1 23 // ADC1 SIM_SCGC3 ADC0 SIM_SCGC6 // A0 PTB2 ADC0 channel 12 #include "mbed.h" #define PRREG(z) printf(#z" 0x%x\n",z) //AnalogIn adc(A0); AnalogOut dac(DAC0_OUT); Timer tmr; static uint32_t t; // based on teensy3.1 firmware analog.c // 60mhz bus #define ADC_CFG1_16BIT BF_ADC_CFG1_ADIV(2) + BF_ADC_CFG1_ADICLK(1) // 7.5 MHz #define ADC_CFG1_12BIT BF_ADC_CFG1_ADIV(1) + BF_ADC_CFG1_ADICLK(1) // 15 MHz #define ADC_CFG1_10BIT BF_ADC_CFG1_ADIV(1) + BF_ADC_CFG1_ADICLK(1) // 15 MHz #define ADC_CFG1_8BIT BF_ADC_CFG1_ADIV(1) + BF_ADC_CFG1_ADICLK(1) // 15 MHz static uint8_t analog_config_bits = 12; // 8 10 12 16 bit ADC static uint8_t analog_num_average = 4; // 0 4 8 16 32 static uint8_t analog_reference_internal = 0; static void adc_init() { SIM_SCGC6 |= SIM_SCGC6_ADC0_MASK; // start ADC peripherals SIM_SCGC3 |= SIM_SCGC3_ADC1_MASK; VREF_TRM = 0x60; VREF_SC = 0xE1; // enable 1.2 volt ref PMC_REGSC |= PMC_REGSC_BGBE_MASK; // enable bandgap // would need to do GPIO init for external pins if (analog_config_bits == 8) { ADC0_CFG1 = ADC_CFG1_8BIT + BF_ADC_CFG1_MODE(0); ADC0_CFG2 = ADC_CFG2_MUXSEL_MASK + BF_ADC_CFG2_ADLSTS(3); ADC1_CFG1 = ADC_CFG1_8BIT + BF_ADC_CFG1_MODE(0); ADC1_CFG2 = ADC_CFG2_MUXSEL_MASK + BF_ADC_CFG2_ADLSTS(3); } else if (analog_config_bits == 10) { ADC0_CFG1 = ADC_CFG1_10BIT + BF_ADC_CFG1_MODE(2) + ADC_CFG1_ADLSMP_MASK; ADC0_CFG2 = ADC_CFG2_MUXSEL_MASK + BF_ADC_CFG2_ADLSTS(3); ADC1_CFG1 = ADC_CFG1_10BIT + BF_ADC_CFG1_MODE(2) + ADC_CFG1_ADLSMP_MASK; ADC1_CFG2 = ADC_CFG2_MUXSEL_MASK + BF_ADC_CFG2_ADLSTS(3); } else if (analog_config_bits == 12) { ADC0_CFG1 = ADC_CFG1_12BIT + BF_ADC_CFG1_MODE(1) + ADC_CFG1_ADLSMP_MASK; ADC0_CFG2 = ADC_CFG2_MUXSEL_MASK + BF_ADC_CFG2_ADLSTS(2); ADC1_CFG1 = ADC_CFG1_12BIT + BF_ADC_CFG1_MODE(1) + ADC_CFG1_ADLSMP_MASK; ADC1_CFG2 = ADC_CFG2_MUXSEL_MASK + BF_ADC_CFG2_ADLSTS(2); } else { ADC0_CFG1 = ADC_CFG1_16BIT + BF_ADC_CFG1_MODE(3) + ADC_CFG1_ADLSMP_MASK; ADC0_CFG2 = ADC_CFG2_MUXSEL_MASK + BF_ADC_CFG2_ADLSTS(2); ADC1_CFG1 = ADC_CFG1_16BIT + BF_ADC_CFG1_MODE(3) + ADC_CFG1_ADLSMP_MASK; ADC1_CFG2 = ADC_CFG2_MUXSEL_MASK + BF_ADC_CFG2_ADLSTS(2); } if (analog_reference_internal) { ADC0_SC2 = BF_ADC_SC2_REFSEL(1); // 1.2V ref ADC1_SC2 = BF_ADC_SC2_REFSEL(1); // 1.2V ref } else { ADC0_SC2 = BF_ADC_SC2_REFSEL(0); // vcc/ext ref ADC1_SC2 = BF_ADC_SC2_REFSEL(0); // vcc/ext ref } // calibrate ADCs t=tmr.read_us(); if (analog_num_average <=1) { ADC0_SC3 = ADC_SC3_CAL_MASK; // no averaging ADC1_SC3 = ADC_SC3_CAL_MASK; } else if (analog_num_average <=4) { ADC0_SC3 = ADC_SC3_CAL_MASK + ADC_SC3_AVGE_MASK + BF_ADC_SC3_AVGS(0); // average 4 ADC1_SC3 = ADC_SC3_CAL_MASK + ADC_SC3_AVGE_MASK + BF_ADC_SC3_AVGS(0); } else if (analog_num_average <=8) { ADC0_SC3 = ADC_SC3_CAL_MASK + ADC_SC3_AVGE_MASK + BF_ADC_SC3_AVGS(1); ADC1_SC3 = ADC_SC3_CAL_MASK + ADC_SC3_AVGE_MASK + BF_ADC_SC3_AVGS(1); } else if (analog_num_average <=16) { ADC0_SC3 = ADC_SC3_CAL_MASK + ADC_SC3_AVGE_MASK + BF_ADC_SC3_AVGS(2); ADC1_SC3 = ADC_SC3_CAL_MASK + ADC_SC3_AVGE_MASK + BF_ADC_SC3_AVGS(2); } else { ADC0_SC3 = ADC_SC3_CAL_MASK + ADC_SC3_AVGE_MASK + BF_ADC_SC3_AVGS(3); ADC1_SC3 = ADC_SC3_CAL_MASK + ADC_SC3_AVGE_MASK + BF_ADC_SC3_AVGS(3); } uint16_t sum; while ((ADC0_SC3 & ADC_SC3_CAL_MASK) || (ADC1_SC3 & ADC_SC3_CAL_MASK)) ; // wait __disable_irq(); sum = ADC0_CLPS + ADC0_CLP4 + ADC0_CLP3 + ADC0_CLP2 + ADC0_CLP1 + ADC0_CLP0; sum = (sum / 2) | 0x8000; ADC0_PG = sum; sum = ADC0_CLMS + ADC0_CLM4 + ADC0_CLM3 + ADC0_CLM2 + ADC0_CLM1 + ADC0_CLM0; sum = (sum / 2) | 0x8000; ADC0_MG = sum; sum = ADC1_CLPS + ADC1_CLP4 + ADC1_CLP3 + ADC1_CLP2 + ADC1_CLP1 + ADC1_CLP0; sum = (sum / 2) | 0x8000; ADC1_PG = sum; sum = ADC1_CLMS + ADC1_CLM4 + ADC1_CLM3 + ADC1_CLM2 + ADC1_CLM1 + ADC1_CLM0; sum = (sum / 2) | 0x8000; ADC1_MG = sum; __enable_irq(); t=tmr.read_us()-t; } static uint16_t adc_read(ADC_Type * ADCx, int channel) { ADCx->SC1[0] = channel; while(!(ADCx->SC1[0] & ADC_SC1_COCO_MASK)); // wait return ADCx->R[0]; } int main() { int ADCmax = 1 << analog_config_bits; int val, i; float Vcc, tempc, slope=ADCmax*0.76/3.3, val25=ADCmax*.0025/3.3; printf("\nSystemCoreClock %d %s %s\n",SystemCoreClock,__TIME__,__DATE__); tmr.start(); adc_init(); dac.write(0.5); // 3.3/2 jumper to A0 and read internal PRREG(SIM_SCGC6); PRREG(SIM_SCGC3); PRREG(VREF->TRM); PRREG(VREF_SC); PRREG(PMC_REGSC); PRREG(ADC0->SC1[0]); // or ADC0_SCA PRREG(ADC0->SC1[1]); PRREG(ADC0->CFG1); PRREG(ADC0_CFG2); PRREG(ADC0->SC2); PRREG(ADC0->SC3); PRREG(ADC1->SC1[0]); // ADC1 PRREG(ADC1->SC1[1]); PRREG(ADC1->CFG1); PRREG(ADC1_CFG2); PRREG(ADC1->SC2); PRREG(ADC1->SC3); printf("res %d average %d calibration %d us\n",analog_config_bits,analog_num_average,t); val = adc_read(ADC1,18); // VREF OUT Vcc = ADCmax*1.195/val; printf("VREF val %d %.2f v\n",val,Vcc); val = adc_read(ADC0,27); // bandgap Vcc = ADCmax*1.0/val; printf("bandgap val %d %.2f v\n",val,Vcc); val = adc_read(ADC0,12); // didn't do GPIO init for A0 printf("A0 val %d %.2f v\n",val,3.3*val/ADCmax); val = adc_read(ADC1,23); // DAC to internal ADC printf("DAC val %d %.2f v\n",val,3.3*val/ADCmax); t=tmr.read_us(); for(i=0;i<1000;i++) adc_read(ADC0,12); t=tmr.read_us()-t; printf("avrg A0 read %d us\n",t/1000); // need internal VREF for temp sensor ?? TODO analog_reference_internal = 1; adc_init(); // re init and calibrate val = adc_read(ADC0,26); // temp sensor tempc = ((val-val25)/slope) + 25.f; printf("temp val %d %.1f C\n",val,tempc); }