cancel
Showing results for 
Search instead for 
Did you mean: 

Variable-size Rx on UART using Interrupts

dbegun
Associate II
Posted on August 18, 2014 at 18:19

I need to implement the reception of messages on UART using interrupt and the HAL set of drivers. Messages can be of varied length, but they have a terminating character. My problem is that HAL_UART_Receive_IT() takes a parameter ''size'', and the Rx_Complete_Callback() won't be called until 'size' characters have been received. The callback also won't be called if I don't call HAL_UART_Receive_IT() at all. So it seems that my only choice is to loop on HAL_UART_Receive_IT(size=1) in the application and manage my Rx buffer. I can do that, but is there no less time consuming solution?

#idleie #uart #interrupts #stm32 #hal
9 REPLIES 9
Andrew Neil
Evangelist
Posted on August 18, 2014 at 18:30

''it seems that my only choice is to loop on HAL_UART_Receive_IT(size=1)''

But isn't that effectively what you'd do if you were just using the interrupt directly...?

dbegun
Associate II
Posted on August 18, 2014 at 18:41

Oh, you mean:

void USARTx_IRQHandler(void)

{

  //HAL_UART_IRQHandler(& UartxHandle); <-- don't call that

 

  // manage Rx buffer

}

That's exactly what I need.

dbegun
Associate II
Posted on August 18, 2014 at 19:19

But then I need to replicate much of the HAL library functionality in my ISR. Is there no textbook solution?

Andrew Neil
Evangelist
Posted on August 19, 2014 at 09:15

No. I mean you request a single-byte asynchronous receive using the HAL function, then your HAL callback will check for the termination, and either finish or request the next single-byte asynchronous receive using the HAL function...

Which is pretty much the same as you'd do if you were using direct register access - just a step removed due to the HAL...

Andrew Neil
Evangelist
Posted on August 19, 2014 at 09:18

This thread looks to be essentially the same topic: 

[DEAD LINK /public/STe2ecommunities/mcu/Lists/STM32Java/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/STM32Java/Need%20help%20with%20RS232%20receive%20%20STMCubeMx&FolderCTID=0x01200200770978C69A1141439FE559EB459D758000F9A0E3A95BA69146A17C2E80209ADC21&TopicsView=https%3a//my.st.com/public/STe2ecommunities/mcu/Lists/STM32Java/AllItems.aspx&currentviews=87]https://my.st.com/public/STe2ecommunities/mcu/Lists/STM32Java/Flat.aspx?RootFolder=%2fpublic%2fSTe2ecommunities%2fmcu%2fLists%2fSTM32Java%2fNeed%20help%20with%20RS232%20receive%20%20STMCubeMx&FolderCTID=0x01200200770978C69A1141439FE559EB459D758000F9A0E3A95BA69146A17C2E80209ADC21&TopicsView=https%3A%2F%2Fmy%2Est%2Ecom%2Fpublic%2FSTe2ecommunities%2Fmcu%2FLists%2FSTM32Java%2FAllItems%2Easpx&currentviews=87

vcelik
Associate II
Posted on August 19, 2014 at 11:13

Hi, I have also a similar problem with STM32F103 UART. My micro is communicating with an rf module using uart but I don't know when the message frame (from modem to my micro) ends. And the frame also doesn't have an ending character. I need to handle every frame separately. So I tried to use idle line interrupt while receiving. Here is my code:

void
USART2_IRQHandler(
void
)
{
U8 temp;
u16 UsartSR_Reg;
UsartSR_Reg = USART2->SR;
if
( UsartSR_Reg & USART_FLAG_ORE) { 
//Overrun Error
temp = USART2->DR;
//To clear flag
goto
IRQ_TX;
} 
if
(UsartSR_Reg & USART_FLAG_RXNE)
{
if
((USART2->CR1 & USART_CR1_IDLEIE) == RESET){
USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);
}
else
if
(UsartSR_Reg & USART_FLAG_IDLE){ 
//Data finished??
temp = USART2->DR;
//To clear flag
USART_ITConfig(USART2, USART_IT_IDLE, DISABLE);
handle_frame(); 
}
if
( (UsartSR_Reg & USART_FLAG_NE) || (UsartSR_Reg & USART_FLAG_FE) ){ 
//Noise Error || Framing Error
temp = USART2->DR;
//To clear flag
goto
IRQ_TX;
}
if
(CIRCULAR_BUFFER_SIZE <= RxQueue.Count)
{ 
temp = (USART2->DR & 0xFF);
//to clear pending bit
goto
IRQ_TX;
}
RxQueue.Count++; 
RxQueue.Buffer[RxQueue.Head++] = (USART2->DR & 0xFF); 
if
(RxQueue.Head == CIRCULAR_BUFFER_SIZE)
{ RxQueue.Head = 0;
} 
}
IRQ_TX:
if
(USART_GetITStatus(USART2, USART_IT_TXE) != RESET)
{ 
USART_SendData(USART2, TxBuffer[TxBufferIndex++]);
if
(TxBufferIndex == TxBufferSize)
{ 
USART_ITConfig(USART2, USART_IT_TXE, DISABLE); 
} 
} 
}

But it seems it doesn't work. I am having trouble on receiving frames. Is it a valid method to use idle line flag to detect the end of the frame?
Andrew Neil
Evangelist
Posted on August 19, 2014 at 13:22

''I have also a similar problem''

But you're not using the HAL?

''

the frame also doesn't have an ending character''

So what is  the condition which defines the end of a ''frame'' - there has to be something?!

How about posting a link to the RF Module in question, or its frame protocol specification?

vcelik
Associate II
Posted on August 19, 2014 at 14:51

''But you're not using the HAL?''

Yes, you are right. I don't use HAL. I just didn't want to start a new discussion, because the title of the problem seemed similar to my problem.

''

So what 

is

  the condition which defines the end of a ''frame

''

- there has to be 

something

?!''

Actually I use AT commands to reach the rf module. I use the term frame for the data coming from the module. For example, for the command 'AT', the rf module sends 'OK' which is a frame for me. 

The document of rf module says there is at least a 20ms time delay between frames. So after the last byte of a frame, the line is idle for 20ms. What I am trying to do in the code that I sent is after getting the first byte of the frame, setting up the idle interrupt and trying to catch the idle line after the last byte of the frame. Because the line should be idle for 20ms after the last byte. And also the baudrate of UART is 115200bps.

What I would like to learn is, is it possible to use idle line interrupt to detect the end of the receiving bytes?

Andrew Neil
Evangelist
Posted on August 19, 2014 at 15:13

AT Commands (and responses) are terminated by the S3 character, followed by the S4character - (almost) invariably CR and LF.

S3 and S4 are Parameters; aka ''S-Registers''

S3 = Command line termination character

(often incorrectly just called ''line feed'' - because that's the value it usually has)

S4 = Response formatting character

(often incorrectly just called ''carriage return'' - because that's the value it usually has)

See ITU-T V.250

https://www.itu.int/rec/T-REC-V.250/en