Usage of ADC interrupt and the inner temperature sensor
Fork of rtos_basic by
Revision 8:4d2d1dbbeda5, committed 2016-03-31
- Comitter:
- icserny
- Date:
- Thu Mar 31 14:13:20 2016 +0000
- Parent:
- 7:84b7291a746d
- Commit message:
- First version
Changed in this revision
main.cpp | Show annotated file Show diff for this revision Revisions of this file |
diff -r 84b7291a746d -r 4d2d1dbbeda5 main.cpp --- a/main.cpp Thu Jan 28 15:24:41 2016 +0000 +++ b/main.cpp Thu Mar 31 14:13:20 2016 +0000 @@ -1,38 +1,71 @@ -/** 09_rtos_basic - * RTOS LED blinking example running 3 threads - * (main and two additional threads) +/** 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); -DigitalOut led2(LED2); -DigitalOut led3(LED3); - -void led2_thread(void const *args) { - while (true) { - led2 = !led2; - Thread::wait(2000); - } -} -void led3_thread(void const *args) { - while (true) { - led3 = !led3; - Thread::wait(4000); - } -} - -int main() { - Thread thread2(led2_thread); - Thread thread3(led3_thread); - +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); + } +}