STM32F4驱动GPS(寄存器版)

本次使用STM32F4的USART1对GPS模块进行驱动,并且将GPS的时间、经纬度通过串口打印出来。

gps模块
在这里插入图片描述
gps模块与接线图
注意:GPS 模块需放到窗户边/阳台,否则可能收不到 GPS 信号。

1、GPS驱动配置(gps.c)
#include "includes.h"

//定义接收信息结构体变量
struct GPS_Data Save_Data;
/*****************************
函数名:clrStruct
函数参数:无

函数返回值:无
函数功能:清除接收结构体信息
函数描述:
*****************************/ 
void clrStruct(void)
{
	Save_Data.isGetData = false;
	Save_Data.isParseData = false;
	Save_Data.isUsefull = false;
	memset(Save_Data.GPS_Buffer, 0, 200);      //清空
	memset(Save_Data.UTCTime, 0, 20);
	memset(Save_Data.latitude, 0, 20);
	memset(Save_Data.N_S, 0, 2);
	memset(Save_Data.longitude, 0, 20);
	memset(Save_Data.E_W, 0, 2);
	
}
/*****************************
函数名:parseGpsBuffer
函数参数:无

函数返回值:无
函数功能:解析接收结构体信息
函数描述:
*****************************/
void parseGpsBuffer(void)
{
	char *subString=NULL;
	char *subStringNext=NULL;
	char i = 0;
	if (Save_Data.isGetData)
	{
		Save_Data.isGetData = false;//串口中断接收一次。解析一次
//		printf(Save_Data.GPS_Buffer);
    //解析数据信息
		for (i = 0 ; i <= 9 ; 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;	//定位信息是否有效
						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
            			case 7:break;
						case 8:break;
						case 9:memcpy(Save_Data.UTCDay, subString, subStringNext - subString);break;	//获取UTC日期
						default:break;
					}

					subString = subStringNext; //指向下一个,后数据信息
					Save_Data.isParseData = true;
					if(usefullBuffer[0] == 'A')
						Save_Data.isUsefull = true;
					else if(usefullBuffer[0] == 'V')
						Save_Data.isUsefull = false;
				}
				else
				{
					errorLog(2);	//解析错误
				}
			}
		}
	}
}
/*****************************
函数名:printGpsBuffer
函数参数:无

函数返回值:无
函数功能:打印接收的数据信息
函数描述:
*****************************/
void printGpsBuffer(void)
{
	u8 year,month,day,hour,minute,second,week;
	double latitude,longitude;
	if (Save_Data.isParseData)
	{
		Save_Data.isParseData = false;
		//获得时间
		hour =(Save_Data.UTCTime[0]-'0')*10+(Save_Data.UTCTime[1]-'0')+8;
		minute =(Save_Data.UTCTime[2]-'0')*10 +(Save_Data.UTCTime[3]-'0');
		second =(Save_Data.UTCTime[4]-'0')*10 +(Save_Data.UTCTime[5]-'0');
		if(Save_Data.isUsefull)
		{
			Save_Data.isUsefull = false;
			//获得纬度
			latitude= atof( Save_Data.latitude);
			latitude/=100;
     		//获得经度
			longitude= atof( Save_Data.longitude);
			longitude/=100;
			//获得日期
			year =(Save_Data.UTCDay[4]-'0')*10+(Save_Data.UTCDay[5]-'0');
			month =(Save_Data.UTCDay[2]-'0')*10 +(Save_Data.UTCDay[3]-'0');
			day =(Save_Data.UTCDay[0]-'0')*10 +(Save_Data.UTCDay[1]-'0');
			
			
			printf("当前时间: 20%d-%d-%d %d:%d:%d\r\n",year,month,day,hour,minute,second);
			printf("当前纬度 %s:%f°\r\n",Save_Data.N_S,latitude);
			printf("当前经度 %s:%f°\r\n",Save_Data.E_W,longitude);
		 }
		else
		{
			printf("GPS DATA is not usefull!\r\n");
		}
		
	}
}
void errorLog(int num)
{
	while (1)
	{
	  	printf("ERROR%d\r\n",num);
	}
}
2、GPS函数声明(gps.h)
#ifndef   GPS_H
#define   GPS_H

#include "stm32f4xx.h"


#define false 0
#define true 1

//GPS接收帧格式结构体
struct GPS_Data 
{
	char GPS_Buffer[200];	//整体数据长度
	char isGetData;			//是否获取到GPS数据
	char isParseData;		//是否解析完成
	char UTCTime[20];		//UTC时间
	char latitude[20];		//纬度
	char N_S[2];			//N/S
	char longitude[20];		//经度
	char E_W[2];			//E/W
	char isUsefull;			//定位信息是否有效
	char UTCDay[20];		//UTC日期
};

extern struct GPS_Data Save_Data;
void clrStruct(void);
void errorLog(int num);
void parseGpsBuffer(void);
void printGpsBuffer(void);

#endif

3、串口驱动配置(usart1.c)注意串口中断函数
#include "includes.h"

/*****************************
函数名:USART1_init
函数参数:
int boand : TX/RX 的波特率
函数返回值:无
函数功能:实现开发板对应USART1的发送/接收初始化配置
函数描述:
USART1_TX  :PA9
USART1_RX : PA10
*****************************/
void USART1_init(int boand )
{
	int OVER8 =0 ; 
	float USARTDIV ;//放入波特率寄存器中的数值
	int DIV_Fraction; //表示USARTDIV的小数部分
	int DIV_Mantissa ;//表示USARTDIV的整数部分
	/*****对USART1的TX RX管脚 复用配置******/
	//打开PA的外设时钟
	RCC->AHB1ENR |=(1<<0);
	/******USART1_TX PA9复用功能配置*****/
	//模式寄存器
	GPIOA->MODER &=~(0X3<<18); //清零
	GPIOA->MODER |=(0X2<<18);  //复用功能
	//具体的复用功能配置
	GPIOA->AFR[1] &=~(0XF<<4); //清零
	GPIOA->AFR[1] |=(0X7<<4);  //复用成USART1_TX
	
	/******USART1_RX PA10复用功能配置*****/
	//模式寄存器
	GPIOA->MODER &=~(0X3<<20); //清零
	GPIOA->MODER |=(0X2<<20);  //复用功能
	//具体的复用功能配置
	GPIOA->AFR[1] &=~(0XF<<8); //清零
	GPIOA->AFR[1] |=(0X7<<8);  //复用成USART1_RX
	
	/******USART1的发送/接收控制功能配置****/
	//打开USART1的外设时钟
	RCC->APB2ENR |=(1<<4);
	//串口工作使能
	USART1->CR1 |=(1<<13);
	//禁止奇偶校验
	USART1->CR1 &=~(1<<10);
	//发送器使能
	USART1->CR1 |=(1<<3);
	//接收器使能
	USART1->CR1 |=(1<<2);
	//不发送断路字符
	USART1->CR1 &=~(1<<0);
#ifdef   MY_OVER8  //16倍
   USART1->CR1 &=~(1<<15);
	 OVER8 =0;
#else    //8倍
   USART1->CR1 |=(1<<15);
	 OVER8 =1;
#endif


	/*****TX/RX的波特率配置*****/
	USARTDIV =(float)84000000/(8*(2-OVER8)*boand);
	DIV_Mantissa =USARTDIV;
  DIV_Fraction =(USARTDIV-DIV_Mantissa)*8*(2-OVER8);
	USART1->BRR = DIV_Mantissa<<4 | DIV_Fraction;
	
	
	/*******接收中断相关配置 *******/
	//接收中断使能
	USART1->CR1 |=(1<<5);
	//USART1 NVIC中断配置 分组值: 7-2  
  MY_NVIC_init(7-2,1,1,USART1_IRQn);
}

/*****************************
函数名:USART1_Sendbyte
函数参数:
u8 data :要发送的数据
函数返回值:无
函数功能:实现串口1发送一个字节数据
函数描述:
*****************************/
void USART1_Sendbyte(u8 data)
{
	 //等待上次数据发送完
	 while((USART1->SR &(1<<6))==0)
	 {
		 ;
	 }
	 //发送该次数据
	 USART1->DR =data;
}

/*****************************
函数名:USART1_Sendstring
函数参数:
u8  *buf : 字符指针,
     表示要发送字符串的首地址
函数返回值:无
函数功能:实现串口1发送一个字符串
函数描述:
*****************************/
void USART1_Sendstring(u8 *buf)
{
	 while(*buf !='\0')
	 {
		  USART1_Sendbyte(*buf);
		  buf++;
	 }
	 USART1_Sendbyte('\r');
	 USART1_Sendbyte('\n');
}

/*****************************
函数名:USART1_Receivebyte
函数参数:无

函数返回值:u8 data :接收到的数据
函数功能:实现串口1接收一个字节数据
函数描述:
*****************************/
u8 USART1_Receivebyte(void)
{
	 u8 data;
	 //等待接收到数据
	 while((USART1->SR &(1<<5))==0)
	 {
		 ;
	 }
	//读出接收到的数据
	data =USART1->DR;
	//把接收到的数据返回出去
	return data;	
}

/*****************************
函数名:USART1_Receivestring
函数参数:u8 *buf :接收到的数据

函数返回值:无
函数功能:实现串口1接收一个字符串
函数描述:
用户自定义结束标志
*****************************/  
void USART1_Receivestring(u8 *buf)
{
	 u8 ch; 
	 while(1)
	 {
		  ch =USART1_Receivebyte();
		 //判断接收到的是否是结束标志
		 if(ch ==' ' || ch =='\r' || ch=='\n')
		 {
			 break;
		 }
		 *buf =ch;
		 buf++;
	 }
	 *buf ='\0';//添加一个结束标志 
}

#pragma import(__use_no_semihosting_swi) //取消半主机状态

struct __FILE { int handle; /* Add whatever you need here */ };
FILE __stdout;

int fputc(int ch, FILE *f) {
	USART1_Sendbyte(ch);
  return (ch);
}
int ferror(FILE *f) {
  /* Your implementation of ferror */
  return EOF;
}

void _ttywrch(int ch) {
  USART1_Sendbyte(ch);
}


u16 point1 = 0;
char USART_RX_BUF[200];     //接收缓冲,
//中断服务函数
void USART1_IRQHandler(void)
{
	 u8 Res;
	 Res =USART1->DR;	//读取接收到的数据
	if(Res == '$') 		//重新开始接收数据
	{
		point1 = 0;	
	}
  USART_RX_BUF[point1++] = Res;
	//确定是否收到"GPRMC"这一帧数据
	if(USART_RX_BUF[0] == '$' && USART_RX_BUF[4] == 'M' && USART_RX_BUF[5] == 'C')			
	{
		if(Res == '\n')	//接收到该帧	数据的最后一个						   
		{
			memset(Save_Data.GPS_Buffer, 0, 100);      				//清空
			memcpy(Save_Data.GPS_Buffer, USART_RX_BUF, point1); 	//保存数据
			Save_Data.isGetData = true;
			point1 = 0;
			memset(USART_RX_BUF, 0, 200);     						 //清空				
		}					
	}	
	if(point1 >= 200)
	{
		point1 = 200;
	}	
}

4、串口函数声明(usart1.h)
#ifndef   USART1_H
#define   USART1_H

#include "stm32f4xx.h"
//如果采用16倍过采样,定义该宏
//如果采用8倍过采样,屏蔽冠宏
#define MY_OVER8

void USART1_init(int boand );
void USART1_Sendbyte(u8 data);
void USART1_Sendstring(u8 *buf);
u8 USART1_Receivebyte(void);
void USART1_Receivestring(u8 *buf);
#endif

5、主函数(main.c)
#include "includes.h"

int main()
{ 
  	//串口初始化
	USART1_init(9600);
	//清除接受结构体信息
	clrStruct();
	while(1)
	{
		//解析数据
		parseGpsBuffer();
		//打印数据
		printGpsBuffer();
	}
	return 0;
}

整个程序代码与使用手册上传至:https://download.csdn.net/download/qq_37619128/84225570

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CinzWS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值