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 12:13:06 2015 +0000
Revision:
1:9a99de9cc5d5
Parent:
0:e1a2b02c8441
Child:
2:71d82e4b3777
add average options

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