2009-12-27 10:50 AM
Using printf to USART in IRQ Handler
2011-05-17 04:35 AM
Hi,
for test purposes I want to send ADC data to Hyperterminal via USART1. The ADC is configured to send the conversion data from 3 channels via DMA to a memory location and then to generate an Interrupt on EOC. The code below show my implementation of the IRQHandler and the __putchar() function. I am using CrossWorks 2.0. The __putchar() implementation works fine when using printf() in the main code. But the printf() call in the IRQ does not produce any output on Hyperterminal. If I set a breakpoint at the printf() call and then step through the rest of the IRQHandler, I sometimes get the output to appear. The ADC is currently triggered every 82ms. The USART1 speed is set at 115200bps. Not sure if this is a timing issue or an issue with the printf implementation. Any help would be greatly appreciated. Thanks, PeterCode:
<BR><BR>/** <BR><BR> * @brief This function handles ADC1 and ADC2 global interrupts requests. <BR><BR> * @param None <BR><BR> * @retval None <BR><BR> */ <BR><BR>void ADC1_2_IRQHandler(void) <BR><BR>{ <BR><BR> float Gyro_XRate, Gyro_YRate, Gyro_Vref; <BR><BR> <BR><BR> /* Disable ADC1 external trigger */ <BR><BR> ADC_ExternalTrigConvCmd(ADC1, DISABLE); <BR><BR> <BR><BR> /* Disable EOC interrupt */ <BR><BR> ADC_ITConfig(ADC1, ADC_IT_EOC, DISABLE); <BR><BR> <BR><BR> /* Increment the conversions counter */ <BR><BR> ADC1Conversions_Number++; <BR><BR> <BR><BR> /* convert ADC values to float */ <BR><BR> Gyro_XRate = (float) ADC1ConvertedValues[0] / ADC_Resolution; <BR><BR> Gyro_YRate = (float) ADC1ConvertedValues[1] / ADC_Resolution; <BR><BR> Gyro_Vref = (float) ADC1ConvertedValues[2] / ADC_Resolution; <BR><BR> <BR><BR> /* write ADC converted values to USART1 */ <BR><BR> printf(''Gyro X, Y Rate & Vref = %6.4f %6.4f %6.4f nr'', Gyro_XRate, Gyro_YRate, Gyro_Vref); <BR><BR> <BR><BR> /* Clear ADC1 EOC pending interrupt bit */ <BR><BR> ADC_ClearITPendingBit(ADC1, ADC_IT_EOC); <BR><BR> <BR><BR> /* Enable ADC1 external trigger */ <BR><BR> ADC_ExternalTrigConvCmd(ADC1, ENABLE); <BR><BR> <BR><BR> /* Enable EOC interrupt */ <BR><BR> ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE); <BR><BR>} <BR><BR>
Code:
<BR><BR>/** <BR><BR> * @brief Defines USART1 output for printf function. <BR><BR> * @param ch: character to output <BR><BR> * @retval EOF if a problem occurs <BR><BR> */ <BR><BR>int __putchar(int ch){ <BR><BR> // <BR><BR> USART_SendData(USART1, ch); <BR><BR> while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); <BR><BR> return NULL; <BR><BR>} <BR><BR>
[ This message was edited by: peter_lanius on 25-12-2009 07:35 ] [ This message was edited by: peter_lanius on 25-12-2009 07:42 ]2011-05-17 04:35 AM
Hi Peter;
It's not recommended to use printf in the interrupt handlers. Your program will stuck in the interrupt routine. I advice you to use it in main using software flags to manage the display. You can also move the computation: ADC1ConvertedValues[X] / ADC_Resolution in main function. So in the interrupt read only the ADC values. B.R. M3allem2011-05-17 04:35 AM
Well, two things may be very important: the printf (or any core function of printf) is non-reentrant on small MCUs, thus cannot be called if another printf in main is active.
Second can be very heavy stack and/or heap activity in this function - do you have your heap configured? Try few kB and see.