demonstrate teensy 3.1 ADC internal channels: temperature sensor and VREF output
Fork of Teensy_MBED_BLINKY by
Diff: main.cpp
- Revision:
- 2:5b51fe85e931
- Parent:
- 1:e452bc59d245
diff -r e452bc59d245 -r 5b51fe85e931 main.cpp --- a/main.cpp Sun Jul 26 01:40:06 2015 +0000 +++ b/main.cpp Fri Oct 02 16:09:35 2015 +0000 @@ -1,20 +1,125 @@ -// MBED_BLINKY with Teensy 3.1 - -// You need to update the latest USBDevice library - +// Teensy 3.1 internal ADC temperature VREF +// analog resolution 16-bits #include "mbed.h" #include "USBSerial.h" +#include "clk_freqs.h" -DigitalOut myled(LED1); // Onboard LED +#define DEFAULT 0 +#define INTERNAL 2 +#define INTERNAL1V2 2 +#define INTERNAL1V1 2 +#define EXTERNAL 0 + +// for teensy 3.1 temp sensor on ADC0 channel 26, vref output on ADC1 channel 18 GC3 +#define ADC_TEMP 26 +#define ADC_VREF 18 + +#define PRREG(x) pc.printf(#x" %0x\n",x) + USBSerial pc; // Virtual serial port over USB - - + +#define MAX_FADC 6000000 +#define ADC1 ((ADC_Type *)0x400BB000u) + +void adc_init(){ + VREF->TRM = 0x60; // from teensy enable vref + VREF->SC = 0xE1; + + // enable ADC0 and ADC1 + SIM->SCGC6 |= SIM_SCGC6_ADC0_MASK; + SIM->SCGC3 |= SIM_SCGC3_ADC1_MASK; + + // bus clk + uint32_t PCLK = bus_frequency(); + uint32_t clkdiv; + for (clkdiv = 0; clkdiv < 4; clkdiv++) { + if ((PCLK >> clkdiv) <= MAX_FADC) + break; + } + if (clkdiv == 4) //Set max div + clkdiv = 0x7; + + // ADC0->SC1[1] = ADC_SC1_ADCH(obj->adc); + + ADC0->CFG1 = ADC_CFG1_ADLPC_MASK // Low-Power Configuration + | ADC_CFG1_ADIV(clkdiv & 0x3) // Clock Divide Select + | ADC_CFG1_ADLSMP_MASK // Long Sample Time + | ADC_CFG1_MODE(3) // (16)bits Resolution + | ADC_CFG1_ADICLK(clkdiv >> 2); // Input Clock + + ADC0->CFG2 = ADC_CFG2_MUXSEL_MASK // ADxxb or ADxxa channels + | ADC_CFG2_ADHSC_MASK // High-Speed Configuration + | ADC_CFG2_ADLSTS(0); // Long Sample Time Select + + ADC0->SC2 = ADC_SC2_REFSEL(0); // Default Voltage Reference + + ADC0->SC3 = ADC_SC3_AVGE_MASK // Hardware Average Enable + | ADC_SC3_AVGS(0); // 4 Samples Averaged +// ADC1 + ADC1->CFG1 = ADC_CFG1_ADLPC_MASK // Low-Power Configuration + | ADC_CFG1_ADIV(clkdiv & 0x3) // Clock Divide Select + | ADC_CFG1_ADLSMP_MASK // Long Sample Time + | ADC_CFG1_MODE(3) // (16)bits Resolution + | ADC_CFG1_ADICLK(clkdiv >> 2); // Input Clock + + ADC1->CFG2 = ADC_CFG2_MUXSEL_MASK // ADxxb or ADxxa channels + | ADC_CFG2_ADHSC_MASK // High-Speed Configuration + | ADC_CFG2_ADLSTS(0); // Long Sample Time Select + + ADC1->SC2 = ADC_SC2_REFSEL(0); // Default Voltage Reference + + ADC1->SC3 = ADC_SC3_AVGE_MASK // Hardware Average Enable + | ADC_SC3_AVGS(0); // 4 Samples Averaged +} + + +uint16_t adc0_read(int channel) { + // start conversion + ADC0->SC1[0] = ADC_SC1_ADCH(channel); + + // Wait Conversion Complete + while ((ADC0->SC1[0] & ADC_SC1_COCO_MASK) != ADC_SC1_COCO_MASK); + + return (uint16_t)ADC0->R[0]; +} + +uint16_t adc1_read(int channel) { + // start conversion + ADC1->SC1[0] = ADC_SC1_ADCH(channel); + + // Wait Conversion Complete + while ((ADC1->SC1[0] & ADC_SC1_COCO_MASK) != ADC_SC1_COCO_MASK); + + return (uint16_t)ADC1->R[0]; +} + +void adc0_ref(int ref){ + ADC0->SC2 = ADC_SC2_REFSEL(ref); + adc0_read(0); // discard a reading after ref change +} + int main() { + double c, v; while(1) { - pc.printf("Hello World\r\n"); - myled = 1; - wait(0.2); - myled = 0; - wait(0.2); + uint16_t val; + pc.printf("SystemCoreClock %d %s %s\n",SystemCoreClock,__TIME__,__DATE__); + PRREG(SIM->CLKDIV1); + PRREG(SIM->CLKDIV2); + + PRREG(SIM->SCGC2); //ref 12.2 + PRREG(SIM->SCGC3); + PRREG(SIM->SCGC4); + PRREG(SIM->SCGC5); + PRREG(SIM->SCGC6); + PRREG(SIM->SCGC7); + adc_init(); + val = adc0_read(ADC_TEMP); + c= -0.02432*val + 371; // may need to calibrate for your chip + pc.printf("val %d %.1f C\n",val,c); + + val = adc1_read(ADC_VREF); + v = 1.195*65536/val; // datasheet says internal vref is 1.195v + pc.printf("val %d Vcc %.3f\n",val,v); + wait(3.0); } }