Author Topic: STM32 HAL UART Recieve Errors  (Read 2815 times)

0 Members and 1 Guest are viewing this topic.

Offline PatrickCPETopic starter

  • Newbie
  • Posts: 9
  • Country: us
STM32 HAL UART Recieve Errors
« on: January 12, 2022, 09:30:47 pm »
Hey everyone,

I'm having some issues with the STM32 HAL_UART_Receive function. I've posted on the ST forums, but I figure you folks on here are pretty knowledgeable about this sorta thing as well. I'll link my post on the ST forum (It has code snippets and screenshots of the debugging steps I've taken) and I'll just summarize the issue here.

Link to ST forums: https://community.st.com/s/question/0D53W00001JAeWZSA1/haluartreceive-polling-mode-only-picks-up-first-character-from-uart

I'm trying to read from a GPS module via UART.

Expected Behavior:
* Read GPS data via USUART1 into a buffer until the buffer is full or timeout occurs
* Print a new line to the serial terminal on USUART2
* Print the data contained within the Buffer to USUART2

Behavior that occurs:
* Reads only the first character into the buffer (which maybe it reads one transfer at a time then returns, but this doesn't explain why subsequent reads fail)
* New line prints just fine
* Buffer data only contains the first char, and will only print once (because besides that the buffer is zeroed out)

Debugging Steps:
* Connect GPS directly to PC (Works fine, confirmed 9600 baud, no parity, 1 stop bit)
* Connect Logic Analyzer to GPS Tx Pin (Works fine, logic analyzer catches the correct GPS Message format)
* Debugger on STM32 (Can see that the UART reads into the buffer correctly once, fails for any subsequent read)

Any help on this would be much appreciated.

Thank you!
 

Online DavidAlfa

  • Super Contributor
  • ***
  • Posts: 6079
  • Country: es
Re: STM32 HAL UART Recieve Errors
« Reply #1 on: January 12, 2022, 09:39:18 pm »
What's the GPS update rate?
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 

Offline PatrickCPETopic starter

  • Newbie
  • Posts: 9
  • Country: us
Re: STM32 HAL UART Recieve Errors
« Reply #2 on: January 12, 2022, 09:46:44 pm »
From what I can see 5 Hz.

The GPS is a clone of the Neo-6M (my fault for buying china clones, a real datasheet is very nice)
Neo-6M datasheet: https://www.u-blox.com/sites/default/files/products/documents/NEO-6_DataSheet_%28GPS.G6-HW-09005%29.pdf

Link to the actual GPS module used: https://www.amazon.com/dp/B07P8YMVNT?ref=ppx_yo2_dt_b_product_details&th=1
 

Offline rcbuck

  • Frequent Contributor
  • **
  • Posts: 351
  • Country: us
Re: STM32 HAL UART Recieve Errors
« Reply #3 on: January 13, 2022, 02:56:22 am »
You are never going to get this to work with polling. It only takes 1.04 msec for each byte at 9600 baud. You have a 100 msec delay in your main while loop. When you execute that delay you are causing a buffer overrun in the USART receiver and everything stops. Then you have a 1 second delay for some reason.

Here is some code I used to read the NMEA input from a NEO-6M and repeat it back out to my PC.
Code: [Select]
void USART1_IRQHandler(void) // Sync and Queue NMEA Sentences
{
  static char rx_buffer[LINEMAX];   // holding buffer to build line - Global variable
  static int rx_index = 0;


  if (USART1->SR & USART_SR_RXNE) // Received character?
  {
    char rx = (char)(USART1->DR & 0xFF);

    if ((rx == '\r') || (rx == '\n')) // Is this an end-of-line condition, either will suffice?
    {
      if (rx_index != 0) // Line has some content
      {
        memcpy((void *)line_buffer, rx_buffer, rx_index); // Copy to static line buffer from dynamic receive buffer
        line_buffer[rx_index] = 0; // Add terminating NUL
        line_valid = 1; // flag new line valid for processing

        rx_index = 0; // Reset content pointer
      }
    }
    else
    {
      if ((rx == '$') || (rx_index == LINEMAX)) // If resync or overflows pull back to start
        rx_index = 0;

      rx_buffer[rx_index++] = rx; // Copy to buffer and increment
      __NOP();
      OutChar(rx); // code to repeat incoming data - not needed for GPS clock
    }
  }
}

These are some of the variables that you see in the USART handler. They are at the beginning of the startup code section.
Code: [Select]
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
#define LINEMAX 80 // Maximal allowed/expected line length
volatile char line_buffer[LINEMAX + 1]; // Holding buffer with space for terminating NUL
volatile int line_valid = 0;
/* USER CODE END PD */

I added this code to the USART initialization code the was generated by the IOC tool.
Code: [Select]
  /* USER CODE BEGIN USART1_Init 2 */
  // setup UART interrupt to be handled by USART1_IRQHandler function
  HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(USART1_IRQn);
  __HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE); // flag receive
  /* USER CODE END USART1_Init 2 */

I was using a blue pill board for my tests. The code above with a lot more code was used to make a 6 digit, 2.3 inch clock. The GPS module provides the time source to the clock so it is never more than a couple of hundred milliseconds off. I used one of the clone boards (not the one you have) and it worked fine. The module on the board is labeled as a Ublox NEO-6M but a label doesn't mean anything for products coming out of China.

What are you trying to accomplish? If you simply need the time information I would suggest reprogramming the GPS module so that the only data that it sends out is the $GPRMC string. You can pull the time and date information from that single message.


 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf