cancel
Showing results for 
Search instead for 
Did you mean: 

How to read data correctly from NEO-6M GPS module?

M7890.1
Associate III

Hi.

I am trying to read data from the GPS module using USART1 and then send to to a serial monitor through USART2. It ended up not printing the information correctly on the serial monitor. (I have tried to connect the GPS module to a FTDI module directly and there are data showing on the serial monitor)

My code:

/* USER CODE BEGIN Header */
/**
 ******************************************************************************
 * @file           : main.c
 * @brief          : Main program body
 ******************************************************************************
 * @attention
 *
 * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
 * All rights reserved.</center></h2>
 *
 * This software component is licensed by ST under BSD 3-Clause license,
 * the "License"; You may not use this file except in compliance with the
 * License. You may obtain a copy of the License at:
 *                        opensource.org/licenses/BSD-3-Clause
 *
 ******************************************************************************
 */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
 
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
 
/* USER CODE END Includes */
 
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
 
/* USER CODE END PTD */
 
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
 
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
 
/* USER CODE END PM */
 
/* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart1;
UART_HandleTypeDef huart2;
 
/* USER CODE BEGIN PV */
 
/* USER CODE END PV */
 
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
static void MX_USART2_UART_Init(void);
/* USER CODE BEGIN PFP */
 
/* USER CODE END PFP */
 
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
 
/* USER CODE END 0 */
 
/**
 * @brief  The application entry point.
 * @retval int
 */
int main(void) {
	/* USER CODE BEGIN 1 */
 
	/* USER CODE END 1 */
 
	/* MCU Configuration--------------------------------------------------------*/
 
	/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
	HAL_Init();
 
	/* USER CODE BEGIN Init */
	uint8_t buffer[128] = {'\0'};
	/* USER CODE END Init */
 
	/* Configure the system clock */
	SystemClock_Config();
 
	/* USER CODE BEGIN SysInit */
 
	/* USER CODE END SysInit */
 
	/* Initialize all configured peripherals */
	MX_GPIO_Init();
	MX_USART1_UART_Init();
	MX_USART2_UART_Init();
	/* USER CODE BEGIN 2 */
 
	/* USER CODE END 2 */
 
	/* Infinite loop */
	/* USER CODE BEGIN WHILE */
	while (1) {
		/* USER CODE END WHILE */
		HAL_UART_Receive(&huart1, buffer, 8, 100);
		HAL_UART_Transmit(&huart2, buffer, sizeof(buffer), 100);
 
		/* USER CODE BEGIN 3 */
	}
	/* USER CODE END 3 */
}
 
/**
 * @brief System Clock Configuration
 * @retval None
 */
void SystemClock_Config(void) {
	RCC_OscInitTypeDef RCC_OscInitStruct = { 0 };
	RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 };
 
	/** Initializes the RCC Oscillators according to the specified parameters
	 * in the RCC_OscInitTypeDef structure.
	 */
	RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
	RCC_OscInitStruct.HSIState = RCC_HSI_ON;
	RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
	RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
	if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
		Error_Handler();
	}
	/** Initializes the CPU, AHB and APB buses clocks
	 */
	RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
			| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
	RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
	RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
	RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
	RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
 
	if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) {
		Error_Handler();
	}
}
 
/**
 * @brief USART1 Initialization Function
 * @param None
 * @retval None
 */
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;
	if (HAL_UART_Init(&huart1) != HAL_OK) {
		Error_Handler();
	}
	/* USER CODE BEGIN USART1_Init 2 */
 
	/* USER CODE END USART1_Init 2 */
 
}
 
/**
 * @brief USART2 Initialization Function
 * @param None
 * @retval None
 */
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;
	if (HAL_UART_Init(&huart2) != HAL_OK) {
		Error_Handler();
	}
	/* USER CODE BEGIN USART2_Init 2 */
 
	/* USER CODE END USART2_Init 2 */
 
}
 
/**
 * @brief GPIO Initialization Function
 * @param None
 * @retval None
 */
static void MX_GPIO_Init(void) {
 
	/* GPIO Ports Clock Enable */
	__HAL_RCC_GPIOD_CLK_ENABLE()
	;
	__HAL_RCC_GPIOA_CLK_ENABLE()
	;
 
}
 
/* USER CODE BEGIN 4 */
 
/* USER CODE END 4 */
 
/**
 * @brief  This function is executed in case of error occurrence.
 * @retval None
 */
void Error_Handler(void) {
	/* USER CODE BEGIN Error_Handler_Debug */
	/* User can add his own implementation to report the HAL error return state */
	__disable_irq();
	while (1) {
	}
	/* USER CODE END Error_Handler_Debug */
}
 
#ifdef  USE_FULL_ASSERT
/**
 * @brief  Reports the name of the source file and the source line number
 *         where the assert_param error has occurred.
 * @param  file: pointer to the source file name
 * @param  line: assert_param error line source number
 * @retval None
 */
void assert_failed(uint8_t *file, uint32_t line)
{
	/* USER CODE BEGIN 6 */
	/* User can add his own implementation to report the file name and line number,
	 ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
	/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
 
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

And here's part of the output on the serial monitor:

0693W00000D1pAQQAZ.png

12 REPLIES 12
KnarfB
Principal III

HAL_UART_Receive returns either when 8 chars were read or the specified time elapsed or an error occured. Your code doesn't handle that in HAL_UART_Transmit

.

TDK
Guru
		HAL_UART_Receive(&huart1, buffer, 8, 100);
		HAL_UART_Transmit(&huart2, buffer, sizeof(buffer), 100);

Also, you're only trying to receive 8 bytes, but you're sending out 128 bytes. The last 120 bytes will be nonsense.

Monitor the return values from HAL functions to see if they worked.

Consider using interrupt or DMA mode so that you can send and receive at the same time.

If the number of bytes is unknown, use HAL_UARTEx_ReceiveToIdle which will return when the bus becomes idle rather than waiting for all characters.

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

Need to read a byte and write a byte.

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

So you mean the GPS module always transmits 128 bytes? I was trying to look for this information in the datasheet but can't find it.

If I were to receive the data and need to use it for other purpose (instead of merely printing it), do you recommend interrupt or DMA or HAL_UARTEx_ReceiveToIdle (I just knew about this)?

I am saying your HAL_UART_Receive tries to receive 8 bytes and your HAL_UART_Transmit statements always sends 128 bytes regardless of whatever is in buffer.
Blocking mode should be fine with this GPS receiver and HAL_UARTEx_ReceiveToIdle seems the easiest to implement.
If you feel a post has answered your question, please click "Accept as Solution".

OK. Also, I would like to know if I want to stop collecting data after newline is encountered, how do I implement that?

In the code below, I was trying to receive one byte at a time and stop receiving after newline is encountered. But the code ended up not transmitting anything.

uint8_t data = 0;
uint8_t buffer[300] = {'\0'};
uint8_t index = 0;
 
do{
			HAL_UART_Receive(&huart1, data, 1, 5000); // receive one data at a time
			buffer[index] = data;
			index++;
		}while(data != '\r');
 
		HAL_UART_Transmit(&huart2, buffer, sizeof(buffer), 100);

HAL_UART_Receive needs the ADDRESS of data variable

You need to ensure the index stays within scope, and perhaps resets when it encounters a CR/LF or $

You should transmit what you actually receive, so perhaps use index as a length rather than the entire buffer via sizeof()

I've published some NMEA line parsing examples to the forum in the past, dig a little.

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

Is '\r' or '\n' used for endline? The code doesn't seem to be able to capture it.

Most GPS/GNSS receivers use both.

HAL_UART_Receive(&huart1, &data, 1, 5000); // Need address of data

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