cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_UART_Receive() Polling Mode: Only picks up first character from UART

PHoey.1
Associate

Hello,

I have a GPS module that prints of NMEA message strings in standard ASCII format at a rate of 9600 baud. This module is connected to usuart1 on my micro.

It appears that only the first character is ever caught by the system, and anything following that fails. Subsequent reads fail as well.

The GPS module has direct USB connection and I can see that 9600 baud with no parity and 1 stop bit is the correct configuration. My logic analyzer confirms this as well.

Does anyone know what might be causing this to occur?

Any help is much appreciated, thanks

Code with other functionality stripped out(filesystem stuff was stripped out for your reading)

/* Private variables ---------------------------------------------------------*/
RTC_HandleTypeDef hrtc;
 
SPI_HandleTypeDef hspi1;
SPI_HandleTypeDef hspi2;
 
UART_HandleTypeDef huart1;
UART_HandleTypeDef huart2;
 
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_RTC_Init(void);
static void MX_SPI1_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_SPI2_Init(void);
static void MX_USART1_UART_Init(void);
 
int main(void)
{
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_RTC_Init();
  MX_SPI1_Init();
  MX_USART2_UART_Init();
  MX_SPI2_Init();
  MX_FATFS_Init();
  MX_USART1_UART_Init();
 
  /* USER CODE BEGIN 2 */
 
  //uint8_t gpsBuff[10] = {0};
 
  HAL_UART_Transmit(&huart2, (uint8_t*)"Hello There\r\n", sizeof("Hello There"), 1000);
  uint8_t secondBuffer[100] = {0};
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
	  // Listen to GPS on uart1 and transmit received message to the Serial Terminal
	  HAL_UART_Receive(&huart1, secondBuffer, sizeof(secondBuffer), 1000);
          HAL_UART_Transmit(&huart2, (uint8_t*)'\r\n', sizeof('\r\n'), 1000);
          HAL_Delay(100);
	  HAL_UART_Transmit(&huart2, secondBuffer, sizeof(secondBuffer), 1000);
	  HAL_Delay(1000);
          secondBuffer[0] = 0;	//Seems strange but you'll see that only index 0 is being changed once, the rest remain zero and won't print
 
	  HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
 
  }
}
 
 
static void MX_USART1_UART_Init(void)
{
 
  /* USER CODE BEGIN USART1_Init 0 */
 
  /* USER CODE END USART1_Init 0 */
 
  /* USER CODE BEGIN USART1_Init 1 */
 
  /* USER CODE END USART1_Init 1 */
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 9600;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART1_Init 2 */
 
  /* USER CODE END USART1_Init 2 */
}
 
 
static void MX_USART2_UART_Init(void)
{
 
  /* USER CODE BEGIN USART2_Init 0 */
 
  /* USER CODE END USART2_Init 0 */
 
  /* USER CODE BEGIN USART2_Init 1 */
 
  /* USER CODE END USART2_Init 1 */
  huart2.Instance = USART2;
  huart2.Init.BaudRate = 115200;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART2_Init 2 */
 
  /* USER CODE END USART2_Init 2 */
 
}

CubeMX Setup for USUART1 (GPS UART)

0693W00000HrSeIQAV.pngSerial Terminal Capture (Occasionally when it first polls in the middle of the window it will publish a garbage character, but as you can see it only reads the first char, then prints only the new lines from the transmit, the buffer remains empty)

0693W00000HrSfVQAV.png 

Serial Terminal Output when GPS connected directly to PC

0693W00000HrSgOQAV.png 

Logic Analyzer Settings

0693W00000HrSeDQAV.pngLogic Analyzer Capture (This is what the HAL should receive, or at least some snippet of it)

0693W00000HrSbxQAF.png

3 REPLIES 3
TDK
Guru

Check the overrun flag. You are probably receiving multiple characters without reading them out. In this case, the first character will stay, the overrun flag will be set, and any characters after that are discarded.

Setting up UART reception in circular DMA mode will be the most robust. Otherwise, you need to ensure the transmitter doesn't send data until you're ready for it, which is usually difficult if not impossible.

If you feel a post has answered your question, please click "Accept as Solution".

Going to timeout if you take more than a second to type.

The interleaved nature of the polling doesn't really lend itself to concurrent reception and transmission, and the receive buffer on the UART is only one byte deep, you have to be responding and buffering as each by comes in. If you get distracted, or are waiting multiple byte times for other data to be sent out, you will miss the service window on the receive side.

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

> Setting up UART reception in circular DMA mode will be the most robust.

For UART at 9600 baud, I would recommend interrupts rather than DMA, except for very well justified cases. Not the Cube/HAL variety, of course, but implementing proper ring buffers.

JW