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@0:e1a2b02c8441, 2015-11-18 (annotated)
- 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?
User | Revision | Line number | New 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 | } |