基于STM32开发板的GPS定位模块设计.docx
《基于STM32开发板的GPS定位模块设计.docx》由会员分享,可在线阅读,更多相关《基于STM32开发板的GPS定位模块设计.docx(22页珍藏版)》请在冰豆网上搜索。
基于STM32开发板的GPS定位模块设计
生产实习设计报告
设计题目:
基于GPS模块的定位装置
生产组长:
王海昕
设计组长:
孙振邦
小组成员:
王洪振、唐政亮、帖小龙、宋劲草、宋晓林
苏刚、孙晓龙、史俊、赵若曦
实习日期:
2012年8月27日-9月15日
一、概述
本设计基于STM32F107开发板,结合iTrax03-02型GPS接收机,实现GPS模块与STM32的通信;通过GPS模块实现定位,STM32对GPS模块传入的数据进行读取和处理,将得到定位信息在OLED显示。
该定位装置还有如下附加功能:
SD卡数据存储功能,定位状态显示(卫星颗数等);可通过RS232串口传输坐标和时间至PC机,并通过上位机软件实现路径计算和网络地图定位。
二、总体设计
1.总体系统结构
2.功能实现
⑴.经纬度测定,海拔高度测定
⑵.速度计算与方向指示
⑶.SD卡定时存储信息
⑷.上位机制作及路径计算
3.人员分工
孙振邦、王海昕完成源程序的编写,以及代码的修改、编译、下载、调试等工作;
宋劲草、宋晓林、苏刚负责GPS数据编码转换编程;
王洪振、帖小龙、唐政亮负责串口数据传输、SD卡定时存储设置;
史俊、赵若曦、孙晓龙负责上位机界面设计和各项功能的验证。
三、关键模块设计
⑴.GPS模块
iTrax03-02型GPS接收机是根据芬兰FASTRAX公司的GPS模块进行了电平转换、通信接口等电路设计后生产的一款GPS(OEM)接收机产品。
该产品通过底板上9pin排线与计算机串口直接通信,定位后即可输出载体的经纬度信息、时间信息、速度信息等。
(2)GPS定位数据格式解析
数据形式:
$GPGGA,hhmmss.dd,xxmm.dddd,,yyymm.dddd,,v,ss,d.d,h.h,M,g.g,M,a.a,xxxx*hh
名称
说明
$GPGGA
GGA消息协议头
hhmmss.dd
UTC时间
xxmm.dddd
纬度信息,度、分格式
纬度半球N(北半球)或S(南半球)
yyymm.dddd
经度信息,度、分格式
纬度半球E(东经)或E(西经)
V
判断是否已定位,定位为1,未定位为0
ss
使用的解算卫星的数量一般0-12颗
d.d
HDOP水平精度因子
h.h
海拔高度
M
单位米
g.g
WGS-84地表面与水平面的差值
M
单位米
a.a
空
xxxx
空
hh
校验及固定包尾
⑵.OLED显示模块
OLED使用的控制器为SSD1305,可通过写入不同的命令字来设置对比度、显示开关、电荷泵、页地址等。
OLED被配置为使用I2C的方式。
I2C的地址二进制位为0111100X,16进制为0x78(写地址),0x79(读地址)。
OLED的Reset平时应该拉高,在初始化的时候,应该有一个从低电平到高电平的跳变。
使用的MCU端口为
PB6CLKI2C
PB7SDAI2C
PE6RESET(低有效)
(3)距离计算功能
公式、原理什么的
(4).串行通信模块
RS232的电平转换芯片为MAX232CE。
外部接口为DB9。
有两个LED指示灯,TXD用来显示接受到数据,RXD用来显示正在发送数据。
对外接口为DB9接口,定义为:
2RXD,3TXD,5GND。
因此,基板可以通过串口线直接连接到PC机,和PC机进行通信。
使用的MCU端口为:
PD5UART2_TX(Remap)
PD6UART2_RX(remap)
四、测试结果
1.开机上电后在数据有效的情况下进入定位信息显示模式;
2.进入定位信息显示模式后,OLED显示出当前位置经度、纬度、海拔高度、移动速度、移动方向、卫星显示颗数
3.设定中断时间后,数据会自动存储至SD卡;
4.通过RS232串口与PC通讯后可以通过上位机软件打开该位置的谷歌地图显示,并且计算路径长度。
附录一
定位测试数据
保存数据如下:
$GPGSV,3,1,10,01,35,047,32,04,30,244,24,08,12,207,27,09,06,318,12*71
$GPGSV,3,2,10,11,20,063,36,17,54,320,39,20,54,099,23,27,10,309,26*7F
$GPGSV,3,3,10,28,78,225,29,32,34,062,26*75
$GPRMC,071738.50,A,3609.4075,N,12029.3426,E,0.00,302.3,090912,5.8,W,A*15
$GPGGA,071738.50,3609.4075,N,12029.3426,E,1,05,2.0,115.0,M,5.5,M,,*50
$PFST,FOM,6*63
$GPGSA,A,3,01,08,11,17,28,,,,,,,,2.9,2.0,2.1*3D
$GPGSV,3,1,10,01,35,047,32,04,30,244,24,08,12,207,27,09,06,318,12*71
$GPGSV,3,2,10,11,20,063,36,17,54,320,39,20,54,099,23,27,10,309,26*7F
$GPGSV,3,3,10,28,78,225,29,32,34,062,26*75
$GPRMC,071739.50,A,3609.4075,N,12029.3428,E,0.00,302.3,090912,5.8,W,A*1A
$GPGGA,071739.50,3609.4075,N,12029.3428,E,1,07,2.0,115.0,M,5.5,M,,*5D
$PFST,FOM,24*53
$GPGSA,A,3,01,04,08,11,17,27,28,,,,,,2.9,2.0,2.1*3C
$GPGSV,3,1,10,01,35,047,31,04,30,244,24,08,12,207,27,09,06,318,12*72
$GPGSV,3,2,10,11,20,063,36,17,54,320,38,20,54,099,23,27,10,309,25*7D
$GPGSV,3,3,10,28,78,225,27,32,34,062,26*7B
$GPRMC,071740.50,A,3609.4074,N,12029.3429,E,0.00,302.3,090912,5.8,W,A*14
$GPGGA,071740.50,3609.4074,N,12029.3429,E,1,07,1.8,115.0,M,5.5,M,,*58
$PFST,FOM,20*57
$GPGSA,A,3,01,04,08,11,17,27,28,,,,,,2.7,1.8,2.0*38
$GPGSV,3,1,10,01,35,047,31,04,30,244,24,08,12,207,27,09,06,318,12*72
$GPGSV,3,2,10,11,20,063,36,17,54,320,38,20,54,099,23,27,10,308,25*7C
$GPGSV,3,3,10,28,78,225,27,32,34,062,26*7B
$GPRMC,071741.50,A,3609.4074,N,12029.3431,E,0.00,302.3,090912,5.8,W,A*1C
附录二
关键程序代码
Main.c:
#include"includes.h"
#include"led.h"
#include
GPIO_InitTypeDefGPIO_InitStructure;
USART_InitTypeDefUSART_InitStructure;
NVIC_InitTypeDefNVIC_InitStructure;
voidUSART1_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE);
//定义UART1TX(PA.09)脚为复用推挽输出
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//IO口的第九脚
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//IO口速度
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//IO口复用推挽输出
GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化串口1输出IO口
//定义USART1Rx(PA.10)为悬空输入
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;//IO口的第十脚
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;//IO口悬空输入
GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化串口1输入IO口
//串口参数配置
USART_InitStructure.USART_BaudRate=4800;//设置波特率为115200
USART_InitStructure.USART_WordLength=USART_WordLength_8b;//设置数据位为8位
USART_InitStructure.USART_StopBits=USART_StopBits_1;//设置停止位为1位
USART_InitStructure.USART_Parity=USART_Parity_No;//无奇偶校验
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//没有硬件流控
USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;//发送与接收
//完成串口COM1的时钟配置、GPIO配置,根据上述参数初始化并使能
USART_Init(USART1,&USART_InitStructure);
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//使能串口1接收中断
USART_Cmd(USART1,ENABLE);
NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
intmain(void)
{
delay_init(72);
GUI_Init();
GUI_SetBkColor(GUI_BLUE);
GUI_Clear();
USART1_Init();
while
(1)
{
gps_display();
}
}
GPS.c:
#include"includes.h"
//GPS数据存储数组//
unsignedcharJD[11];//经度
unsignedcharJD_a;//经度方向
unsignedcharWD[10];//纬度
unsignedcharWD_a;//纬度方向
unsignedchartime[10];//时间
unsignedcharspeed[6]={0};//速度
unsignedcharspeed2[6]={0};//速度
unsignedcharhigh[6];//高度
unsignedcharhaiba[6];//海拔
unsignedcharangle[6];//方位角
unsignedcharuse_sat[3];//使用的卫星数
unsignedchartotal_sat[3];//天空中总卫星数
unsignedcharlock;//定位状态
//串口中断需要的变量
unsignedcharseg_count;//逗号计数器
unsignedchardot_count;//小数点计数器
unsignedcharbyte_count;//位数计数器
unsignedcharcmd_number;//命令类型
unsignedcharmode;//0:
结束模式,1:
命令模式,2:
数据模式
unsignedcharbuf_full;//1:
整句接收完成,相应数据有效。
0:
缓存数据无效。
unsignedcharcmd[5];//命令类型存储数组
unsignedcharUSART_END;
unsignedcharnewflag=0;
//
经纬度转换用//
doubled;
doublef;
unsignedchard_d;
doubleD_D;
unsignedchartime_8;//时区转换
voidgps_deal(void)
{
u8tmp=0;
if(USART_GetITStatus(USART1,USART_IT_RXNE)!
=RESET)//如果是接收中断
tmp=USART_ReceiveData(USART1);
switch(tmp)
{
case'$':
cmd_number=0;//命令类型清空
mode=1;//接收命令模式
byte_count=0;//接收位数清空
break;
case',':
seg_count++;//逗号计数加1
byte_count=0;
break;
case'*':
switch(cmd_number)
{
case1:
newflag|=0x01;//GGA
break;
case2:
newflag|=0x02;//GSV
break;
case3:
newflag|=0x04;//RMC
break;
}
mode=0;
break;
default:
if(mode==1)
{
//命令种类判断
cmd[byte_count]=tmp;//接收字符放入类型缓存
if(byte_count>=4)//如果类型数据接收完毕,判断类型
{
if(cmd[0]=='G')
{
if(cmd[1]=='P')
{
if(cmd[2]=='G')
{
if(cmd[3]=='G')
{
if(cmd[4]=='A')
{
cmd_number=1;
mode=2;
seg_count=0;
byte_count=0;
}
}
elseif(cmd[3]=='S')
{
if(cmd[4]=='V')
{
cmd_number=2;
mode=2;
seg_count=0;
byte_count=0;
}
}
}
elseif(cmd[2]=='R')
{
if(cmd[3]=='M')
{
if(cmd[4]=='C')
{
cmd_number=3;
mode=2;
seg_count=0;
byte_count=0;
}
}
}
}
}
}
}
elseif(mode==2)
{
//接收数据处理
switch(cmd_number)
{
case1:
//类型1数据接收。
GPGGA
switch(seg_count)
{
case2:
//纬度处理
if(byte_count<11)
{
WD[byte_count]=tmp;
WD[byte_count+1]='\0';//解决输出位数过多
}
break;
case3:
//纬度方向处理
if(byte_count<1)
{
WD_a=tmp;
}
break;
case4:
//经度处理
if(byte_count<11)
{
JD[byte_count]=tmp;
JD[byte_count+1]='\0';
}
break;
case5:
//经度方向处理
if(byte_count<1)
{
JD_a=tmp;
}
break;
case7:
//定位使用的卫星数
if(byte_count<2)
{
use_sat[byte_count]=tmp;
use_sat[byte_count+1]='\0';
}
break;
case9:
//高度处理
if(byte_count<6)
{
high[byte_count]=tmp;
}
break;
case11:
//海拔处理
if(byte_count<6)
{
haiba[byte_count]=tmp;
}
break;
}
break;
case2:
//类型2数据接收。
GPGSV
switch(seg_count)
{
case3:
//天空中的卫星总数
if(byte_count<2)
{
total_sat[byte_count]=tmp;
total_sat[byte_count+1]='\0';
}
break;
}
break;
case3:
//类型3数据接收。
GPRMC
switch(seg_count)
{
case1:
if(byte_count<10)
{
//时间处理
time[byte_count]=tmp;
}
break;
case2:
//定位判断
if(byte_count<1)
{
lock=tmp;
}
break;
case7:
//速度处理
if(byte_count<5)
{
speed2[byte_count]=tmp;
//spd_wei=byte_count;
}
break;
case8:
//方位角处理
if(byte_count<5)
{
angle[byte_count]=tmp;
}
break;
}
break;
}
}
byte_count++;//接收数位加1
break;
}
}
//时区转换
voidTIME_AREA(void)
{
time_8=(time[0]-0x30)*10+(time[1]-0x30)+8;
if(time_8>23)
{
time_8=time_8-24;
}
time[0]=(time_8/10)+0x30;
time[1]=((time_8-(time_8/10)*10)/1)+0x30;
}
//经纬度转换
doubleJWD_AREA(char*jwd)
{
d=atof(jwd)/100.0;//将JD[]转换为double
d_d=d/1;
f=(d-d_d)/60.0*100;
D_D=d_d+f;
returnD_D;
}
voidgps_display(void)
{
LED0=!
LED0;
if(newflag==0x07)
{
newflag=0;
GUI_SetColor(GUI_GREEN);
GUI_SetFont(&GUI_Font8x16);
GUI_DispStringAt("status",20,20);
GUI_DispCharAt(lock,140,20);
TIME_AREA();
GUI_DispStringAt("time",20,40);
GUI_DispStringAt(time,140,40);
GUI_DispStringAt("Longitude",20,60);
JWD_AREA(JD);//经度转换
GUI_DispFloat(D_D,10);
GUI_DispCharAt(JD_a,120,60);
GUI_DispStringAt("Latitude",20,80);
JWD_AREA(WD);//纬度转换
GUI_DispFloat(D_D,10);
GUI_DispCharAt(WD_a,120,80);
GUI_DispStringAt("use_sat",20,100);
GUI_DispStringAt(use_sat,140,100);
GUI_DispStringAt("total_sat",20,120);
GUI_DispStringAt(total_sat,140,120);
GUI_DispStringAt("Elevation",20,140);
GUI_DispStringAt(high,140,140);
GUI_DispStringAt("high",20,160);
GUI_DispStringAt(haiba,140,160);
GUI_DispStringAt("Speed",20,180);
GUI_DispStringAt(speed2,140,180);
GUI_DispStringAt("Direction",20,200);
GUI_DispStringAt(angle,140,200);
GUI_DispStringAt("OUCAUTOMATIONGPS",40,280);
}
}