demonstrate teensy 3.1 ADC internal channels: temperature sensor and VREF output

Dependencies:   USBDevice mbed

Fork of Teensy_MBED_BLINKY by HM Yoong

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);
     }
 }