2025-01-02 01:02 AM
Happy New Year everyone !
I am currently trying to get the nmea sentences from the above gnss module (vic3da) i have connected the uart rx/tx and ground (gnd) and am able to ping the gps unit but unable to read any data from it has anyone ever written code that i might have a look at to know if I'm doing some thing wrong as I am completely new to MCUs or can anyone guide me to complete my project successfully ?
with regards
swayam :)
2025-01-02 07:46 AM - edited 2025-01-02 01:07 PM
Hi,
VIC3DA has 2 UARTs, UART1 and UART2. By default, NMEA is coming out of UART2.
Can you please tell me which UART (UART1 or UART2) you are tapping into?
Where you are connecting the UART lines?
Have you put a scope or logic analyzer on the UART TX pin to see if there is data coming out on the point where you are tapping into?
If you are looking into developing application development with an MCU, it is better to use UART1 as there is J401 and J403 with UART pins exposed. You can connect STM32 MCU UART lines here.
To change internal routing for VIC3DA from UART2 to UART1, you should send the following commands.
$PSTMSETPAR,1101,1 //changes from UART2 to UART1
$PSTMSAVEPAR // save into flash
$PSTMSRR // software rest for settings to take effect
//any time you make a change to CDB (register settings), you have to send $PSTMSAVEPAR followed by $PSTMSRR for settings to take effect.
Please note that once you change communication from UART2 to UART1, you will no longer see data on the USB port.
Also there is board called X-NUCLEO-GNSS2A1 board which plugs directly into the ST morpho connector. This might be the best hardware fit your development needs. https://www.st.com/en/ecosystems/x-nucleo-gnss2a1.html
Regarding firmware, you can refer to X-NUCLEO-GNSS1 software package. Please refer to getting started guide on how to start a project and you can include one of the example projects as part of your application during GNSS middleware configuration.
2025-01-18 01:03 AM
2025-01-18 01:04 AM
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
/* 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 huart2;
/* USER CODE BEGIN PV */
#define BUFFER_SIZE 1024
uint8_t rxBuffer[BUFFER_SIZE];
char uartBuffer[100];
volatile uint8_t rxByte;
volatile uint16_t rxHead = 0;
volatile uint16_t rxTail = 0;
bool gnss_connected = false;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART2_UART_Init(void);
/* USER CODE BEGIN PFP */
static void ProcessNMEAData(void);
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART2)
{
rxBuffer[rxHead] = rxByte;
rxHead = (rxHead + 1) % BUFFER_SIZE;
HAL_UART_Receive_IT(&huart2, &rxByte, 1);
}
}
static void ProcessNMEAData(void)
{
static char line[256];
static int lineIndex = 0;
while (rxHead != rxTail)
{
char c = rxBuffer[rxTail];
rxTail = (rxTail + 1) % BUFFER_SIZE;
if (c == '\n')
{
line[lineIndex] = '\0';
// Echo the complete NMEA sentence
HAL_UART_Transmit(&huart2, (uint8_t*)line, lineIndex, 100);
HAL_UART_Transmit(&huart2, (uint8_t*)"\r\n", 2, 100);
lineIndex = 0;
}
else if (c == '\r')
{
// Ignore carriage returns
continue;
}
else if (lineIndex < 255)
{
line[lineIndex++] = c;
}
}
}
/* 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 */
/* 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_USART2_UART_Init();
/* USER CODE BEGIN 2 */
// Start UART reception in interrupt mode
HAL_UART_Receive_IT(&huart2, &rxByte, 1);
// VIC3DA Configuration Commands
uint8_t get_version[] = "$PSTMGETSWVER,0*3C\r\n";
uint8_t rate_cmd[] = "$PSTMSETPAR,1000,100*54\r\n"; // Set 10Hz rate
uint8_t gga_msg[] = "$PSTMSETPAR,1001,1*76\r\n"; // Enable GGA
uint8_t gsa_msg[] = "$PSTMSETPAR,1002,1*75\r\n"; // Enable GSA
uint8_t gsv_msg[] = "$PSTMSETPAR,1003,1*74\r\n"; // Enable GSV
uint8_t rmc_msg[] = "$PSTMSETPAR,1005,1*72\r\n"; // Enable RMC
uint8_t save_cmd[] = "$PSTMSAVEPAR*58\r\n";
uint8_t reset_cmd[] = "$PSTMSRR*3F\r\n";
// Send initial configuration
HAL_UART_Transmit(&huart2, get_version, strlen((char*)get_version), 100);
HAL_Delay(1000); // Wait for version response
HAL_UART_Transmit(&huart2, rate_cmd, strlen((char*)rate_cmd), 100);
HAL_Delay(100);
HAL_UART_Transmit(&huart2, gga_msg, strlen((char*)gga_msg), 100);
HAL_Delay(100);
HAL_UART_Transmit(&huart2, gsa_msg, strlen((char*)gsa_msg), 100);
HAL_Delay(100);
HAL_UART_Transmit(&huart2, gsv_msg, strlen((char*)gsv_msg), 100);
HAL_Delay(100);
HAL_UART_Transmit(&huart2, rmc_msg, strlen((char*)rmc_msg), 100);
HAL_Delay(100);
// Save settings and reset
HAL_UART_Transmit(&huart2, save_cmd, strlen((char*)save_cmd), 100);
HAL_Delay(1000);
HAL_UART_Transmit(&huart2, reset_cmd, strlen((char*)reset_cmd), 100);
HAL_Delay(2000); // Wait for reset to complete
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
uint32_t lastBlinkTime = 0;
uint8_t blinkState = 0; // Used to track the blink pattern state
while (1)
{
ProcessNMEAData();
// LED blinking pattern: two quick blinks followed by one long blink
uint32_t currentTime = HAL_GetTick();
if(currentTime - lastBlinkTime >= 200) // Check every 200ms
{
switch(blinkState) {
case 0: // First quick blink ON
HAL_GPIO_WritePin(Led_GPIO_Port, Led_Pin, GPIO_PIN_RESET);
lastBlinkTime = currentTime;
blinkState = 1;
break;
case 1: // First quick blink OFF
HAL_GPIO_WritePin(Led_GPIO_Port, Led_Pin, GPIO_PIN_SET);
lastBlinkTime = currentTime;
blinkState = 2;
break;
case 2: // Second quick blink ON
HAL_GPIO_WritePin(Led_GPIO_Port, Led_Pin, GPIO_PIN_RESET);
lastBlinkTime = currentTime;
blinkState = 3;
break;
case 3: // Second quick blink OFF
HAL_GPIO_WritePin(Led_GPIO_Port, Led_Pin, GPIO_PIN_SET);
lastBlinkTime = currentTime;
blinkState = 4;
break;
case 4: // Long blink ON
HAL_GPIO_WritePin(Led_GPIO_Port, Led_Pin, GPIO_PIN_RESET);
lastBlinkTime = currentTime;
blinkState = 5;
break;
case 5: // Long blink OFF (with longer delay)
HAL_GPIO_WritePin(Led_GPIO_Port, Led_Pin, GPIO_PIN_SET);
lastBlinkTime = currentTime;
blinkState = 0;
HAL_Delay(500); // Longer pause before repeating pattern
break;
}
}
HAL_Delay(10); // Small delay to prevent busy-waiting
/* USER CODE END WHILE */
/* 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_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
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_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;
RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
Error_Handler();
}
}
/**
* @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;
huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart2.Init.ClockPrescaler = UART_PRESCALER_DIV1;
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 */
}
/**
* @brief GPIO Initialization Function
* @PAram None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(Led_GPIO_Port, Led_Pin, GPIO_PIN_SET);
/*Configure GPIO pin : User_Button_Pin */
GPIO_InitStruct.Pin = User_Button_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(User_Button_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pin : Led_Pin */
GPIO_InitStruct.Pin = Led_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(Led_GPIO_Port, &GPIO_InitStruct);
/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI4_15_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI4_15_IRQn);
/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}
/* 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 */
2025-01-18 01:34 AM
Isn't there a pin level conflict on the NUCLEO-64 with Arduino rail D0/D1 and ST-LINK VCP?
Why echoing NMEA back to receiver?
2025-01-18 01:42 AM
Hi !
I'm completely new to this so .. Did you mean to use two different UARTs?
UART2 for the VCP (USB) and UART1 for the communication between the gnss module and the mcu ?
2025-01-18 11:55 AM
Looking at the Schematic https://www.st.com/resource/en/schematic_pack/mb1717-c031c6-b02_schematic.pdf#page=3
PA2/PA3 (USART2) is for the ST-LINK VCP, can connect to rail via SB (Solder Bridges)
PB6/PB7 (USART1) is for the Arduino rail
Pins for MCU via Data Sheet tables
https://www.st.com/resource/en/datasheet/stm32c031c4.pdf#page=36
So interact with the VIC3DA via the STM32C031's USART1, and echo/diagnose through USART2 to the ST-LINK and the terminal connected to that COM/VCP
2025-01-21 07:16 AM
Hi
I have tried to run the program as per the suggested configuration. Still i am not able to communicate between the gnss module and the MCU.
I have also some confusions in the initialization of the GNSS. I dont know what all parameters needs to be initialized. I have only tried with the baud rate. Please guide me.
2025-01-21 07:28 AM
@swayamsidhmohanty wrote:Still i am not able to communicate between the gnss module and the MCU.
I have also some confusions in the initialization of the GNSS. I dont know what all parameters needs to be initialized.
Start by doing this without the MCU - that's just an unnecessary added complication.
Connect that GNSS board to a PC terminal (via UART-to-USB converter).
In particular, pay attention to line endings - does it need just CR? just LF? CR and LF?
Once you've got that working, then (and only then) start thinking about how to implement that on the MCU.
Similarly, get your MCU UART code working with a PC terminal before connecting to the GNSS
2025-01-21 07:33 AM
Hi
I have tried connecting directly using USB to PC and the values are coming in serial monitor. But not in MCU.