简体   繁体   中英

Why does stm32f4 uart skip some characters when receiving using an interrupt

Having some problems trying to receive characters from a serial Putty Session. When I type sentences/multiple characters into Putty to send character to the stm32f4 microcontroller, it doesn't seem to receive all of the characters using an interrupt approach.

So two questions:

  1. Not sure what is going on here. Am I missing something?
  2. I am a little confused when an interrupt is called for receiving characters. Is the interrupt called for each character or do you process the whole string with one interrupt call?

Code:

void USART_Write(USART_TypeDef * USARTx, char * str)  {                         

  while(*str){                                                                  
    // First check if the Transmission Data register is empty                   
    while ( !(USARTx->SR & USART_SR_TXE)){};                                    

    // Write Data to the register which will then get shifted out               
    USARTx->DR =(*str &(uint16_t) 0x01FF);                                      

    str++;                                                                      
  }                                                                             
  // Wait until transmission is complete                                        
  while ( !(USARTx->SR & USART_SR_TC)){};                                       

}                              

void receive(USART_TypeDef * USARTx, volatile  char *buffer,
                volatile uint32_t * pCounter){

  if(USARTx->SR & USART_SR_RXNE){                                               
    char c = USARTx->DR;                                                        
    USART_Write(USARTx,&c);                                                     
    USART_Write(USARTx,"\n\r");                                                 
  }                                                                             



}                                                                               

void USART2_IRQHandler(void){                                                   
  receive(USART2, USART2_Buffer_Rx,&Rx2_Counter);                             
}  

Putty Session:

(I type asdfghjkl into Putty and print out the receiving characters using the USART_WRITE(...) function)

asdfghjkl
a
s
g
k
USART_Write(USARTx,&c);
...........
while(*str)...
  • NO! Single chars are not NUL-terminated char arrays!

You must not use a polled tx approach directly from an rx interrupt-handler. It will likely result in rx overrun as the rx buffer gets overwritten by newly received chars while the rx interrupt-handler is stuck polling the tx registers.

You need a tx interrupt and some kind of buffer, eg. a circular char queue.

Yes, I know it's a bit of a pain handling tx interrupts, circular buffers etc. If the tx interrupt finds no more chars to send it has to exit having sent none. This means that when the rx interrupt next needs to queue up char to send, it must load it into the tx register instead of the queue in order to 'prime' the tx interrupt mechanism.

Things get even more umm 'interesting' if the chars need to traverse waiting non-interrupt thread/s and/or need to be blocked up into protocol units.

Anyway, whatever, you must not use this mixed interrupt/polling. It will not work reliably and the extra delays will adversely affect other interrupts, especially lower-priority interrupts, that will remain disabled for long periods:(

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM