Skocz do zawartości

HAL_Delay w while psuje wyniki z GPS


DeadGeneratio

Pomocna odpowiedź

Dobry wieczór, ciekawy i irytujący problem - wstawienie dowolnej długości delay do pętli while psuje odczyty z gps-a. Dowiedziałem się o tym gdy podłączyłem RTC i zacząłem z nim pracować, wszystkie wyniki z płytki GPS nagle stały się losowe i bezwartościowe. Czy ktoś podsunie pomysł o co może chodzić? To przykład dla kodu z pustą pętlą while:

image.thumb.png.71b9716cb44ff206df8c0d2c12c508de.png

A to przykład dla kodu gdzie  wpętli while jest tylko i wyłącznie HAL_Delay(200);

image.thumb.png.5fa61b5ec5cb9c712b26adb5738424dd.png

I dodatkowe pytanie - odpowiedziałem do swojego postu odnośnie FFT na F407 i widzę, że post nie pojawił się na szczycie, nie widać nawet dodatkowej odpowiedzi. Coś zostało zmienione na forum?

/* 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"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

#define GPS_BUFFER_SIZE 1024

#define RTC_ADDRESS 0xD0
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c1;

UART_HandleTypeDef huart1;

/* USER CODE BEGIN PV */

/* RTC SARTS HERE ------------------------------------------------------- */

typedef struct {
	uint8_t seconds;
	uint8_t minutes;
	uint8_t hour;
	uint8_t dayofweek;
	uint8_t dayofmonth;
	uint8_t month;
	uint8_t year;
} TIME;

TIME time;

/* RTC ENDS HERE ---------------------------------------------------------*/

/* GPS STARTS HERE ------------------------------------------------------ */

char rxBuffer[GPS_BUFFER_SIZE];

char nmeaSentence[82]; // Maksymalna długość zdania NMEA to 82 znaki

uint16_t bufferIndex = 0;

typedef struct {
	char utc_time[11];
	char latitude[11];
	char latitude_dir;
	char longitude[12];
	char longitude_dir;
	int fix_quality;
	int num_satellites;
	float hdop;
	float altitude;
	char altitude_units;
	float geoid_height;
	char geoid_height_units;
} GGAData;

typedef struct {
	char utc_time[11];
	char status;
	char latitude[11];
	char latitude_dir;
	char longitude[12];
	char longitude_dir;
	float speed_over_ground;
	float course_over_ground;
	char date[7];
	float magnetic_variation;
	char magnetic_variation_dir;
	char mode;
} RMCData;

typedef struct {
	int num_messages;
	int message_num;
	int num_sv;

	struct {
		int prn;
		int elevation;
		int azimuth;
		int snr;
	} satellites[4];
} GSVData;

typedef struct {
	char mode1;
	int mode2;
	int sat_used[12];
	float pdop;
	float hdop;
	float vdop;
} GSAData;

typedef struct {
	char utc_time[11];
	char latitude[11];
	char latitude_dir;
	char longitude[12];
	char longitude_dir;
	char status;
	char mode;
} GLLData;

typedef struct {
	float true_track;
	char true_track_sym;
	float mag_track;
	char mag_track_sym;
	float ground_speed_knots;
	char ground_speed_knots_sym;
	float ground_speed_kmph;
	char ground_speed_kmph_sym;
} VTGData;

typedef struct {
	int message_number;
	int total_messages;
	int message_type;
	char text[61];
} TXTData;

GGAData ggaData;
RMCData rmcData;
GSVData gsvData;
GSAData gsaData;
GLLData gllData;
VTGData vtgData;
TXTData txtData;

/* GPS ENDS HERE ------------------------------------------------------------*/

/* 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_I2C1_Init(void);
/* USER CODE BEGIN PFP */
void processNMEASentence(char *sentence);
void processGGA(char *sentence);
void processRMC(char *sentence);
void processGSV(char *sentence);
void processGSA(char *sentence);
void processGLL(char *sentence);
void processVTG(char *sentence);
void processTXT(char *sentence);
uint8_t decToBcd(int val);
int bcdToDec(uint8_t val);
void Set_Time(uint8_t sec, uint8_t min, uint8_t hour, uint8_t dow, uint8_t dom,
		uint8_t month, uint8_t year);
void Get_Time(void);

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
uint8_t decToBcd(int val) {
	return (uint8_t) ((val / 10 * 16) + (val % 10));
}
int bcdToDec(uint8_t val) {
	return (int) ((val / 16 * 10) + (val % 16));
}

void Set_Time(uint8_t sec, uint8_t min, uint8_t hour, uint8_t dow, uint8_t dom,
		uint8_t month, uint8_t year) {
	uint8_t set_time[7];
	set_time[0] = decToBcd(sec);
	set_time[1] = decToBcd(min);
	set_time[2] = decToBcd(hour);
	set_time[3] = decToBcd(dow);
	set_time[4] = decToBcd(dom);
	set_time[5] = decToBcd(month);
	set_time[6] = decToBcd(year);

	HAL_I2C_Mem_Write(&hi2c1, RTC_ADDRESS, 0x00, 1, set_time, 7, 1000);
}

void Get_Time(void) {
	uint8_t get_time[7];
	HAL_I2C_Mem_Read(&hi2c1, RTC_ADDRESS, 0x00, 1, get_time, 7, 1000);
	time.seconds = bcdToDec(get_time[0]);
	time.minutes = bcdToDec(get_time[1]);
	time.hour = bcdToDec(get_time[2]);
	time.dayofweek = bcdToDec(get_time[3]);
	time.dayofmonth = bcdToDec(get_time[4]);
	time.month = bcdToDec(get_time[5]);
	time.year = bcdToDec(get_time[6]);
}

void processNMEASentence(char *sentence) {
	if (strncmp(sentence, "$GPGGA", 6) == 0) {
		processGGA(sentence);
	} else if (strncmp(sentence, "$GPRMC", 6) == 0) {
		processRMC(sentence);
	} else if (strncmp(sentence, "$GPGSV", 6) == 0) {
		processGSV(sentence);
	} else if (strncmp(sentence, "$GPGSA", 6) == 0) {
		processGSA(sentence);
	} else if (strncmp(sentence, "$GPGLL", 6) == 0) {
		processGLL(sentence);
	} else if (strncmp(sentence, "$GPVTG", 6) == 0) {
		processVTG(sentence);
	} else if (strncmp(sentence, "$GPTXT", 6) == 0) {
		processTXT(sentence);
	}
}

void processGGA(char *sentence) {
	// Przetwarzanie $GPGGA
	sscanf(sentence,
			"$GPGGA,%10[^,],%10[^,],%c,%11[^,],%c,%d,%d,%f,%f,%c,%f,%c",
			ggaData.utc_time, ggaData.latitude, &ggaData.latitude_dir,
			ggaData.longitude, &ggaData.longitude_dir, &ggaData.fix_quality,
			&ggaData.num_satellites, &ggaData.hdop, &ggaData.altitude,
			&ggaData.altitude_units, &ggaData.geoid_height,
			&ggaData.geoid_height_units);
}

void processRMC(char *sentence) {
	// Przetwarzanie $GPRMC
	sscanf(sentence,
			"$GPRMC,%10[^,],%c,%10[^,],%c,%11[^,],%c,%f,%f,%6[^,],%f,%c,%c",
			rmcData.utc_time, &rmcData.status, rmcData.latitude,
			&rmcData.latitude_dir, rmcData.longitude, &rmcData.longitude_dir,
			&rmcData.speed_over_ground, &rmcData.course_over_ground,
			rmcData.date, &rmcData.magnetic_variation,
			&rmcData.magnetic_variation_dir, &rmcData.mode);
}

void processGSV(char *sentence) {
	// Przetwarzanie $GPGSV
	int num_messages, message_num, num_sv;
	int prn[4] = { 0 }, elevation[4] = { 0 }, azimuth[4] = { 0 },
			snr[4] = { 0 };

	// Parse the sentence
	sscanf(sentence, "$GPGSV,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
			&num_messages, &message_num, &num_sv, &prn[0], &elevation[0],
			&azimuth[0], &snr[0], &prn[1], &elevation[1], &azimuth[1], &snr[1],
			&prn[2], &elevation[2], &azimuth[2], &snr[2], &prn[3],
			&elevation[3], &azimuth[3], &snr[3]);

	// Store the parsed data in the global structure
	gsvData.num_messages = num_messages;
	gsvData.message_num = message_num;
	gsvData.num_sv = num_sv;

	for (int i = 0; i < 4; i++) {
		gsvData.satellites[i].prn = prn[i];
		gsvData.satellites[i].elevation = elevation[i];
		gsvData.satellites[i].azimuth = azimuth[i];
		gsvData.satellites[i].snr = snr[i];
	}
}

void processGSA(char *sentence) {
	// Przetwarzanie $GPGSA
	sscanf(sentence, "$GPGSA,%c,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%f,%f,%f",
			&gsaData.mode1, &gsaData.mode2, &gsaData.sat_used[0],
			&gsaData.sat_used[1], &gsaData.sat_used[2], &gsaData.sat_used[3],
			&gsaData.sat_used[4], &gsaData.sat_used[5], &gsaData.sat_used[6],
			&gsaData.sat_used[7], &gsaData.sat_used[8], &gsaData.sat_used[9],
			&gsaData.sat_used[10], &gsaData.sat_used[11], &gsaData.pdop,
			&gsaData.hdop, &gsaData.vdop);
}

void processGLL(char *sentence) {
	// Przetwarzanie $GPGLL
	sscanf(sentence, "$GPGLL,%10[^,],%c,%11[^,],%c,%10[^,],%c,%c",
			gllData.latitude, &gllData.latitude_dir, gllData.longitude,
			&gllData.longitude_dir, gllData.utc_time, &gllData.status,
			&gllData.mode);
}

void processVTG(char *sentence) {
	// Przetwarzanie $GPVTG
	sscanf(sentence, "$GPVTG,%f,%c,%f,%c,%f,%c,%f,%c", &vtgData.true_track,
			&vtgData.true_track_sym, &vtgData.mag_track, &vtgData.mag_track_sym,
			&vtgData.ground_speed_knots, &vtgData.ground_speed_knots_sym,
			&vtgData.ground_speed_kmph, &vtgData.ground_speed_kmph_sym);
}

void processTXT(char *sentence) {
	// Przetwarzanie $GPTXT
	sscanf(sentence, "$GPTXT,%d,%d,%d,%60[^\n]", &txtData.message_number,
			&txtData.total_messages, &txtData.message_type, txtData.text);
}
/* 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_USART1_UART_Init();
  MX_I2C1_Init();
  /* USER CODE BEGIN 2 */
	HAL_UART_Receive_IT(&huart1, (uint8_t*) rxBuffer, 1);

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
	while (1) {
    /* 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};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** 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 I2C1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_I2C1_Init(void)
{

  /* USER CODE BEGIN I2C1_Init 0 */

  /* USER CODE END I2C1_Init 0 */

  /* USER CODE BEGIN I2C1_Init 1 */

  /* USER CODE END I2C1_Init 1 */
  hi2c1.Instance = I2C1;
  hi2c1.Init.ClockSpeed = 100000;
  hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c1.Init.OwnAddress1 = 0;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN I2C1_Init 2 */

  /* USER CODE END I2C1_Init 2 */

}

/**
  * @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 GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}

/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
	if (huart->Instance == USART1) {
		char receivedChar;
		HAL_UART_Receive_IT(&huart1, (uint8_t*) &receivedChar, 1);
		if (receivedChar == '$') {
			bufferIndex = 0;
		}
		if (bufferIndex < GPS_BUFFER_SIZE - 1) {
			rxBuffer[bufferIndex++] = receivedChar;
			rxBuffer[bufferIndex] = '\0'; // Null-terminate string

			if (receivedChar == '\n' && bufferIndex > 1
					&& rxBuffer[bufferIndex - 2] == '\r') {
				strncpy(nmeaSentence, rxBuffer, bufferIndex);
				nmeaSentence[bufferIndex] = '\0';
				processNMEASentence(nmeaSentence);
				bufferIndex = 0;
			}
		} else {
			bufferIndex = 0;
		}
	}
}



/* 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 */

GPS.zip

Edytowano przez DeadGeneratio
Link do komentarza
Share on other sites

@DeadGeneratio odczytujesz to po UARCIE w przerwaniu po 1 znaku? 

	HAL_UART_Receive_IT(&huart1, (uint8_t*) rxBuffer, 1);

Dodaj obsługę błędu od UARTu. Spróbuj też innej metody niż odczytywanie po 1 znaku. Np UARTex ma funkcję z odczytyweaniem do sygnału idle z DMA dla nieznanego rozmiaru danych.

Sprawdź priorytety, 0 to najwyższy. Sprawdź czy nie kłuci się z timerem od delaya.

I nie używaj delay 😄

Link do komentarza
Share on other sites

@Gineq poprawiłem kod na odbiór przez DMA, wszystko śmiga ładnie. No można powiedzieć, że prawie ładnie bo moduł ma rozrzut dokładności o około 100m, ale obstawiam, że to wina odbierania sygnału w mieszkaniu. Dodałem sobie także RTC oraz aktualizowanie RTC względem czasu GPS. Obecnie będę się męczył nad implementacją wyświetlacza e-ink.

/* 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 "DS3231.h"
#include "stdlib.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 ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c1;
DMA_HandleTypeDef hdma_i2c1_rx;
DMA_HandleTypeDef hdma_i2c1_tx;

SPI_HandleTypeDef hspi1;

TIM_HandleTypeDef htim14;

UART_HandleTypeDef huart1;
DMA_HandleTypeDef hdma_usart1_rx;

/* USER CODE BEGIN PV */

/* RTC STARTS HERE ------------------------------------------------------------------ */

/* RTC ENDS HERE -------------------------------------------------------------------- */

RTCDateTime RTC_time;

/* GPS STARTS HERE ------------------------------------------------------------------ */

#define GPS_BUFFER_SIZE 512
#define NMEA_SIZE 86

char rxBuffer[GPS_BUFFER_SIZE];
char GGA_sentence[NMEA_SIZE]; // Global Positioning System Fix Data
char RMC_sentence[NMEA_SIZE]; // Recommended Minimum Navigation Information
char GSV_sentence[NMEA_SIZE]; // GNSS Satelites in View
char GSA_sentence[NMEA_SIZE]; // GNSS DOP and Active Satellites
char GLL_sentence[NMEA_SIZE]; // Geographic Position - Latitude/Longitude
char VTG_sentence[NMEA_SIZE]; // Track mode good and Ground speed
char TXT_sentence[NMEA_SIZE]; // Inne dane

typedef struct {
	char utc_time[11];
	char latitude[11];
	char latitude_dir;
	char longitude[12];
	char longitude_dir;
	int fix_quality;
	int num_satellites;
	float hdop;
	float altitude;
	char altitude_units;
	float geoid_height;
	char geoid_height_units;
} GGAData;

typedef struct {
	char utc_time[11];
	char status;
	char latitude[11];
	char latitude_dir;
	char longitude[12];
	char longitude_dir;
	float speed_over_ground;
	float course_over_ground;
	char date[7];
	float magnetic_variation;
	char magnetic_variation_dir;
	char mode;
} RMCData;

typedef struct {
	int num_messages;
	int message_num;
	int num_sv;

	struct {
		int prn;
		int elevation;
		int azimuth;
		int snr;
	} satellites[4];
} GSVData;

typedef struct {
	char mode1;
	int mode2;
	int sat_used[12];
	float pdop;
	float hdop;
	float vdop;
} GSAData;

typedef struct {
	char utc_time[11];
	char latitude[11];
	char latitude_dir;
	char longitude[12];
	char longitude_dir;
	char status;
	char mode;
} GLLData;

typedef struct {
	float true_track;
	char true_track_sym;
	float mag_track;
	char mag_track_sym;
	float ground_speed_knots;
	char ground_speed_knots_sym;
	float ground_speed_kmph;
	char ground_speed_kmph_sym;
} VTGData;

typedef struct {
	int message_number;
	int total_messages;
	int message_type;
	char text[61];
} TXTData;

GGAData ggaData;
RMCData rmcData;
GSVData gsvData;
GSAData gsaData;
GLLData gllData;
VTGData vtgData;
TXTData txtData;

/* GPS ENDS HERE ------------------------------------------------------------------------ */

/* 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_I2C1_Init(void);
static void MX_TIM14_Init(void);
static void MX_SPI1_Init(void);
/* USER CODE BEGIN PFP */
void processGGA(char *sentence);
void processRMC(char *sentence);
void processGSV(char *sentence);
void processGSA(char *sentence);
void processGLL(char *sentence);
void processVTG(char *sentence);
void processTXT(char *sentence);
/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void processGGA(char *sentence) {
	sscanf(sentence,
			"$GPGGA,%10[^,],%10[^,],%c,%11[^,],%c,%d,%d,%f,%f,%c,%f,%c",
			ggaData.utc_time, ggaData.latitude, &ggaData.latitude_dir,
			ggaData.longitude, &ggaData.longitude_dir, &ggaData.fix_quality,
			&ggaData.num_satellites, &ggaData.hdop, &ggaData.altitude,
			&ggaData.altitude_units, &ggaData.geoid_height,
			&ggaData.geoid_height_units);
}

void processRMC(char *sentence) {
	sscanf(sentence,
			"$GPRMC,%10[^,],%c,%10[^,],%c,%11[^,],%c,%f,%f,%6[^,],%f,%c,%c",
			rmcData.utc_time, &rmcData.status, rmcData.latitude,
			&rmcData.latitude_dir, rmcData.longitude, &rmcData.longitude_dir,
			&rmcData.speed_over_ground, &rmcData.course_over_ground,
			rmcData.date, &rmcData.magnetic_variation,
			&rmcData.magnetic_variation_dir, &rmcData.mode);
}

void processGSV(char *sentence) {
	int num_messages, message_num, num_sv;
	int prn[4] = { 0 }, elevation[4] = { 0 }, azimuth[4] = { 0 },
			snr[4] = { 0 };

	sscanf(sentence, "$GPGSV,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
			&num_messages, &message_num, &num_sv, &prn[0], &elevation[0],
			&azimuth[0], &snr[0], &prn[1], &elevation[1], &azimuth[1], &snr[1],
			&prn[2], &elevation[2], &azimuth[2], &snr[2], &prn[3],
			&elevation[3], &azimuth[3], &snr[3]);

	gsvData.num_messages = num_messages;
	gsvData.message_num = message_num;
	gsvData.num_sv = num_sv;

	for (int i = 0; i < 4; i++) {
		gsvData.satellites[i].prn = prn[i];
		gsvData.satellites[i].elevation = elevation[i];
		gsvData.satellites[i].azimuth = azimuth[i];
		gsvData.satellites[i].snr = snr[i];
	}
}

void processGSA(char *sentence) {
	sscanf(sentence, "$GPGSA,%c,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%f,%f,%f",
			&gsaData.mode1, &gsaData.mode2, &gsaData.sat_used[0],
			&gsaData.sat_used[1], &gsaData.sat_used[2], &gsaData.sat_used[3],
			&gsaData.sat_used[4], &gsaData.sat_used[5], &gsaData.sat_used[6],
			&gsaData.sat_used[7], &gsaData.sat_used[8], &gsaData.sat_used[9],
			&gsaData.sat_used[10], &gsaData.sat_used[11], &gsaData.pdop,
			&gsaData.hdop, &gsaData.vdop);
}

void processGLL(char *sentence) {
	sscanf(sentence, "$GPGLL,%10[^,],%c,%11[^,],%c,%10[^,],%c,%c",
			gllData.latitude, &gllData.latitude_dir, gllData.longitude,
			&gllData.longitude_dir, gllData.utc_time, &gllData.status,
			&gllData.mode);
}

void processVTG(char *sentence) {
	sscanf(sentence, "$GPVTG,%f,%c,%f,%c,%f,%c,%f,%c", &vtgData.true_track,
			&vtgData.true_track_sym, &vtgData.mag_track, &vtgData.mag_track_sym,
			&vtgData.ground_speed_knots, &vtgData.ground_speed_knots_sym,
			&vtgData.ground_speed_kmph, &vtgData.ground_speed_kmph_sym);
}

void processTXT(char *sentence) {
	sscanf(sentence, "$GPTXT,%d,%d,%d,%60[^\n]", &txtData.message_number,
			&txtData.total_messages, &txtData.message_type, txtData.text);
}
/* 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_I2C1_Init();
  MX_TIM14_Init();
  MX_SPI1_Init();
  /* USER CODE BEGIN 2 */
	HAL_UART_Receive_DMA(&huart1, (uint8_t*) rxBuffer, GPS_BUFFER_SIZE);
	DS3231_Init(&hi2c1);

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
	while (1) {
    /* 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};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** 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_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = 8;
  RCC_OscInitStruct.PLL.PLLN = 64;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 2;
  RCC_OscInitStruct.PLL.PLLR = 2;
  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_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV2;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief I2C1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_I2C1_Init(void)
{

  /* USER CODE BEGIN I2C1_Init 0 */

  /* USER CODE END I2C1_Init 0 */

  /* USER CODE BEGIN I2C1_Init 1 */

  /* USER CODE END I2C1_Init 1 */
  hi2c1.Instance = I2C1;
  hi2c1.Init.ClockSpeed = 400000;
  hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c1.Init.OwnAddress1 = 0;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN I2C1_Init 2 */

  /* USER CODE END I2C1_Init 2 */

}

/**
  * @brief SPI1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_SPI1_Init(void)
{

  /* USER CODE BEGIN SPI1_Init 0 */

  /* USER CODE END SPI1_Init 0 */

  /* USER CODE BEGIN SPI1_Init 1 */

  /* USER CODE END SPI1_Init 1 */
  /* SPI1 parameter configuration*/
  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;
  hspi1.Init.Direction = SPI_DIRECTION_1LINE;
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 10;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI1_Init 2 */

  /* USER CODE END SPI1_Init 2 */

}

/**
  * @brief TIM14 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM14_Init(void)
{

  /* USER CODE BEGIN TIM14_Init 0 */

  /* USER CODE END TIM14_Init 0 */

  /* USER CODE BEGIN TIM14_Init 1 */

  /* USER CODE END TIM14_Init 1 */
  htim14.Instance = TIM14;
  htim14.Init.Prescaler = 32000-1;
  htim14.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim14.Init.Period = 60000-1;
  htim14.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim14.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  if (HAL_TIM_Base_Init(&htim14) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM14_Init 2 */

  /* USER CODE END TIM14_Init 2 */

}

/**
  * @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 */

}

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

  /* DMA controller clock enable */
  __HAL_RCC_DMA2_CLK_ENABLE();
  __HAL_RCC_DMA1_CLK_ENABLE();

  /* DMA interrupt init */
  /* DMA1_Stream0_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);
  /* DMA1_Stream1_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
  /* DMA2_Stream2_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA2_Stream2_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_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, EPAPER_RST_Pin|EPAPER_CS_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(EPAPER_DC_GPIO_Port, EPAPER_DC_Pin, GPIO_PIN_RESET);

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

  /*Configure GPIO pins : EPAPER_RST_Pin EPAPER_CS_Pin */
  GPIO_InitStruct.Pin = EPAPER_RST_Pin|EPAPER_CS_Pin;
  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 : EPAPER_DC_Pin */
  GPIO_InitStruct.Pin = EPAPER_DC_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(EPAPER_DC_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : DS3231_INT_Pin */
  GPIO_InitStruct.Pin = DS3231_INT_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(DS3231_INT_GPIO_Port, &GPIO_InitStruct);

  /* EXTI interrupt init*/
  HAL_NVIC_SetPriority(EXTI9_5_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);

/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}

/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
	if (huart->Instance == USART1) {
		char *start_ptr;

		start_ptr = strstr((char*) rxBuffer, "$GPGGA");
		if (start_ptr != NULL) {
			char *end_ptr = strchr(start_ptr, '\r');
			if (end_ptr != NULL) {
				size_t length = end_ptr - start_ptr;
				strncpy(GGA_sentence, start_ptr, length);
				memset(GGA_sentence + length, 0, NMEA_SIZE - length);
				processGGA(GGA_sentence);
			}
		}

		start_ptr = strstr((char*) rxBuffer, "$GPRMC");
		if (start_ptr != NULL) {
			char *end_ptr = strchr(start_ptr, '\r');
			if (end_ptr != NULL) {
				size_t length = end_ptr - start_ptr;
				strncpy(RMC_sentence, start_ptr, length);
				memset(RMC_sentence + length, 0, NMEA_SIZE - length);
				processRMC(RMC_sentence);
			}
		}

		start_ptr = strstr((char*) rxBuffer, "$GPGSV");
		if (start_ptr != NULL) {
			char *end_ptr = strchr(start_ptr, '\r');
			if (end_ptr != NULL) {
				size_t length = end_ptr - start_ptr;
				strncpy(GSV_sentence, start_ptr, length);
				memset(GSV_sentence + length, 0, NMEA_SIZE - length);
				processGSV(GSV_sentence);
			}
		}

		start_ptr = strstr((char*) rxBuffer, "$GPGSA");
		if (start_ptr != NULL) {
			char *end_ptr = strchr(start_ptr, '\r');
			if (end_ptr != NULL) {
				size_t length = end_ptr - start_ptr;
				strncpy(GSA_sentence, start_ptr, length);
				memset(GSA_sentence + length, 0, NMEA_SIZE - length);
				processGSA(GSA_sentence);
			}
		}

		start_ptr = strstr((char*) rxBuffer, "$GPGLL");
		if (start_ptr != NULL) {
			char *end_ptr = strchr(start_ptr, '\r');
			if (end_ptr != NULL) {
				size_t length = end_ptr - start_ptr;
				strncpy(GLL_sentence, start_ptr, length);
				memset(GLL_sentence + length, 0, NMEA_SIZE - length);
				processGLL(GLL_sentence);
			}
		}

		start_ptr = strstr((char*) rxBuffer, "$GPVTG");
		if (start_ptr != NULL) {
			char *end_ptr = strchr(start_ptr, '\r');
			if (end_ptr != NULL) {
				size_t length = end_ptr - start_ptr;
				strncpy(VTG_sentence, start_ptr, length);
				memset(VTG_sentence + length, 0, NMEA_SIZE - length);
				processVTG(VTG_sentence);
			}
		}

		start_ptr = strstr((char*) rxBuffer, "$GPTXT");
		if (start_ptr != NULL) {
			char *end_ptr = strchr(start_ptr, '\r');
			if (end_ptr != NULL) {
				size_t length = end_ptr - start_ptr;
				strncpy(TXT_sentence, start_ptr, length);
				memset(TXT_sentence + length, 0, NMEA_SIZE - length);
				processTXT(TXT_sentence);
			}
		}
		HAL_UART_Receive_DMA(&huart1, (uint8_t*) rxBuffer, GPS_BUFFER_SIZE);
	}
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
	if (GPIO_Pin == DS3231_INT_Pin) {
		DS3231_ReceiveDateTimeDMA();
	}
}

void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c) {
	DS3231_CalculateDateTime(&RTC_time);
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
	if (htim == &htim14) {
		if (ggaData.fix_quality > 0 && rmcData.status == 'A') {
			if (abs(RTC_time.Second - atoi(rmcData.utc_time + 4)) > 20
					|| RTC_time.Minute != atoi(rmcData.utc_time + 2)
					|| RTC_time.Hour != atoi(rmcData.utc_time)
					|| RTC_time.Day != atoi(rmcData.date + 0)
					|| RTC_time.Month != atoi(rmcData.date + 2)
					|| RTC_time.Year != 2000 + atoi(rmcData.date + 4)) {

				RTC_time.Second = atoi(rmcData.utc_time + 4);
				RTC_time.Minute = atoi(rmcData.utc_time + 2);
				RTC_time.Hour = atoi(rmcData.utc_time) + 2;
				RTC_time.Day = atoi(rmcData.date + 0);
				RTC_time.Month = atoi(rmcData.date + 2);
				RTC_time.Year = 2000 + atoi(rmcData.date + 4);

				DS3231_SetDateTime(&RTC_time);
			}
		}
	}
}

/* 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 */

 

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.