Skip to main content
VPras
Associate III
August 26, 2019
Solved

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

  • August 26, 2019
  • 13 replies
  • 3473 views

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 ??

This topic has been closed for replies.
Best answer by Trevor Jones

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;
}

13 replies

Ozone
Principal
August 26, 2019

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.

VPras
VPrasAuthor
Associate III
August 27, 2019

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 ??

Tesla DeLorean
Guru
August 26, 2019

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

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
VPras
VPrasAuthor
Associate III
August 26, 2019

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?

Tesla DeLorean
Guru
August 26, 2019

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 VenmoUp vote any posts that you find helpful, it shows what's working..
VPras
VPrasAuthor
Associate III
August 27, 2019

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 ??

VPras
VPrasAuthor
Associate III
August 26, 2019

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
August 26, 2019

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.

Andrei Chichak
Lead
August 26, 2019

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?

Ozone
Principal
August 27, 2019

I never used Cube for any similar purpose.

GPS (NMEA183) can easily be handled in a Rx interrupt, with a little checking and buffer management.

A concurrent transmission (e.g. to a PC) can be done via DMA, or a temporarily enabled TxE interrupt for the transmitting UART.

> 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 ??

This is not a problem of buffer size, but time management.

Just do not send the received strings via blocking HAL functions in the interrupt context. The character loss occurs during this time.

Try DMA for sending.

VPras
VPrasAuthor
Associate III
August 27, 2019

Thanks Ozone,

It works Perfect now.But now i need to parse the received data and process ,at the same time we would need to receive data from GPS as well without missing any data.

How can i implement that?

Ozone
Principal
August 27, 2019

Not in the receive interrupt context.

I used to simply set a flag in the Rx interrupt handler, when a sentence was ready for parsing/processing.

This flag was checked regularly in the main loop, which did the processing (and resets the flag).

Main loop cycle times could relatively easy be adapted to the GPS receiver sentence rate, which is usually configurable, too.

I never used Cube, though, and not intent to do it in the foreseeable future.

It takes too much design options and decisions out of my hand. Not even mentioning bug rate.

T J
Senior III
August 27, 2019

its so easy using the Rx DMA, super simple I would say.

never lose a byte, upto your buffer size, could be 100K if you want it... you can drink beer before you check it, and still every byte is intact.

and the data is available within 10nS of receiving a byte...

non blocking Tx DMA while still using printf is achievable but a little more problematic, not easy for the young engineers.

T J
Senior III
August 27, 2019

do you use HAL ?

VPras
VPrasAuthor
Associate III
August 27, 2019

Yes TJ. I'm using HAL generated from CubeMX.I only wanted to read data ,then in the meantime i want to process the data without any data being lost in the receiver side.

I will be using rtos so that i do not want to do it with interrupts.

How do i receive data using Rx DMA and increase the buffer size and how do i read the buffer stored for processing???

Thanks in advance

Andrei Chichak
Lead
August 27, 2019

Start here:

https://embedded.fm/blog/2016/11/29/discovery-uarts-part-1

It goes on for 4 posts, then there is two on DMA.