Using ADC interrupts in RTOS environment. This program also demonstrates the usage of RTOS API function calls from interrupt.
main.cpp
- Committer:
- cspista
- Date:
- 2022-04-10
- Revision:
- 0:b6055a7af0c9
File content as of revision 0:b6055a7af0c9:
#include "mbed.h"
#include "rtos.h"
AnalogIn adc(A4);
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 ADC1_IRQHandler()
{
NVIC_ClearPendingIRQ(ADC_IRQn); //Clear ADC Interrupt Request Flag
uint16_t raw = ADC1->DR;
queue.put((message_t*)raw); //Send result through a Queue
}
//--- Start conversion, wait for result -----
uint16_t adc_read(uint32_t ch)
{
ADC1->SQR3 = ch; //set conversion channel
ADC1->SMPR2 = 7; //Sample time =480
ADC1->CR1 |= ADC_CR1_EOCIE; //enable interrupt
ADC1->CR2 |= ADC_CR2_SWSTART; //Start conversion
osEvent evt = queue.get(); //Wait for a message
return (uint16_t)evt.value.v; //Return obtained value
}
int main()
{
int32_t v25 = 760; //Voltage at 25C (in millivolts)
float m = 2.5; //Slope mV per degree)
uint16_t dummy = adc.read(); //needed for ADC configuration
ADC123_COMMON->CCR |= ADC_CCR_TSVREFE; //Enable inner channels
NVIC_SetVector(ADC_IRQn,(uint32_t)&ADC1_IRQHandler); //Attach ADC ISR
NVIC_EnableIRQ(ADC_IRQn); //Enable ADC interrupts
Thread thread1(led1_thread);
printf("\r\n Lab09 ADC interrupt in RTOS environment\r\n");
while(true) {
uint32_t a1 = 0;
uint32_t a2 = 0;
for(int i=0; i<3300; i++) {
a1 += adc_read(11); //Measure voltage at A4 (PTC_1)
a2 += adc_read(18); //Internal temperature sensor
}
float v1 = a1/4096.0f; //Convert v1 to millivolts
float temp1 = (v1-500)/10.0; //MCP9700 temperature in Celsius
float v2 = a2/4096.0f; //Convert v2 to millivolts
float temp2 = 25.0f+(v2-v25)/m; //Calculate temp in Celsius
printf("A4 = %.0f mV Temp = %.1f C Inner Ts: %.0f mV Temp = %.1f C\r\n",v1,temp1,v2,temp2);
Thread::wait(2000);
}
}