cancel
Showing results for 
Search instead for 
Did you mean: 

trying to get NMEA sentences from EVB-VIC3DA using NUCLEO-C031C6

swayamsidhmohanty
Associate II

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 :)

16 REPLIES 16

So now connect MCU to a PC serial terminal via USB-to-UART:

  • Verify that stuff sent by the MCU is received on the terminal
  • Verify that stuff sent from the terminal is received by the MCU

 

Hi,

First step.

Check if UART-1-TX lines from VIC3DA has NMEA data without going through MCU board. This confirms if VIC3DA is outputting data in the UART port of GNSS module you are expecting data to come out of. Can you confirm this?

How to check:

- Check using oscilloscope or logic analyzer

- Or use USB to UART cable and open a serial terminal program or Teseo Suite

Second Step:

Use Getting Started Guide in X-CUBE-GNSS1 software package to configure your MCU.

I would start with VirtualCOMPort  example. In this example MCU sends data out via a different UART.  Another UART receives data from GNSS module.

Another example would be SimOSGetPos.

Refer to UM2334 for more details.

All initialization of GNSS module is done by X-CUBE-GNSS1 software.

You can post a screenshot of your GNSS setting in from CUBE-MX.

Question:

From your pin assignment diagram I only see 1 UART.

You need 2 UARTS if you want to see data on a terminal program.

GNSS module ---- UART_A -----> MCU ------ UART_B ----> Terminal program (just for debug purposes)

 


In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.

Hi
I have verified the stuff sent by the MCU (Just printed Helloworld).
I have verified both the stuff.

Try sending some GNSS sentences from the terminal.

You should be able to copy & paste ...

For sending stuff to the GNSS, remember that it may be choosy as to what line ending(s) it accepts.

Make sure that your receiving stuff handles whatever the GNSS uses as line endings.

 

Tips on debugging serial comms:

https://community.st.com/t5/community-guidelines/how-to-write-your-question-to-maximize-your-chances-to-find-a/tac-p/706966/highlight/true#M49

If everything is working it shouldn't be hard to close the circle..

GNSS typically just wants to output data in a continuous stream.

Avoid code that blocks, avoid arbitrary delays.

Reduce the amount of commands you send, check responses, and determine which need to get sent.

 

Make a simple forwarder to confirm end-to-end communication.

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

Hi

I have conducted the tests either way. 

There is some progress I can say. Initially I was trying to power up the GNSS module using the USB Type A to USB MIcro ( Laptop to the module). Now I tried with powering it up with the 3.3V from the MCU itself and while i do that I do get some interrupts. Initially I did doubt the reliability of jumper wires but now it is also cleared since I ensured continuity among wires. Since I dont have a scope or logic analyzer( i have ordered it - it might take some time), I cannot monitor the signals.

 

 

About the Interrupt that I received, the code parses the first character and then checks for the symbol '$". It didnt work.

So I increased the no. of characters to 10 then i received this output

swayamsidhmohanty_0-1737583485295.jpeg

 

Hello world is just to check the UART between the MCU and my computer. Please dont mind it.

 

The no that i get is 536871948. I find it strange that ASCII code for $ is 36 and G is 71. And in UART serial monitor I am getting NMEA sentences starting with '$G....' and the output we got somehow has these codes. 5-36-8-71-.... There is a character in between.

Is this meaningful data. If yes should we parse it this way.

 

What are your suggestions to read data using DMA over this character by character approach?

536871948 = 0x2000040C  the address of rxChar array in memory.

Your handler is now expecting 10 characters, you make no attempt to process them in that form

I'd recommend mastering C coding before trying DMA. Perhaps work with colleagues or supervisors to guide you.

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2025 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 */

/* 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;
DMA_HandleTypeDef hdma_usart1_rx;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_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 */
#define NMEA_BUFFER_SIZE 512
 uint8_t nmeaBuffer[NMEA_BUFFER_SIZE];

 uint8_t rxChar[10], rcvd_msg;

 volatile uint16_t nmeaIndex = 0;
 volatile uint8_t nmeaComplete = 0;
 volatile char nmeaSentence[NMEA_BUFFER_SIZE];

 /* GNSS configuration commands */
 GPIO_PinState Test_Jumper;

 const char* GNSS_SET_RATE_1HZ = "$PMSTK220,1000*1F\r\n";           // Set update rate to 1Hz
 uint8_t GNSS_SET_BAUD_9600[] = "$PSTMSETPAR,115200*17\r\n";          // Set baud rate to 9600
 const char* GNSS_SET_NMEA_OUTPUT = "$PMSTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28\r\n";  // Enable GGA and RMC sentences

void GNSS_Init()
{
    /* Send configuration commands to GNSS module */

//   UART_Start_Receive_DMA(&huart1, nmeaBuffer, NMEA_BUFFER_SIZE);

//    HAL_UART_Transmit(&huart1, (uint8_t*)GNSS_SET_BAUD_9600, 25, HAL_MAX_DELAY);
//    HAL_Delay(100);
//    HAL_UART_Transmit(&huart1, (uint8_t*)GNSS_SET_RATE_1HZ, strlen(GNSS_SET_RATE_1HZ), HAL_MAX_DELAY);
//    HAL_Delay(100);
//    HAL_UART_Transmit(&huart1, (uint8_t*)GNSS_SET_NMEA_OUTPUT, strlen(GNSS_SET_NMEA_OUTPUT), HAL_MAX_DELAY);
//    HAL_Delay(100);

   /* Start receiving data in interrupt mode */
   HAL_UART_Receive_IT(&huart1, &rxChar[0], sizeof(rxChar));
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  if (huart->Instance == USART1)
  {
    int i;
    for(i=0; i<sizeof(rxChar); i++) // For each character requested
    {
      if (rxChar[i] == '$')  // Start of NMEA sentence
      {
         nmeaIndex = 0;
      }
      if (nmeaIndex < NMEA_BUFFER_SIZE - 1)
      {
        nmeaBuffer[nmeaIndex++] = rxChar[i];

        if (rxChar[i] == '\n')  // End of NMEA sentence
        {
          nmeaBuffer[nmeaIndex] = '\0';
          if (nmeaComplete != 1)
          {
            strcpy(nmeaSentence, (char *)nmeaBuffer); // copy to an inactive buffer
            nmeaComplete = 1;
          }
        }
      }
      else
      {
        nmeaIndex = 0;  // Buffer overflow protection
      }

    /* Restart interrupt reception */
    HAL_UART_Receive_IT(&huart1, &rxChar[0], sizeof(rxChar));
  }
}

void USART2OutString(char *str)
{
  HAL_UART_Transmit(&huart2, (uint8_t *)str, strlen(str), HAL_MAX_DELAY);
}


void ProcessNMEASentence(char* sentence)
{
    /* Forward NMEA sentence to debug UART */
    USART2OutString(sentence);

    /* Add your NMEA parsing code here */

// strstr() seems like a poor choice the sentence starts at the first character

    /* Example: Check for specific NMEA sentences

    if (strstr(sentence, "$GPRMC") != NULL)
    {
        // Parse RMC sentence
    }
    else if(strstr((char*)sentence, "$GPGGA") != NULL)
    {
        // Parse GGA sentence
    }

    */
}

/* 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_DMA_Init();
  MX_USART1_UART_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  GNSS_Init();
  uint8_t data[] = "Hello world\n\r";
  char msg[100];

  USART2OutString(data);

  while (1)
  {
    Test_Jumper = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6);
    if (Test_Jumper)
      HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
    else
      HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);

    if (nmeaComplete)
    {
      ProcessNMEASentence(nmeaSentence);
      nmeaComplete = 0;
    }
  }
}

/**
  * @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.HSIDiv = RCC_HSI_DIV4;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  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_HSI;
  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_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 = 115200;
  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.Init.ClockPrescaler = UART_PRESCALER_DIV1;
  huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetTxFifoThreshold(&huart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetRxFifoThreshold(&huart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_DisableFifoMode(&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;
  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 */

}

/**
  * Enable DMA controller clock
  */
static void MX_DMA_Init(void)
{
  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();

  /* DMA interrupt init */
  /* DMA1_Channel1_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
}

/**
  * @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_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);

  /*Configure GPIO pin : PA5 */
  GPIO_InitStruct.Pin = GPIO_PIN_5;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pin : PA6 */
  GPIO_InitStruct.Pin = GPIO_PIN_6;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

/* 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 */
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..