Usage of ADC interrupt and the inner temperature sensor
Fork of rtos_basic by
main.cpp@8:4d2d1dbbeda5, 2016-03-31 (annotated)
- Committer:
- icserny
- Date:
- Thu Mar 31 14:13:20 2016 +0000
- Revision:
- 8:4d2d1dbbeda5
- Parent:
- 7:84b7291a746d
First version
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
icserny | 8:4d2d1dbbeda5 | 1 | /** 12_rtos_ADCinterrupt |
icserny | 8:4d2d1dbbeda5 | 2 | * Using ADC interrupts and RTOS messaging for non-blockin waitting |
icserny | 8:4d2d1dbbeda5 | 3 | * Meanwhile a LED is blinked... |
icserny | 8:4d2d1dbbeda5 | 4 | * With our adc_read function we can reach extra |
icserny | 8:4d2d1dbbeda5 | 5 | * ADC channels as well, like the internal temperature sensor. |
icserny | 7:84b7291a746d | 6 | * |
icserny | 7:84b7291a746d | 7 | * Hardware requirement: |
icserny | 7:84b7291a746d | 8 | * - FRDM-KL25Z board |
icserny | 8:4d2d1dbbeda5 | 9 | * - Some analog voltage applied to A0 input |
icserny | 7:84b7291a746d | 10 | */ |
icserny | 7:84b7291a746d | 11 | |
emilmont | 1:491820ee784d | 12 | #include "mbed.h" |
emilmont | 1:491820ee784d | 13 | #include "rtos.h" |
icserny | 8:4d2d1dbbeda5 | 14 | AnalogIn adc(A0); |
emilmont | 1:491820ee784d | 15 | DigitalOut led1(LED1); |
icserny | 7:84b7291a746d | 16 | |
icserny | 8:4d2d1dbbeda5 | 17 | typedef uint32_t message_t; |
icserny | 8:4d2d1dbbeda5 | 18 | Queue <message_t, 4> queue; |
icserny | 8:4d2d1dbbeda5 | 19 | |
icserny | 8:4d2d1dbbeda5 | 20 | void led1_thread(void const *args) { |
emilmont | 1:491820ee784d | 21 | while (true) { |
emilmont | 1:491820ee784d | 22 | led1 = !led1; |
icserny | 7:84b7291a746d | 23 | Thread::wait(1000); |
emilmont | 1:491820ee784d | 24 | } |
emilmont | 1:491820ee784d | 25 | } |
icserny | 8:4d2d1dbbeda5 | 26 | |
icserny | 8:4d2d1dbbeda5 | 27 | //--- ADC Interrupt handler ----------------- |
icserny | 8:4d2d1dbbeda5 | 28 | extern "C" void ADC0_IRQHandler() |
icserny | 8:4d2d1dbbeda5 | 29 | { |
icserny | 8:4d2d1dbbeda5 | 30 | NVIC_ClearPendingIRQ(ADC0_IRQn); //Clear ADC Interrupt Request Flag |
icserny | 8:4d2d1dbbeda5 | 31 | uint16_t raw = ADC0->R[0]; |
icserny | 8:4d2d1dbbeda5 | 32 | queue.put((message_t*)raw); //Send result through a Queue |
icserny | 8:4d2d1dbbeda5 | 33 | } |
icserny | 8:4d2d1dbbeda5 | 34 | |
icserny | 8:4d2d1dbbeda5 | 35 | |
icserny | 8:4d2d1dbbeda5 | 36 | uint16_t adc_read(uint32_t ch) { |
icserny | 8:4d2d1dbbeda5 | 37 | ADC0->SC3 = ADC_SC3_AVGE_MASK // Hardware Average Enable |
icserny | 8:4d2d1dbbeda5 | 38 | | ADC_SC3_AVGS(3); // 32 Samples Averaged |
icserny | 8:4d2d1dbbeda5 | 39 | // start conversion |
icserny | 8:4d2d1dbbeda5 | 40 | ADC0->SC1[0] = ADC_SC1_AIEN_MASK | ch; //Set channel, enable interrupt |
icserny | 8:4d2d1dbbeda5 | 41 | osEvent evt = queue.get(); //Wait for a message |
icserny | 8:4d2d1dbbeda5 | 42 | return (uint16_t)evt.value.v; |
icserny | 8:4d2d1dbbeda5 | 43 | } |
icserny | 8:4d2d1dbbeda5 | 44 | |
icserny | 8:4d2d1dbbeda5 | 45 | int main() { |
icserny | 8:4d2d1dbbeda5 | 46 | /* |
icserny | 8:4d2d1dbbeda5 | 47 | * The v25 value is the voltage reading at 25C, it comes from the ADC |
icserny | 8:4d2d1dbbeda5 | 48 | * electricals table in the processor manual. V25 is in millivolts. |
icserny | 8:4d2d1dbbeda5 | 49 | */ |
icserny | 8:4d2d1dbbeda5 | 50 | int32_t v25 = 716; |
icserny | 8:4d2d1dbbeda5 | 51 | |
icserny | 8:4d2d1dbbeda5 | 52 | /* |
icserny | 8:4d2d1dbbeda5 | 53 | * The m value is slope of the temperature sensor values, again from |
icserny | 8:4d2d1dbbeda5 | 54 | * the ADC electricals table in the processor manual. |
icserny | 8:4d2d1dbbeda5 | 55 | * M in microvolts per degree. |
icserny | 8:4d2d1dbbeda5 | 56 | */ |
icserny | 8:4d2d1dbbeda5 | 57 | int32_t m = 1620; |
icserny | 8:4d2d1dbbeda5 | 58 | NVIC_SetVector(ADC0_IRQn, (uint32_t)&ADC0_IRQHandler); //Attach ADC interrupt service routine |
icserny | 8:4d2d1dbbeda5 | 59 | NVIC_EnableIRQ(ADC0_IRQn); //Enable ADC interrupt requests |
icserny | 8:4d2d1dbbeda5 | 60 | Thread thread1(led1_thread); |
icserny | 8:4d2d1dbbeda5 | 61 | |
icserny | 8:4d2d1dbbeda5 | 62 | while (true) { |
icserny | 8:4d2d1dbbeda5 | 63 | uint16_t a1 = adc_read(8); //Measure voltage at A0 (PTB0) |
icserny | 8:4d2d1dbbeda5 | 64 | uint16_t a2 = adc_read(26); //Internal temperature sensor |
icserny | 8:4d2d1dbbeda5 | 65 | float v1 = a1*3.3f/65536; //Convert v1 to Volts |
icserny | 8:4d2d1dbbeda5 | 66 | float v2 = a2*3300.0f/65536; //Convert v2 to millivolts |
icserny | 8:4d2d1dbbeda5 | 67 | float temp = 25.0f-(v2-v25)*1000.0f/m; //Calculate temp in Celsius |
icserny | 8:4d2d1dbbeda5 | 68 | printf("A0 = %6.3f V Temp = %5.2f C\n",v1,temp); |
icserny | 8:4d2d1dbbeda5 | 69 | Thread::wait(2000); |
icserny | 8:4d2d1dbbeda5 | 70 | } |
icserny | 8:4d2d1dbbeda5 | 71 | } |