cancel
Showing results for 
Search instead for 
Did you mean: 

why i couldn't receive continuous data of GPS over UART?

VPras
Associate II

Hi,

I am trying to get the NMEA data over UART and print it over another uart .But when i try read in loop after writing data to PC ,I'm not receiving any data. what could be the issue?

any ideas ??

1 ACCEPTED SOLUTION

Accepted Solutions
Trevor Jones
Senior

I use this method,

never miss abyte, make your buffer 1024bytes at least,

uint32_t  U1RxBufferPtrIN =0;
uint32_t  U1RxBufferPtrOUT =0;
void initUart1RxDMABuffer(void) {
    if (HAL_UART_Receive_DMA(&huart1, (uint8_t *)Usart1RxDMABuffer, U1RxBufSize) != HAL_OK)
    {
        sprintf(string, "initUart1RxDMABuffer Failed\n");
        puts1(string);        
    }
    else
        {
            sprintf(string, "initUart1RxDMABuffer OK!\n");
            puts1(string);
        }
}
char peekRxU1(int offset) {
    // offset of zero returns the next byte to be read
    int relativePtr = (U1RxBufferPtrOUT + offset) & (U1RxBufSize - 1); 
    char PeekRx = Usart1RxDMABuffer[relativePtr];   // just looking Don't increment pointer
return PeekRx;
}
char readU1(void) {
    char readByte = Usart1RxDMABuffer[U1RxBufferPtrOUT++];
    if (U1RxBufferPtrOUT >= U1RxBufSize) U1RxBufferPtrOUT = 0;
    return readByte;
}
char readableU1(void) {
    U1RxBufferPtrIN =  U1RxBufSize - huart1.hdmarx->Instance->CNDTR;
    return U1RxBufferPtrIN - U1RxBufferPtrOUT;
}                               
void clearRxBuffer(void) {
    U1RxBufferPtrIN =  U1RxBufSize - huart1.hdmarx->Instance->CNDTR;
    U1RxBufferPtrOUT = U1RxBufferPtrIN;
}

View solution in original post

22 REPLIES 22
Ozone
Lead

Since you presented no relevant code, and my Magic Crystal Ball is under repair, I make a guess.

You probably use Cube-generated code, call the PC output from the interrupt callback (i.e. in interrupt context), and cause a Rx overflow error in the GPS reception which you do not handle.

A pair of blocking functions in a loop are apt to drop data.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
VPras
Associate II

Hi Thanks,

This is my code

while(1)
{
	   HAL_UART_Receive(&huart2, (uint8_t *)UARTRxBuffer, 700,1000);
	   HAL_UART_Transmit(&huart3, (uint8_t *)UARTRxBuffer, strlen(UARTRxBuffer), 1000);
  }

here uart2 is for GPS Data and uart3 is to transmit data to PC.

How to find Rx overflow is happening? and how do i handle it?

VPras
Associate II

Hi Clive,

I understand blocking functions in a loop drop data but my GPS module sends every second. Even after transmitting i couldn't receive any data. Not even a single data!!

any other issues??

S.Ma
Principal

If the UART3 baudrate is same or higher than USART2, use the USART2 Receive interrupt method and in the callback simply send the received byte.

It's simple, not elegant, but it may get you moving on.

UART receiving by polling (blocking) is definitely simple and wrong = misleading.

Is there any good reason to assume that the UARTRxBuffer would have a properly formatted C string in it? Where does the NULL terminator come from? How about on the second call, what is in the buffer and where does the new NULL terminator come from?

What do the return status codes tell you?

What is in the buffer? Does it contain appropriate data for strlen to work properly?

What happens in the receive function the second time it is called? Which parts did you trace through, and which parts are being executed?

strlen() has a dependency on the string data being NUL terminated, GPS receivers don't send NUL bytes.

Assuming same rates, otherwise use ring-buffers

#ifdef USART_CR1_TXEIE_TXFNFIE // FIFO Support
#define USART_CR1_RXNEIE USART_CR1_RXNEIE_RXFNEIE
#define USART_CR1_TXEIE  USART_CR1_TXEIE_TXFNFIE
#define USART_ISR_RXNE   USART_ISR_RXNE_RXFNE
#define USART_ISR_TXE    USART_ISR_TXE_TXFNF
#endif
 
void Forward(void)
{
  while(1)
  {
    if((USART2->ISR & USART_ISR_RXNE) == 0) // Wait for Char
    {
      if (USART2->ISR & USART_ISR_ORE) // Overrun Error
        USART2->ICR = USART_ICR_ORECF;
      if (USART2->ISR & USART_ISR_NE) // Noise Error
        USART2->ICR = USART_ICR_NCF;
      if (USART2->ISR & USART_ISR_FE) // Framing Error
        USART2->ICR = USART_ICR_FECF;
    }
    else
    {
      uint8_t Data = USART2->RDR; // Read Char;
 
      while((USART3->ISR & USART_ISR_TXE) == 0);
 
      USART3->TDR = Data; // Send Char
    }
 
    if((USART3->ISR & USART_ISR_RXNE) == 0) // Wait for Char
    {
      if (USART3->ISR & USART_ISR_ORE) // Overrun Error
        USART3->ICR = USART_ICR_ORECF;
      if (USART3->ISR & USART_ISR_NE) // Noise Error
        USART3->ICR = USART_ICR_NCF;
      if (USART3->ISR & USART_ISR_FE) // Framing Error
        USART3->ICR = USART_ICR_FECF;
    }
    else
    {
      uint8_t Data = USART3->RDR; // Read Char
 
      while((USART2->ISR & USART_ISR_TXE) == 0);
 
      USART2->TDR = Data; // Send Char
    }
  }
} 

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Hi Clive,

Thanks

I used this USART2->ICR = USART_ICR_ORECF; to clear the overrun.Now i can get the data continuously.But issue is i'm missing more data inbetween.

How do i reduce the occurrence of overrun or is there any way to increase the buffer size ??

Thanks Ozone(O3),

I can get data continuously but i'm missing more data in mean time.is there any way to increase the buffer ??