STM32F407ZGT6笔记15:G60_GPS北斗导航模块_串口通信

发布于:2025-04-07 ⋅ 阅读:(29) ⋅ 点赞:(0)

这里记录下SYTM32驱动一个模块的程序

主要是因为,官方给的例程是HAL库的,这里我改成标准库的形式写一遍:

文章提供测试代码讲解、完整工程下载、测试效果图

目录

串口1中断:

数据处理:

主函数调用:

按键程序:

测试效果视频:

完整工程下载:


串口1中断:

1

void USART1_IRQHandler(void) // 串口1中断服务程序
{
    u8 Res;
    if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) // 接收中断
    {
        Res = USART_ReceiveData(USART1); // 读取接收到的数据
        
        if (Res == '$') point1 = 0;
        USART_RX_BUF[point1++] = Res;
        
        if (USART_RX_BUF[0] == '$' && USART_RX_BUF[4] == 'M' && USART_RX_BUF[5] == 'C' )
        {
            if (Res == '\n')
            {
                memset(Save_Data.GPS_Buffer, 0, GPS_Buffer_Length); // 清空
                memcpy(Save_Data.GPS_Buffer, USART_RX_BUF, point1); // 保存数据
                Save_Data.isGetData = true;
                point1 = 0;
                memset(USART_RX_BUF, 0, USART_REC_LEN); // 清空
            }
            
            if (point1 >= USART_REC_LEN) point1 = USART_REC_LEN;
        }
    }
		// 清除中断标志
    USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}

数据处理:

这里为了我自己的显示问题,我将数据完整性校验去除了,使得打印没有解算出的数据为0:

 


void ParseGpsBuffer_G60(void)
{
	char *subString;
	char *subStringNext;
	char i = 0;
	if (Save_Data.isGetData)
	{
		Save_Data.isGetData = false;
		//UsartPrintf(USART1, "**************\r\n");
		//UsartPrintf(USART1, "%s",Save_Data.GPS_Buffer);
		sprintf(buf,"t10.txt=\"%s\"",Save_Data.GPS_Buffer);
		UsartPrintf(USART1, "%s",buf);
		for(i=0; i<3; i++)
		{
				USART_SendData(USART1,0xff);
				while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
		}
		for (i = 0 ; i <= 6 ; i++)
		{
			if (i == 0)
			{
				if ((subString = strstr(Save_Data.GPS_Buffer, ",")) == NULL){}
					//ErrorLog(1);	//解析错误
			}
			else
			{
				subString++;
				if ((subStringNext = strstr(subString, ",")) != NULL)
				{
					char usefullBuffer[2]; 
					switch(i)
					{
						case 1:memcpy(Save_Data.UTCTime, subString, subStringNext - subString);break;	//获取UTC时间
						case 2:memcpy(usefullBuffer, subString, subStringNext - subString);break;	//获取UTC时间
						case 3:memcpy(Save_Data.latitude, subString, subStringNext - subString);break;	//获取纬度信息
						case 4:memcpy(Save_Data.N_S, subString, subStringNext - subString);break;	//获取N/S
						case 5:memcpy(Save_Data.longitude, subString, subStringNext - subString);break;	//获取经度信息
						case 6:memcpy(Save_Data.E_W, subString, subStringNext - subString);break;	//获取E/W

						default:break;
					}
					subString = subStringNext;
					Save_Data.isParseData = true;
					Save_Data.isUsefull = true;
//					if(usefullBuffer[0] == 'A')
//						Save_Data.isUsefull = true;
//					else if(usefullBuffer[0] == 'V')
//						Save_Data.isUsefull = false;
				}
				else
				{
					//ErrorLog(2);	//解析错误
				}
			}
		}
	}
}

// GPS数据转化单位为度。
double Convert_to_degrees(char* data)
{
	double temp_data = atof(data);
	int degree = (int)(temp_data / 100);
	double f_degree = (temp_data / 100.0 - degree)*100/60.0;
	double result = degree + f_degree;
	return result;
}


void PrintGpsBuffer_G60(void)
{
	double f_latitude = 0.0;
	double f_longitude = 0.0;
	int i =0;
	
	if (Save_Data.isParseData)
	{
		Save_Data.isParseData = false;
		sprintf(buf,"t2.txt=\"%s\"",Save_Data.UTCTime);
		UsartPrintf(USART1, "%s",buf);
		for(i=0; i<3; i++)
		{
				USART_SendData(USART1,0xff);
				while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
		}
		
		if(Save_Data.isUsefull)
		{
			f_latitude = Convert_to_degrees(Save_Data.latitude);
					sprintf(buf,"t12.txt=\"%lf%s\"",f_latitude,Save_Data.N_S);
					UsartPrintf(USART1, "%s",buf);
					for(i=0; i<3; i++)
					{
							USART_SendData(USART1,0xff);
							while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
					}
				sprintf(buf,"t4.txt=\"%s\"",Save_Data.N_S);
					UsartPrintf(USART1, "%s",buf);
					for(i=0; i<3; i++)
					{
							USART_SendData(USART1,0xff);
							while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
					}
			f_longitude = Convert_to_degrees(Save_Data.longitude);
			f_latitude = Convert_to_degrees(Save_Data.latitude);
					sprintf(buf,"t6.txt=\"%lf%s\"", f_longitude, Save_Data.E_W);
					UsartPrintf(USART1, "%s",buf);
					for(i=0; i<3; i++)
					{
							USART_SendData(USART1,0xff);
							while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
					}	
				sprintf(buf,"t8.txt=\"%s\"",Save_Data.E_W);
					UsartPrintf(USART1, "%s",buf);
					for(i=0; i<3; i++)
					{
							USART_SendData(USART1,0xff);
							while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
					}
					
					
			Save_Data.isUsefull = false;
		}
		else
		{
			UsartPrintf(USART1, "GPS DATA is not usefull!\r\n");
		}
		
	}
}

主函数调用:

 

按键程序:



uint8_t KEY_Scan(uint8_t mode)
{	 
	static uint8_t key_up=1;//按键按松开标志
	uint8_t KEY1,KEY2,KEY3,KEY4;
	KEY1=1;KEY2=1;KEY3=1;KEY4=1;
	    if( GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_12) == 0 ){KEY1=0;}
      if( GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_13) == 0 ){KEY2=0;}
      if( GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_11) == 0 ){KEY3=0;}
			if( GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_10) == 0 ){KEY4=0;}
	if(mode)key_up=1;  //支持连按		  
	if(key_up&&(KEY2==0||KEY1==0||KEY3==0||KEY4==0))
	{
		delay_ms(10);//去抖动 
		key_up=0;
		if(KEY2==0)     return 2;
		else if(KEY1==0)return 1;
		else if(KEY3==0)return 3;
		else if(KEY4==0)return 4;
	}
	else if(KEY1==1&&KEY2==1&&KEY3==1&&KEY4==1)key_up=1; 	    
 	return 0;// 无按键按下
}


void KEY2_init(void)
{
	  GPIO_InitTypeDef GPIO_InitStructure;

    // 1. 使能GPIOD时钟
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
    // 2. 配置PD10-PD13为输入模式(带上拉)
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;       // 输入模式
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;       // 内部上拉(按键另一端接地时有效)
    GPIO_Init(GPIOD, &GPIO_InitStructure);
    /* 如果按键另一端接VCC,需要改为下拉:
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; */
}

测试效果视频:

这个程序不理想,会让系统变卡,尤其是拿到室外接收到卫星数据之后,大量浮点数的运算让按键切屏都不是很流畅

STM32F407ZGT6笔记15:G60_GPS北斗导航模

 

完整工程下载:

https://download.csdn.net/download/qq_64257614/90572117