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

22 REPLIES 22
Ozone
Lead II

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.

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?

T J
Lead

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.

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
Lead

do you use HAL ?

VPras
Associate II

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

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.

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

Thanks Trevor,

Now i can able to get seamless data .now i wanted to clear the Usart1RxDMABuffer once it gets full and start filling the new data to that buffer.

is that possible without reinitialize again??

I'm doing this ,But i cannot read the correct data

char readU1(void) {
    char readByte = Usart1RxDMABuffer[U1RxBufferPtrOUT++];
 
    if (U1RxBufferPtrOUT >= U1RxBufSize) {
    	U1RxBufferPtrOUT = 0;
 
        memset(Usart1RxDMABuffer,0,sizeof(Usart1RxDMABuffer));
        initUart1RxDMABuffer();
    }
    return readByte;
}