Usage of ADC interrupt and the inner temperature sensor

Dependencies:   mbed-rtos mbed

Fork of rtos_basic by mbed official

main.cpp

Committer:
icserny
Date:
2016-03-31
Revision:
8:4d2d1dbbeda5
Parent:
7:84b7291a746d

File content as of revision 8:4d2d1dbbeda5:

/** 12_rtos_ADCinterrupt
 * Using ADC interrupts and RTOS messaging for non-blockin waitting
 * Meanwhile a LED is blinked...
 * With our adc_read function we can reach extra 
 * ADC channels as well, like the internal temperature sensor.
 *
 * Hardware requirement:
 *  - FRDM-KL25Z board
 *  - Some analog voltage applied to A0 input
 */

#include "mbed.h"
#include "rtos.h"
AnalogIn adc(A0);
DigitalOut led1(LED1);

typedef uint32_t message_t;
Queue <message_t, 4> queue;

void led1_thread(void const *args) {
    while (true) {
        led1 = !led1;
        Thread::wait(1000);
    }
}

//--- ADC Interrupt handler -----------------
extern "C" void ADC0_IRQHandler()
{
    NVIC_ClearPendingIRQ(ADC0_IRQn);            //Clear ADC Interrupt Request Flag
    uint16_t raw = ADC0->R[0];
    queue.put((message_t*)raw);                 //Send result through a Queue
}


uint16_t adc_read(uint32_t ch) {
    ADC0->SC3 = ADC_SC3_AVGE_MASK               // Hardware Average Enable
              | ADC_SC3_AVGS(3);                // 32 Samples Averaged
    // start conversion
    ADC0->SC1[0] = ADC_SC1_AIEN_MASK | ch;      //Set channel, enable interrupt
    osEvent evt = queue.get();                  //Wait for a message
    return (uint16_t)evt.value.v;
}

int main() {
/*
 * The v25 value is the voltage reading at 25C, it comes from the ADC
 * electricals table in the processor manual. V25 is in millivolts.
 */
    int32_t v25 = 716;

/*
 * The m value is slope of the temperature sensor values, again from
 * the ADC electricals table in the processor manual.
 * M in microvolts per degree.
 */
    int32_t m = 1620;    
    NVIC_SetVector(ADC0_IRQn, (uint32_t)&ADC0_IRQHandler);      //Attach ADC interrupt service routine
    NVIC_EnableIRQ(ADC0_IRQn);                                  //Enable ADC interrupt requests    
    Thread thread1(led1_thread);

    while (true) {
        uint16_t a1 = adc_read(8);                              //Measure voltage at A0 (PTB0)
        uint16_t a2 = adc_read(26);                             //Internal temperature sensor
        float v1 = a1*3.3f/65536;                               //Convert v1 to Volts
        float v2 = a2*3300.0f/65536;                            //Convert v2 to millivolts
        float temp = 25.0f-(v2-v25)*1000.0f/m;                  //Calculate temp in Celsius                     
        printf("A0 = %6.3f V  Temp = %5.2f C\n",v1,temp);
        Thread::wait(2000);
    }
}