K64F internal ADC channels: bandgap, VREF, temperature sensor derived from teensy 3.1 firmware analog.c

Dependencies:   mbed

K64F internal ADC channels: bandgap, VREF, temperature sensor derived from teensy 3.1 firmware analog.c

Committer:
manitou
Date:
Thu Nov 19 17:44:52 2015 +0000
Revision:
2:71d82e4b3777
Parent:
1:9a99de9cc5d5
does temp sensor need internal analog reference?

Who changed what in which revision?

UserRevisionLine numberNew contents of line
manitou 0:e1a2b02c8441 1 // k64f internal ADC channels 3.7.1.3.1
manitou 0:e1a2b02c8441 2 // temp sensor ADC0 26 slope 1.62mv/C 716mv @25C
manitou 0:e1a2b02c8441 3 // bandgap ADC0 27 1.0v
manitou 0:e1a2b02c8441 4 // VREFout ADC1 18 1.195v
manitou 1:9a99de9cc5d5 5 // DAC0 ADC1 23
manitou 0:e1a2b02c8441 6 // ADC1 SIM_SCGC3 ADC0 SIM_SCGC6
manitou 0:e1a2b02c8441 7 // A0 PTB2 ADC0 channel 12
manitou 0:e1a2b02c8441 8 #include "mbed.h"
manitou 0:e1a2b02c8441 9
manitou 0:e1a2b02c8441 10 #define PRREG(z) printf(#z" 0x%x\n",z)
manitou 0:e1a2b02c8441 11 //AnalogIn adc(A0);
manitou 2:71d82e4b3777 12 AnalogOut dac(DAC0_OUT);
manitou 0:e1a2b02c8441 13 Timer tmr;
manitou 0:e1a2b02c8441 14 static uint32_t t;
manitou 0:e1a2b02c8441 15
manitou 0:e1a2b02c8441 16 // based on teensy3.1 firmware analog.c
manitou 0:e1a2b02c8441 17 // 60mhz bus
manitou 0:e1a2b02c8441 18 #define ADC_CFG1_16BIT BF_ADC_CFG1_ADIV(2) + BF_ADC_CFG1_ADICLK(1) // 7.5 MHz
manitou 0:e1a2b02c8441 19 #define ADC_CFG1_12BIT BF_ADC_CFG1_ADIV(1) + BF_ADC_CFG1_ADICLK(1) // 15 MHz
manitou 0:e1a2b02c8441 20 #define ADC_CFG1_10BIT BF_ADC_CFG1_ADIV(1) + BF_ADC_CFG1_ADICLK(1) // 15 MHz
manitou 0:e1a2b02c8441 21 #define ADC_CFG1_8BIT BF_ADC_CFG1_ADIV(1) + BF_ADC_CFG1_ADICLK(1) // 15 MHz
manitou 0:e1a2b02c8441 22
manitou 0:e1a2b02c8441 23 static uint8_t analog_config_bits = 12; // 8 10 12 16 bit ADC
manitou 1:9a99de9cc5d5 24 static uint8_t analog_num_average = 4; // 0 4 8 16 32
manitou 0:e1a2b02c8441 25 static uint8_t analog_reference_internal = 0;
manitou 0:e1a2b02c8441 26
manitou 0:e1a2b02c8441 27 static void adc_init() {
manitou 0:e1a2b02c8441 28 SIM_SCGC6 |= SIM_SCGC6_ADC0_MASK; // start ADC peripherals
manitou 0:e1a2b02c8441 29 SIM_SCGC3 |= SIM_SCGC3_ADC1_MASK;
manitou 0:e1a2b02c8441 30 VREF_TRM = 0x60;
manitou 0:e1a2b02c8441 31 VREF_SC = 0xE1; // enable 1.2 volt ref
manitou 0:e1a2b02c8441 32 PMC_REGSC |= PMC_REGSC_BGBE_MASK; // enable bandgap
manitou 1:9a99de9cc5d5 33
manitou 1:9a99de9cc5d5 34 // would need to do GPIO init for external pins
manitou 0:e1a2b02c8441 35
manitou 0:e1a2b02c8441 36 if (analog_config_bits == 8) {
manitou 0:e1a2b02c8441 37 ADC0_CFG1 = ADC_CFG1_8BIT + BF_ADC_CFG1_MODE(0);
manitou 0:e1a2b02c8441 38 ADC0_CFG2 = ADC_CFG2_MUXSEL_MASK + BF_ADC_CFG2_ADLSTS(3);
manitou 0:e1a2b02c8441 39 ADC1_CFG1 = ADC_CFG1_8BIT + BF_ADC_CFG1_MODE(0);
manitou 0:e1a2b02c8441 40 ADC1_CFG2 = ADC_CFG2_MUXSEL_MASK + BF_ADC_CFG2_ADLSTS(3);
manitou 0:e1a2b02c8441 41 } else if (analog_config_bits == 10) {
manitou 0:e1a2b02c8441 42 ADC0_CFG1 = ADC_CFG1_10BIT + BF_ADC_CFG1_MODE(2) + ADC_CFG1_ADLSMP_MASK;
manitou 0:e1a2b02c8441 43 ADC0_CFG2 = ADC_CFG2_MUXSEL_MASK + BF_ADC_CFG2_ADLSTS(3);
manitou 0:e1a2b02c8441 44 ADC1_CFG1 = ADC_CFG1_10BIT + BF_ADC_CFG1_MODE(2) + ADC_CFG1_ADLSMP_MASK;
manitou 0:e1a2b02c8441 45 ADC1_CFG2 = ADC_CFG2_MUXSEL_MASK + BF_ADC_CFG2_ADLSTS(3);
manitou 0:e1a2b02c8441 46 } else if (analog_config_bits == 12) {
manitou 0:e1a2b02c8441 47 ADC0_CFG1 = ADC_CFG1_12BIT + BF_ADC_CFG1_MODE(1) + ADC_CFG1_ADLSMP_MASK;
manitou 0:e1a2b02c8441 48 ADC0_CFG2 = ADC_CFG2_MUXSEL_MASK + BF_ADC_CFG2_ADLSTS(2);
manitou 0:e1a2b02c8441 49 ADC1_CFG1 = ADC_CFG1_12BIT + BF_ADC_CFG1_MODE(1) + ADC_CFG1_ADLSMP_MASK;
manitou 0:e1a2b02c8441 50 ADC1_CFG2 = ADC_CFG2_MUXSEL_MASK + BF_ADC_CFG2_ADLSTS(2);
manitou 0:e1a2b02c8441 51 } else {
manitou 0:e1a2b02c8441 52 ADC0_CFG1 = ADC_CFG1_16BIT + BF_ADC_CFG1_MODE(3) + ADC_CFG1_ADLSMP_MASK;
manitou 0:e1a2b02c8441 53 ADC0_CFG2 = ADC_CFG2_MUXSEL_MASK + BF_ADC_CFG2_ADLSTS(2);
manitou 0:e1a2b02c8441 54 ADC1_CFG1 = ADC_CFG1_16BIT + BF_ADC_CFG1_MODE(3) + ADC_CFG1_ADLSMP_MASK;
manitou 0:e1a2b02c8441 55 ADC1_CFG2 = ADC_CFG2_MUXSEL_MASK + BF_ADC_CFG2_ADLSTS(2);
manitou 0:e1a2b02c8441 56 }
manitou 0:e1a2b02c8441 57
manitou 0:e1a2b02c8441 58 if (analog_reference_internal) {
manitou 0:e1a2b02c8441 59 ADC0_SC2 = BF_ADC_SC2_REFSEL(1); // 1.2V ref
manitou 0:e1a2b02c8441 60 ADC1_SC2 = BF_ADC_SC2_REFSEL(1); // 1.2V ref
manitou 0:e1a2b02c8441 61 } else {
manitou 0:e1a2b02c8441 62 ADC0_SC2 = BF_ADC_SC2_REFSEL(0); // vcc/ext ref
manitou 0:e1a2b02c8441 63 ADC1_SC2 = BF_ADC_SC2_REFSEL(0); // vcc/ext ref
manitou 0:e1a2b02c8441 64 }
manitou 0:e1a2b02c8441 65 // calibrate ADCs
manitou 0:e1a2b02c8441 66 t=tmr.read_us();
manitou 1:9a99de9cc5d5 67 if (analog_num_average <=1) {
manitou 1:9a99de9cc5d5 68 ADC0_SC3 = ADC_SC3_CAL_MASK; // no averaging
manitou 1:9a99de9cc5d5 69 ADC1_SC3 = ADC_SC3_CAL_MASK;
manitou 1:9a99de9cc5d5 70 } else if (analog_num_average <=4) {
manitou 1:9a99de9cc5d5 71 ADC0_SC3 = ADC_SC3_CAL_MASK + ADC_SC3_AVGE_MASK + BF_ADC_SC3_AVGS(0); // average 4
manitou 1:9a99de9cc5d5 72 ADC1_SC3 = ADC_SC3_CAL_MASK + ADC_SC3_AVGE_MASK + BF_ADC_SC3_AVGS(0);
manitou 1:9a99de9cc5d5 73 } else if (analog_num_average <=8) {
manitou 1:9a99de9cc5d5 74 ADC0_SC3 = ADC_SC3_CAL_MASK + ADC_SC3_AVGE_MASK + BF_ADC_SC3_AVGS(1);
manitou 1:9a99de9cc5d5 75 ADC1_SC3 = ADC_SC3_CAL_MASK + ADC_SC3_AVGE_MASK + BF_ADC_SC3_AVGS(1);
manitou 1:9a99de9cc5d5 76 } else if (analog_num_average <=16) {
manitou 1:9a99de9cc5d5 77 ADC0_SC3 = ADC_SC3_CAL_MASK + ADC_SC3_AVGE_MASK + BF_ADC_SC3_AVGS(2);
manitou 1:9a99de9cc5d5 78 ADC1_SC3 = ADC_SC3_CAL_MASK + ADC_SC3_AVGE_MASK + BF_ADC_SC3_AVGS(2);
manitou 1:9a99de9cc5d5 79 } else {
manitou 1:9a99de9cc5d5 80 ADC0_SC3 = ADC_SC3_CAL_MASK + ADC_SC3_AVGE_MASK + BF_ADC_SC3_AVGS(3);
manitou 1:9a99de9cc5d5 81 ADC1_SC3 = ADC_SC3_CAL_MASK + ADC_SC3_AVGE_MASK + BF_ADC_SC3_AVGS(3);
manitou 1:9a99de9cc5d5 82 }
manitou 0:e1a2b02c8441 83 uint16_t sum;
manitou 0:e1a2b02c8441 84
manitou 0:e1a2b02c8441 85 while ((ADC0_SC3 & ADC_SC3_CAL_MASK) || (ADC1_SC3 & ADC_SC3_CAL_MASK)) ; // wait
manitou 0:e1a2b02c8441 86
manitou 0:e1a2b02c8441 87 __disable_irq();
manitou 0:e1a2b02c8441 88
manitou 0:e1a2b02c8441 89 sum = ADC0_CLPS + ADC0_CLP4 + ADC0_CLP3 + ADC0_CLP2 + ADC0_CLP1 + ADC0_CLP0;
manitou 0:e1a2b02c8441 90 sum = (sum / 2) | 0x8000;
manitou 0:e1a2b02c8441 91 ADC0_PG = sum;
manitou 0:e1a2b02c8441 92 sum = ADC0_CLMS + ADC0_CLM4 + ADC0_CLM3 + ADC0_CLM2 + ADC0_CLM1 + ADC0_CLM0;
manitou 0:e1a2b02c8441 93 sum = (sum / 2) | 0x8000;
manitou 0:e1a2b02c8441 94 ADC0_MG = sum;
manitou 0:e1a2b02c8441 95 sum = ADC1_CLPS + ADC1_CLP4 + ADC1_CLP3 + ADC1_CLP2 + ADC1_CLP1 + ADC1_CLP0;
manitou 0:e1a2b02c8441 96 sum = (sum / 2) | 0x8000;
manitou 0:e1a2b02c8441 97 ADC1_PG = sum;
manitou 0:e1a2b02c8441 98 sum = ADC1_CLMS + ADC1_CLM4 + ADC1_CLM3 + ADC1_CLM2 + ADC1_CLM1 + ADC1_CLM0;
manitou 0:e1a2b02c8441 99 sum = (sum / 2) | 0x8000;
manitou 0:e1a2b02c8441 100 ADC1_MG = sum;
manitou 0:e1a2b02c8441 101
manitou 0:e1a2b02c8441 102 __enable_irq();
manitou 0:e1a2b02c8441 103 t=tmr.read_us()-t;
manitou 0:e1a2b02c8441 104 }
manitou 0:e1a2b02c8441 105
manitou 0:e1a2b02c8441 106 static uint16_t adc_read(ADC_Type * ADCx, int channel) {
manitou 0:e1a2b02c8441 107 ADCx->SC1[0] = channel;
manitou 0:e1a2b02c8441 108 while(!(ADCx->SC1[0] & ADC_SC1_COCO_MASK)); // wait
manitou 0:e1a2b02c8441 109 return ADCx->R[0];
manitou 0:e1a2b02c8441 110 }
manitou 0:e1a2b02c8441 111
manitou 0:e1a2b02c8441 112 int main()
manitou 0:e1a2b02c8441 113 {
manitou 0:e1a2b02c8441 114 int ADCmax = 1 << analog_config_bits;
manitou 0:e1a2b02c8441 115 int val, i;
manitou 0:e1a2b02c8441 116 float Vcc, tempc, slope=ADCmax*0.76/3.3, val25=ADCmax*.0025/3.3;
manitou 0:e1a2b02c8441 117
manitou 0:e1a2b02c8441 118 printf("\nSystemCoreClock %d %s %s\n",SystemCoreClock,__TIME__,__DATE__);
manitou 0:e1a2b02c8441 119 tmr.start();
manitou 0:e1a2b02c8441 120 adc_init();
manitou 2:71d82e4b3777 121 dac.write(0.5); // 3.3/2 jumper to A0 and read internal
manitou 1:9a99de9cc5d5 122
manitou 0:e1a2b02c8441 123 PRREG(SIM_SCGC6);
manitou 0:e1a2b02c8441 124 PRREG(SIM_SCGC3);
manitou 0:e1a2b02c8441 125 PRREG(VREF->TRM);
manitou 0:e1a2b02c8441 126 PRREG(VREF_SC);
manitou 0:e1a2b02c8441 127 PRREG(PMC_REGSC);
manitou 0:e1a2b02c8441 128 PRREG(ADC0->SC1[0]); // or ADC0_SCA
manitou 0:e1a2b02c8441 129 PRREG(ADC0->SC1[1]);
manitou 0:e1a2b02c8441 130 PRREG(ADC0->CFG1);
manitou 0:e1a2b02c8441 131 PRREG(ADC0_CFG2);
manitou 0:e1a2b02c8441 132 PRREG(ADC0->SC2);
manitou 0:e1a2b02c8441 133 PRREG(ADC0->SC3);
manitou 2:71d82e4b3777 134 PRREG(ADC1->SC1[0]); // ADC1
manitou 2:71d82e4b3777 135 PRREG(ADC1->SC1[1]);
manitou 2:71d82e4b3777 136 PRREG(ADC1->CFG1);
manitou 2:71d82e4b3777 137 PRREG(ADC1_CFG2);
manitou 2:71d82e4b3777 138 PRREG(ADC1->SC2);
manitou 2:71d82e4b3777 139 PRREG(ADC1->SC3);
manitou 2:71d82e4b3777 140
manitou 1:9a99de9cc5d5 141 printf("res %d average %d calibration %d us\n",analog_config_bits,analog_num_average,t);
manitou 0:e1a2b02c8441 142 val = adc_read(ADC1,18); // VREF OUT
manitou 0:e1a2b02c8441 143 Vcc = ADCmax*1.195/val;
manitou 0:e1a2b02c8441 144 printf("VREF val %d %.2f v\n",val,Vcc);
manitou 0:e1a2b02c8441 145 val = adc_read(ADC0,27); // bandgap
manitou 0:e1a2b02c8441 146 Vcc = ADCmax*1.0/val;
manitou 0:e1a2b02c8441 147 printf("bandgap val %d %.2f v\n",val,Vcc);
manitou 2:71d82e4b3777 148 val = adc_read(ADC0,12); // didn't do GPIO init for A0
manitou 2:71d82e4b3777 149 printf("A0 val %d %.2f v\n",val,3.3*val/ADCmax);
manitou 2:71d82e4b3777 150 val = adc_read(ADC1,23); // DAC to internal ADC
manitou 2:71d82e4b3777 151 printf("DAC val %d %.2f v\n",val,3.3*val/ADCmax);
manitou 0:e1a2b02c8441 152 t=tmr.read_us();
manitou 0:e1a2b02c8441 153 for(i=0;i<1000;i++) adc_read(ADC0,12);
manitou 0:e1a2b02c8441 154 t=tmr.read_us()-t;
manitou 0:e1a2b02c8441 155 printf("avrg A0 read %d us\n",t/1000);
manitou 2:71d82e4b3777 156 // need internal VREF for temp sensor ?? TODO
manitou 2:71d82e4b3777 157 analog_reference_internal = 1;
manitou 2:71d82e4b3777 158 adc_init(); // re init and calibrate
manitou 2:71d82e4b3777 159 val = adc_read(ADC0,26); // temp sensor
manitou 2:71d82e4b3777 160 tempc = ((val-val25)/slope) + 25.f;
manitou 2:71d82e4b3777 161 printf("temp val %d %.1f C\n",val,tempc);
manitou 0:e1a2b02c8441 162 }