前言
在全球化的今天,時間同步已經(jīng)成為各行各業(yè)不可或缺的重要技術(shù)。無論是通信、金融、電力、交通還是國防等領(lǐng)域,都需要高精度的時間基準(zhǔn)來確保系統(tǒng)的穩(wěn)定運行和數(shù)據(jù)的準(zhǔn)確性。GPS(全球定位系統(tǒng))和北斗(中國自主研發(fā)的全球衛(wèi)星導(dǎo)航系統(tǒng))作為兩大主流的衛(wèi)星導(dǎo)航系統(tǒng),都提供了授時服務(wù),為全球用戶提供了可靠的時間基準(zhǔn)。
GPS授時系統(tǒng)是全球范圍內(nèi)應(yīng)用最廣泛的授時系統(tǒng)之一。它利用GPS衛(wèi)星發(fā)射的信號,通過接收和處理這些信號,用戶可以獲取到高精度的時間信息。GPS授時系統(tǒng)具有覆蓋范圍廣、精度高、穩(wěn)定性好等優(yōu)點,被廣泛應(yīng)用于各個領(lǐng)域。
而北斗授時系統(tǒng)則是中國自主研發(fā)的衛(wèi)星導(dǎo)航系統(tǒng)提供的授時服務(wù)。北斗系統(tǒng)是我國自主建設(shè)運行的全球衛(wèi)星導(dǎo)航系統(tǒng),是為全球用戶提供定位、導(dǎo)航和授時服務(wù)的國家重要空間基礎(chǔ)設(shè)施。北斗授時系統(tǒng)同樣具有高精度、高穩(wěn)定性和廣泛的應(yīng)用領(lǐng)域。與GPS授時系統(tǒng)相比,北斗授時系統(tǒng)具有自主可控、兼容并蓄等優(yōu)勢,可以更好地滿足國家安全和社會經(jīng)濟發(fā)展的需求。
硬件框圖說明
整個硬件設(shè)計是基于STM32G030CBT6進行的,采用了國產(chǎn)的GPS+北斗的雙模授時模塊。使用SMA的天線接口,支持有源和無源天線,對外還有RS485通信接口,完成對外的數(shù)據(jù)傳輸功能,RS485通信距離可以達到1200米,支持室內(nèi)到室外以及隧道到露天的應(yīng)用場景。
STM32F030C8T6作為一款高性能、低功耗的32位ARM Cortex-M0系列微控制器,具有豐富的外設(shè)接口和高速存儲器,適用于多種嵌入式應(yīng)用場景。其易于開發(fā)和集成的特性,使得開發(fā)者能夠快速實現(xiàn)產(chǎn)品的智能化和自動化控制。同時,STM32F030C8T6的廣泛應(yīng)用領(lǐng)域也為其在市場上贏得了廣泛的認(rèn)可和好評。
GPS北斗雙模模塊具有體積小,響應(yīng)速度塊的特點, 基于中科微第四代采用完全自主 知識產(chǎn)權(quán)的低功耗 GNSS SOC 芯片-AT6558,支持多種衛(wèi)星導(dǎo)航系統(tǒng),包括中國的 BDS(北斗衛(wèi)星導(dǎo)航系統(tǒng)),美國的 GPS,俄羅斯的 GLONASS,歐盟的 GALILEO,日本的 QZSS 以及衛(wèi)星增強系統(tǒng) SBAS(WAAS,EGNOS,GAGANMSAS)。ATGM336H 是一款真正意義的六合一多模衛(wèi)星導(dǎo)航模塊,包含32個跟蹤通道可以同時接收六個衛(wèi)星導(dǎo)航系統(tǒng)的 GNSS信號,并且實現(xiàn)聯(lián)合定位、導(dǎo)航與授時。具有高靈敏度、低功耗、低成本等優(yōu)勢,適用于車載定位與導(dǎo)航和手持或可穿戴設(shè)備,可以直接替換 U-blox MAX 系列模塊。
硬件設(shè)計
整個硬件設(shè)計主要是以外觀小巧功能強大來設(shè)計,整個模塊化的設(shè)計都按照工業(yè)級要求來精心設(shè)計的。
整個硬件的設(shè)計相對比較簡單,但是應(yīng)該有的保護功能都還是做到了的,電路電源使用寬電壓芯片設(shè)計,支持常用的12V以及24V的工業(yè)電源模塊供電,RS485接口使用了自動收發(fā)的設(shè)計,節(jié)約了MCU的IO口資源,也簡化了操作的程序。
PCB整個尺寸非常小,配有四個安裝孔,方便進行小型化的生產(chǎn)。
整個模塊設(shè)計焊接的效果如上圖所示,帶有對外的通信接口以及模塊的供電接口,以及SMA的天線接口。
軟件設(shè)計
軟件設(shè)計流程圖也相對比較簡單使用通用的穿行接口進行對模塊的配置以及復(fù)位和初始化的工作,然后判斷模塊輸出的秒脈沖以及位置信號是否有效進行處理,如果有效的話就進行時間的更新,沒模塊每500ms更新一次數(shù)據(jù),保證數(shù)據(jù)的實時性。
軟件代碼具體如下:
void Clear_GPS_Struct(void)
{
GPS_Value.isGetData = false;
GPS_Value.isParseData = false;
GPS_Value.isUsefull = false;
memset(GPS_Value.GPS_Buffer, 0, GPS_Buffer_Length); //清空
memset(GPS_Value.UTCTime, 0, UTCTime_Length);
memset(GPS_Value.latitude, 0, latitude_Length);
memset(GPS_Value.N_S, 0, N_S_Length);
memset(GPS_Value.longitude, 0, longitude_Length);
memset(GPS_Value.E_W, 0, E_W_Length);
}
void GPS_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
//--GPS_RST
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Pin = GPIO_PIN_8;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
//--GPS_ON_OFF
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Pin = GPIO_PIN_12;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
//--GPS_PPS
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Pin = GPIO_PIN_11;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
//--復(fù)位GPS--
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_8,0);
HAL_Delay(500);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_8,1);
HAL_Delay(500);
//--GPS -ON --
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_12,1);
}
#define USART_REC_LEN 200 //定義最大接收字節(jié)數(shù) 200
unsigned int point1=0;
unsigned char USART_RX_BUF[USART_REC_LEN]; //接收緩沖,最大USART_REC_LEN個字節(jié).
void GPS_Process(unsigned char Res )
{
if(Res == '$')
{
point1 = 0;
}
USART_RX_BUF[point1++] = Res;
if(USART_RX_BUF[0] == '$' && USART_RX_BUF[4] == 'M' && USART_RX_BUF[5] == 'C') //確定是否收到"GPRMC/GNRMC"這一幀數(shù)據(jù)
{
if(Res == '\n')
{
memset(GPS_Value.GPS_Buffer, 0, GPS_Buffer_Length); //清空
memcpy(GPS_Value.GPS_Buffer, USART_RX_BUF, point1); //保存數(shù)據(jù)
GPS_Value.isGetData = true;
point1 = 0;
memset(USART_RX_BUF, 0, USART_REC_LEN); //清空
}
}
if(point1 >= USART_REC_LEN)
{
point1 = USART_REC_LEN;
}
}
void parseGpsBuffer(void)
{
char *subString;
char *subStringNext;
char i = 0;
if (GPS_Value.isGetData)
{
GPS_Value.isGetData = false;
for (i = 0 ; i <= 6 ; i++)
{
if (i == 0)
{
if ((subString = strstr(GPS_Value.GPS_Buffer, ",")) == NULL)
{
}
}
else
{
subString++;
if ((subStringNext = strstr(subString, ",")) != NULL)
{
char usefullBuffer[2];
switch(i)
{
case 1:memcpy(GPS_Value.UTCTime, subString, subStringNext - subString);break; //獲取UTC時間
case 2:memcpy(usefullBuffer, subString, subStringNext - subString);break; //獲取UTC時間
case 3:memcpy(GPS_Value.latitude, subString, subStringNext - subString);break; //獲取緯度信息
case 4:memcpy(GPS_Value.N_S, subString, subStringNext - subString);break; //獲取N/S
case 5:memcpy(GPS_Value.longitude, subString, subStringNext - subString);break; //獲取經(jīng)度信息
case 6:memcpy(GPS_Value.E_W, subString, subStringNext - subString);break; //獲取E/W
default:break;
}
subString = subStringNext;
GPS_Value.isParseData = true;
if(usefullBuffer[0] == 'A')
GPS_Value.isUsefull = true;
else if(usefullBuffer[0] == 'V')
GPS_Value.isUsefull = false;
}
else
{
}
}
}
}
}
上面是PGS數(shù)據(jù)處理終端的相關(guān)代碼。
#include "stm32g0xx_hal.h"
#include "DRV_IO.h"
#include "DRV_SHTC3.h"
#include "DRV_UART.h"
#include "GPS_Process.h"
int main(void)
{
HAL_Init();
SystemClock_Config();
LED_Init();
UART_Init();
while (1)
{
LED_Test();
parseGpsBuffer();
printf("北斗數(shù)據(jù):");
printf("UTC: %s",GPS_Value.UTCTime);
}
}
上面是我們主函數(shù)輪詢處理的邏輯代碼。
總 結(jié)
隨著科技的不斷發(fā)展,GPS和北斗授時系統(tǒng)都在不斷完善和升級。例如,北斗系統(tǒng)已經(jīng)經(jīng)歷了北斗一號、北斗二號和北斗三號三個階段的發(fā)展,目前北斗三號衛(wèi)星導(dǎo)航系統(tǒng)已經(jīng)正式開通,并提前半年完成組網(wǎng)。這使得北斗授時系統(tǒng)的精度和穩(wěn)定性得到了進一步提升,應(yīng)用領(lǐng)域也更加廣泛。
同時,隨著5G時代的到來,各式創(chuàng)新應(yīng)用對時間和位置感知有了更高的要求。高精度授時技術(shù)不僅可以提高系統(tǒng)的運行效率和準(zhǔn)確性,還可以為各種創(chuàng)新應(yīng)用提供有力的技術(shù)支撐。因此,GPS和北斗授時系統(tǒng)將在未來發(fā)揮更加重要的作用。
整個的視頻鏈接如下,歡迎大家點評:
https://www.bilibili.com/video/BV1aXSMYVEhE/?spm_id_from=333.999.0.0
視頻演示: