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:
Wed Nov 18 18:16:43 2015 +0000
Revision:
0:e1a2b02c8441
Child:
1:9a99de9cc5d5
K64F internal ADC channels: bandgap, VREF, temperature sensor

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