Usage of ADC interrupt and the inner temperature sensor

Dependencies:   mbed-rtos mbed

Fork of rtos_basic by mbed official

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /** 12_rtos_ADCinterrupt
00002  * Using ADC interrupts and RTOS messaging for non-blockin waitting
00003  * Meanwhile a LED is blinked...
00004  * With our adc_read function we can reach extra 
00005  * ADC channels as well, like the internal temperature sensor.
00006  *
00007  * Hardware requirement:
00008  *  - FRDM-KL25Z board
00009  *  - Some analog voltage applied to A0 input
00010  */
00011 
00012 #include "mbed.h"
00013 #include "rtos.h"
00014 AnalogIn adc(A0);
00015 DigitalOut led1(LED1);
00016 
00017 typedef uint32_t message_t;
00018 Queue <message_t, 4> queue;
00019 
00020 void led1_thread(void const *args) {
00021     while (true) {
00022         led1 = !led1;
00023         Thread::wait(1000);
00024     }
00025 }
00026 
00027 //--- ADC Interrupt handler -----------------
00028 extern "C" void ADC0_IRQHandler()
00029 {
00030     NVIC_ClearPendingIRQ(ADC0_IRQn);            //Clear ADC Interrupt Request Flag
00031     uint16_t raw = ADC0->R[0];
00032     queue.put((message_t*)raw);                 //Send result through a Queue
00033 }
00034 
00035 
00036 uint16_t adc_read(uint32_t ch) {
00037     ADC0->SC3 = ADC_SC3_AVGE_MASK               // Hardware Average Enable
00038               | ADC_SC3_AVGS(3);                // 32 Samples Averaged
00039     // start conversion
00040     ADC0->SC1[0] = ADC_SC1_AIEN_MASK | ch;      //Set channel, enable interrupt
00041     osEvent evt = queue.get();                  //Wait for a message
00042     return (uint16_t)evt.value.v;
00043 }
00044 
00045 int main() {
00046 /*
00047  * The v25 value is the voltage reading at 25C, it comes from the ADC
00048  * electricals table in the processor manual. V25 is in millivolts.
00049  */
00050     int32_t v25 = 716;
00051 
00052 /*
00053  * The m value is slope of the temperature sensor values, again from
00054  * the ADC electricals table in the processor manual.
00055  * M in microvolts per degree.
00056  */
00057     int32_t m = 1620;    
00058     NVIC_SetVector(ADC0_IRQn, (uint32_t)&ADC0_IRQHandler);      //Attach ADC interrupt service routine
00059     NVIC_EnableIRQ(ADC0_IRQn);                                  //Enable ADC interrupt requests    
00060     Thread thread1(led1_thread);
00061 
00062     while (true) {
00063         uint16_t a1 = adc_read(8);                              //Measure voltage at A0 (PTB0)
00064         uint16_t a2 = adc_read(26);                             //Internal temperature sensor
00065         float v1 = a1*3.3f/65536;                               //Convert v1 to Volts
00066         float v2 = a2*3300.0f/65536;                            //Convert v2 to millivolts
00067         float temp = 25.0f-(v2-v25)*1000.0f/m;                  //Calculate temp in Celsius                     
00068         printf("A0 = %6.3f V  Temp = %5.2f C\n",v1,temp);
00069         Thread::wait(2000);
00070     }
00071 }