前言
在全球化的今天,时间同步已经成为各行各业不可或缺的重要技术。无论是通信、金融、电力、交通还是国防等领域,都需要高精度的时间基准来确保系统的稳定运行和数据的准确性。GPS(全球定位系统)和北斗(中国自主研发的全球卫星导航系统)作为两大主流的卫星导航系统,都提供了授时服务,为全球用户提供了可靠的时间基准。
GPS授时系统是全球范围内应用最广泛的授时系统之一。它利用GPS卫星发射的信号,通过接收和处理这些信号,用户可以获取到高精度的时间信息。GPS授时系统具有覆盖范围广、精度高、稳定性好等优点,被广泛应用于各个领域。
而北斗授时系统则是中国自主研发的卫星导航系统提供的授时服务。北斗系统是我国自主建设运行的全球卫星导航系统,是为全球用户提供定位、导航和授时服务的国家重要空间基础设施。北斗授时系统同样具有高精度、高稳定性和广泛的应用领域。与GPS授时系统相比,北斗授时系统具有自主可控、兼容并蓄等优势,可以更好地满足国家安全和社会经济发展的需求。
硬件框图说明
整个硬件设计是基于STM32G030CBT6进行的,采用了国产的GPS+北斗的双模授时模块。使用SMA的天线接口,支持有源和无源天线,对外还有RS485通信接口,完成对外的数据传输功能,RS485通信距离可以达到1200米,支持室内到室外以及隧道到露天的应用场景。
STM32F030C8T6作为一款高性能、低功耗的32位ARM Cortex-M0系列微控制器,具有丰富的外设接口和高速存储器,适用于多种嵌入式应用场景。其易于开发和集成的特性,使得开发者能够快速实现产品的智能化和自动化控制。同时,STM32F030C8T6的广泛应用领域也为其在市场上赢得了广泛的认可和好评。
GPS北斗双模模块具有体积小,响应速度块的特点, 基于中科微第四代采用完全自主 知识产权的低功耗 GNSS SOC 芯片-AT6558,支持多种卫星导航系统,包括中国的 BDS(北斗卫星导航系统),美国的 GPS,俄罗斯的 GLONASS,欧盟的 GALILEO,日本的 QZSS 以及卫星增强系统 SBAS(WAAS,EGNOS,GAGANMSAS)。ATGM336H 是一款真正意义的六合一多模卫星导航模块,包含32个跟踪通道可以同时接收六个卫星导航系统的 GNSS信号,并且实现联合定位、导航与授时。具有高灵敏度、低功耗、低成本等优势,适用于车载定位与导航和手持或可穿戴设备,可以直接替换 U-blox MAX 系列模块。
硬件设计
整个硬件设计主要是以外观小巧功能强大来设计,整个模块化的设计都按照工业级要求来精心设计的。
整个硬件的设计相对比较简单,但是应该有的保护功能都还是做到了的,电路电源使用宽电压芯片设计,支持常用的12V以及24V的工业电源模块供电,RS485接口使用了自动收发的设计,节约了MCU的IO口资源,也简化了操作的程序。
PCB整个尺寸非常小,配有四个安装孔,方便进行小型化的生产。
整个模块设计焊接的效果如上图所示,带有对外的通信接口以及模块的供电接口,以及SMA的天线接口。
软件设计
软件设计流程图也相对比较简单使用通用的穿行接口进行对模块的配置以及复位和初始化的工作,然后判断模块输出的秒脉冲以及位置信号是否有效进行处理,如果有效的话就进行时间的更新,没模块每500ms更新一次数据,保证数据的实时性。
软件代码具体如下:
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);
//--复位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 //定义最大接收字节数 200
unsigned int point1=0;
unsigned char USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
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"这一帧数据
{
if(Res == '\n')
{
memset(GPS_Value.GPS_Buffer, 0, GPS_Buffer_Length); //清空
memcpy(GPS_Value.GPS_Buffer, USART_RX_BUF, point1); //保存数据
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; //获取经度信息
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数据处理终端的相关代码。
#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("北斗数据:");
printf("UTC: %s",GPS_Value.UTCTime);
}
}
上面是我们主函数轮询处理的逻辑代码。
总 结
随着科技的不断发展,GPS和北斗授时系统都在不断完善和升级。例如,北斗系统已经经历了北斗一号、北斗二号和北斗三号三个阶段的发展,目前北斗三号卫星导航系统已经正式开通,并提前半年完成组网。这使得北斗授时系统的精度和稳定性得到了进一步提升,应用领域也更加广泛。
同时,随着5G时代的到来,各式创新应用对时间和位置感知有了更高的要求。高精度授时技术不仅可以提高系统的运行效率和准确性,还可以为各种创新应用提供有力的技术支撑。因此,GPS和北斗授时系统将在未来发挥更加重要的作用。
整个的视频链接如下,欢迎大家点评:
https://www.bilibili.com/video/BV1aXSMYVEhE/?spm_id_from=333.999.0.0
视频演示: