嵌入式综合实验报告
《嵌入式系统综合实验》报告
学号: 姓名: Shanghai University of Engineering Science School of Electronic and Electrical Engineering
基于 2 STM32 的 的 S GPS 信息 显示系统
—— 嵌入式系统综合实验报告
班级:0211112
姓名:褚建勤 学号:021111228 班级:0211112
姓名:于心忆 学号:021111216 班级:0211112
姓名:乐浩奎 学号:021111232 一、产品设计要求( ( 产品规 格描述) )
1 、嵌入式产品名称
GPS 信息显示系统 2 、嵌入式产品目的
在学校的生活中,您经常可能需要联系不就是同一间宿舍的同学,但就是您不能确定她现在在什么地方,这时候全球定位系统(GPS)就可以发挥作用了,但就是传统的 GPS 系统只能提供经纬度信息,不能直观的显示您想要找到人在何处,我们的系统就在传统的 GPS 的基础上添加了对应位置显示的功能,方便您更方便更快捷的找到您想找的同学 3 、嵌入式产品功能
使用 GPS 输入用户位置信息 GPS 将相关经纬度信息反馈给主处理器 主处理器处理相关位置信息并将信息转换为对应位置在 LCD 上显示出来 在 LCD 上输出用户状态信息 4 、嵌入式产品的输入与输出
输入设备:GPS 系统 输出设备:LCD 二、产品方案设计( ( 产品设计方案) )
1 、产品架构设计
2 、产品硬件设计
1 ) 处理器选择
本系统选用基于 ARMCortex-M3 内核的 STM32F103RB 嵌入式微控制器作为处理器。
①
选用原因 A
技术因素 工作频率: 最高 72MHz。
内部与外部存储器: 128K 字节的闪存程序存储器,用于存放程序及数据;多达 20K 字节的内置 SRAM,CPU 能以 0 等待周期访问(读/写)。
定时器与中断:包含 1 个高级控制定时器、3 个普通定时器,以及 2 个瞧门狗定时器与 1个系统嘀嗒定时器;内置嵌套的向量式中断控制器,能够处理多达43个可屏蔽中断通道与16个优先级。
IO 接口:通用输入输出接口(GPIO)。每个 GPIO 管脚都可以由软件配置成输出(推拉或开路)、输入(带或不带上拉或下拉)或其它的外设功能口。多数 GPIO 管脚都与数字或模拟的外设共用。所有的 GPIO 管脚都有大电流通过能力。在需要的情况下,I/O 管脚的外设功能可以通过一个特定的操作锁定,以避免意外的写入 I/O 寄存器。在 APB2 上的 I/O 脚可达 18MHzstm32 LCD GPS 模块
的翻转速度。
通用同步/异步接受发送器(USART):USART1 接口通信速率可达 4、5 兆位/秒,其她接口的通信速率可达 2、25 兆位/秒。USART 接口具有硬件的 CTS 与 RTS 信号管理、支持 IrDA SIR ENDEC 传输编解码、兼容 ISO7816 的智能卡并提供 LIN 主/从功能。所有 USART 接口都可以使用 DMA 操作。
环境要求:-40°C 至+85°C 温度范围。
B
非技术因素 开发及调试工具:Keil MDK
参考资料:STM32F103RBT6 官方资料 操作系统:Windows XP / Windows 7 / Windows 8 内部 AHB 时钟频率 :72 MHz。
内部 APB1 时钟频率:36 MHz。
内部 APB2 时钟频率:72 MHz。
标准工作电压 VDD:2、0V~3、6V。
模拟部分工作电压(未使用 ADC):必须与 VDD 相同,最大 3、6V。
模拟部分工作电压(使用 ADC):必须与 VDD 相同,2、4V~3、6V。
备份部分工作电压 VBAT:1、8V~3、6V。
电流:睡眠时与工作时差异较大,还与打开的外设多少有关,范围大约为 4mA~50mA。
存储温度:-65 至+150 度。
工作温度:-40 至+85 度。
3 、产品软件设计
1 ) 操作系统选择
无操作系统 2 ) 其她重要器件选择
D LCD 模块: :
功能: 主要特性: S GPS 模块: :
该 GPS 模块选用的就是型号为 ATK-NEO-M6_V12 的 GPS 模块,就是 ALIENTEK 生产的一款高性能 GPS 模块,模块核心采用 UBLOX 公司的 NEO-M^模组,具有 50 个通道,追踪灵敏度高达-161dBm,测量输出频率最高可达 5HZ。
功能:
实现当前系统位置的定位 主要特性: 1,模块采用 UBLOX NEO-M6 模组,体积小,性能优异。
2,模组自带陶瓷天线及 MAXIM 公司 20,5dB 高增益 LNA 芯片,搜星能力强。
3,模组可通过串口进行各种参数设置,并可以保存在 EEPROM,使用方便。
4,模组自带 IPX 接口,可以连接各种有源天线,适应能力强。
5 模组兼容 3、3V/5、5V 电平,方便连接各种单片机系统。
6,模组自带可充电后备电源,可以掉电保持星历数据 注 : : 在主电源断电后,后备电池可以维持半小时左右的GPS星历数据的保存,以支持温启动或者热启动,从而实现快速定位 。
GPS 模块图 3 3
) ) 开发环境选择
本系统选用 KEIL 作为开发环境。
KeiL uVision4 完美支持 Cortex-M、Cortex-R4、ARM7 与 ARM9 系列器件;拥有业行领先的 ARM C/C++编译工具链;提供带标准驱动类的 USB 设备与 USB 主机栈;为带图形用户接口的嵌入式系统提供了完善的 GUI 库支持;ULINKpro 可实时分析运行中的应用程序,且能记录 Cortex-M 指令的每一次执行;执行分析工具与性能分析器可使程序得到最优化等特征。
4 4
) ) 开发语言选择
产品软件开发语言:C 语言 C 语言就是一种计算机程序设计语言,它既具有高级语言的特点,又具有汇编语言的特点。它可以作为工作系统设计语言,编写系统应用程序,也可以作为应用程序设计语言,编写不依赖计算机硬件的应用程序。它的应用范围广泛,具备很强的数据处理能力,不仅仅就是在软件开发上,而且各类科研都需要用到 C 语言,适于编写系统软件,具体应用比如单片机以及嵌入式系统开发。主要优点如下:简洁紧凑、灵活方便;运算符丰富;数据类型丰富;表达方式灵活实用;允许直接访问物理地址,对硬件进行操作;生成目标代码质量高,程序执行效率高;可移植性好;表达力强。由于大一刚进校时就接触C语言,所以C语言相对我们而言比较熟悉,在编写中更加容易。
4 、项目组成员分工
姓名 现有工作基础 项目中 任务 项目中预计总共 工作时间(小时) 组长 褚建勤 C 语言基础 GPS 90 组员 于心忆 初学 串口 90 组员 乐浩奎 初学 LCD 90 5 、产品开发计划
时间 任务计划 1-10 制定嵌入式系统综合实验计划。
11-15 查阅相关书籍,到官方网站下载 GPS 使用说明。
15-30 了解熟悉 AT 指令、串口通信的知识。
31-45 了解熟悉 GPS 相关知识 46-60 完成 GPS 初始化及基础设置 61-75 添加对应位置显示功能 76-90 撰写嵌入式系统综合实验报告
6 、产品成本分析 1 )硬件成本清单 产品中硬件材料(如元器件芯片、开发板、仿真器、编程器与测量仪器等)及开发费用(如制板及焊接等费用) 类别 型号∕参数 单价 数量 合计 供应商 联系人及方式 CPU STM32f103RB 138 1 138 正点原子 … GPS
Neo-6m-v12 85 1 85 青岛达英电信器材有限公司
LCD
TFTLCD 2、8
1
★
要求供应商必须就是专业公司非淘宝个人用户并能开立正规的产品发票 2 )软件成本清单 产品中所用软件(如嵌入式开发环境、嵌入式操作系统、GUI 支持包与 TCPIP 协议栈等)费用 类别 名称 单价 数量 合计 供应商 联系人及方式 开发环境 Keil uVsion4 0 1 0 无 无 ★
要求供应商必须就是专业公司非淘宝个人用户并能开立正规的产品发票 3 )人工成本清单
人工成本= 50 小时*10 元/小时*3 人=1500 元
4 )其她成本
无本 5 )产品总成本及分析
产品总成本=硬件成本+软件成本+人工成本+其她成本=138+ 三、产品实现
1 、硬件实现( ( 必须) )
嵌入式处理器的最小系统图 GPS 模块原理图
嵌入式处理器与 GPS 模块间的具体连接连线图硬件连接: STM32 开发板-->ATK-NEO-6M GPS 模块
PA9 -->RXD
PA10-->TXD
GND -->GND
5V/3、3V-->VCC
2 、软件实现( ( 必须) )
软件编程中设计思路(main 主程序流程图)
GPS 模块主要函数: u8 NMEA_Comma_Pos(u8 *buf,u8 cx); 功能:分析 GPS 接收到的数据,采用逗号取值法 参数:数据缓存区数据首地址、逗号位置标号: 返回值: 两个逗号之间的数据 int NMEA_Str2num(u8 *buf,u8*dx); 功能: 把获取到的字符串转换为数字 参数:数据缓存区数据首地址、小数点位置 返回值:转换后的数值 void NMEA_GPGSV_Analysis(nmea_msg *gpsx,u8 *buf); 工能:用来获取可见卫星的总数、卫星编号、卫星仰角、卫星方位角、信噪比等信息 参数:结构体 gpsx 的首地址、数据缓存区首地址 返回值:无、 $GPGSV 语句的基本格式如下: $GPGSV,(1),(2),(3),(4),(5),(6),(7),、、、,(4),(5),(6),(7)*hh(CR)(LF) (1) GSV 语句总数 (2)本句 GSV 的编号 (3) 可见卫星总数(00~12,前面的 0 也将被传输)
(4)卫星编号(01~32,前面的 0 也将被传输) (5)卫星仰角(00~90 度,前面的 0 也将被传输) (6)卫星方位角(000~359 度,前面的 0 也将被传输) (7)信噪比(00~99dB,没有跟踪到卫星时为空) void NMEA_GPGGA_Analysis(nmea_msg *gpsx,u8 *buf); 功能:用来获取 UTC 时间、经纬度、海拔高度等信息 参数:结构体 gpsx 的首地址、数据缓存区首地址 返回值:无 $GPGGA 的语句格式如下: $GPGGA, $GPGGA, $GPGGA,$GPGGA,(1),(2),(3),(4),(5),(6),(7),(8),(9),M, (10 ),M,,M, (11 ),(12 )*hh (CR )( LF ) (1) UTC 时间,格式 hhmmss、ss (2) 纬度 ddmm、mmmmm 度分格式 ); (3) 纬度半球 N 或 S(北纬 或南); (4) 经度,格式为 dddmm、mmm 度分格式; (5) 经度半球 E 或 W(东经 或西); (6) GPSGPS 状态 ,0= 未定位, 1= 非差分定位, 2=
差分定位 ; (7) 正在使用的于定位卫星数量(00~12) (8) HDOP 水平精确度 因子( 0、5~99、9 ) (9) 海拔 高度 (-9999、9 到 9999、9 米) (10 ) 大地水准面高度(-9999、9
到 9999、9 米) (11 ) 差分 时间(从最近一次接收到差分信号开始的秒数,非定位此项为空)
(12 ) 差分参考基站标号 (0000 到 1023 ,首位 0 也将传送 ,非差分定位此项为空 void NMEA_GPGSA_Analysis(nmea_msg *gpsx,u8 *buf); 功能:用来获得卫星号、水平/垂直因子等信息 参数:结构体 gpsx 的首地址、数据缓存区首地址 返回值:无 $GPGSA 的语句格式如下: $GPGSA,(1),(2),(3),(3),(3),(3),(3),(3),(3),(3),(3),(3),(3),(3),(4),(5),(6)*hh(CR)(LF) (1) 模式, M=手动,A=自动 (2) 定位类型,1=为定位,2=2D 定位,3=3D 定位 (3)正在用于定位的卫星号(00~32) (4)PDOP 综合位置精度因子(0、5~99、9) (5)HDOP 水平精度因子(0、5~99、9) (6)VDOP 垂直精度因子(0、5~99、9) void NMEA_GPRMC_Analysis(nmea_msg *gpsx,u8 *buf); 功能:获取 UTC 时间、UTC 日期、地面速度等信息 参数:结构体 gpsx 的首地址、数据缓存区首地址 返回值:无 $GP $GPRMC 语句的基本格式如下:
$GPRMC,(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)*(CR)(LF) (1) (1) (1) UTC 时间 hhmmsshhmmss(时分秒) (2)
A= 有效定位, V= 无效定位 无效定 (3) ddmm、mmm (度分) (度分)
(4) 纬度半球 N(北半球)或 S(南半球) (5) 经度 dddmm、mm(度分(度分) (6)经度半球 E(东经)或 W(西经) (7)地面速率 000、0~999、9 节) (8) 地面航向(
000、0~359、9 度,以 真北方 为参考基准)) (9) UTC 日期, 日期, ddmmyyddmmyy
(日月年) (10)磁偏角(000、0~180、0 度,前导位数不足则补 0) (11)磁偏角方向, E(东)或 W(西)
(12)
模式指示( A= 自主定位 D= 差分 E= 估算, N= 数据无效)
void NMEA_GPVTG_Analysis(nmea_msg *gpsx,u8 *buf); 功能:获取地面航向、地面速率等信息 参数:结构体 gpsx 的首地址、数据缓存区首地址 返回值:无 格式如下: $GPVTG,(1),T,(2),M,(3),N,(4),K, (5)*hh(CR)(LF) (1) 以真北为参考基准的地面航向(000~359 度,前面的 0 也将被传输) (2) 以磁北为参考基准的地面航向(000~359 度,前面的 0 也将被传输) (3)地面速率(000、0~999、9 节,前面的 0 也将被传输) (4)地面速率(0000、0~1851、8 公里/小时,前面的 0 也将被传输) (5)模式指示 (A=自主定位,D=差分,E= 估算,N=数据无效) 四、用户使用说明
该产品就是一个基于 STM32 的校园定位系统,在您接通电源、按下电源后系统能够精确的显示出您当前的坐标、时间、以及海拔等信息。
由于室内 GPS 无法接收到信号,该产品只能在室外进行定位 五、产品开发小结
1 、产品完成情况( ( 必须) )
本产品最初的目的就是实现一个个人定位系统、并且实现位置信息的跟踪,但就是由于技术问题只完成了当前位置的定位。
花费的时间:60 小时 费用: 2 、产品存在问题( ( 必须) )
该产品的定位并不完善,仅仅就是能够获取到当前位置,当然如果您就是在我们本校园的话、还可以显示具体的校园地址信息,比如图书馆、实训楼、教学楼等信息。但就是有一个问题就就是没有实现将数据传输到手机端或者 PC 端,无法进行位置信息的跟踪。
3 3 、产品开发过程中的经验与体会( ( 必须) )
在这次嵌入式的实验过程中学习到了好多以前没有接触过的东西,比如 STM32 开发板的使用,GPS 模块的使用,在这过程中学会了如何点亮 LCD、LED,如何让一个 GPS 开始工作、并且把获取的数据显示在 LCD 上等等。
如果要自己编写所有的代码以我们目前的水平还就是有一定的难度的,所以这次试验基本上就是在原有的代码上进行了一定的修改来实现自己的目标程序。通过对代码的反复读写与研究基本上理解了 GPS 的实现过程。
附 附 2: 所有源程序代码( ( 必须) )
#include "gps、h"
#include "led、h"
#include "delay、h"
#include "usart1、h"
#include "stdio、h"
#include "stdarg、h"
#include "string、h"
#include "math、h" //从 buf 里面得到第 cx 个逗号所在的位置 //返回值:0~0XFE,代表逗号所在位置的偏移、 //
0XFF,代表不存在第 cx 个逗号
u8 NMEA_Comma_Pos(u8 *buf,u8 cx) {
u8 *p=buf;
while(cx)
{
if(*buf=="*"||*buf<" "||*buf>"z")return 0XFF;//遇到"*"或者非法字符,则不存在第 cx 个逗号
if(*buf==",")cx--;
buf++;
}
return buf-p;
} //m^n 函数 //返回值:m^n 次方、 u32 NMEA_Pow(u8 m,u8 n) {
u32 result=1;
while(n--)result*=m;
return result; }
//str 转换为数字,以","或者"*"结束 //buf:数字存储区 //dx:小数点位数,返回给调用函数 //返回值:转换后的数值 int NMEA_Str2num(u8 *buf,u8*dx) {
u8 *p=buf;
u32 ires=0,fres=0;
u8 ilen=0,flen=0,i;
u8 mask=0;
int res;
while(1) //得到整数与小数的长度
{
if(*p=="-"){mask|=0X02;p++;}//就是负数
if(*p==","||(*p=="*"))break;//遇到结束了
if(*p=="、"){mask|=0X01;p++;}//遇到小数点了
else if(*p>"9"||(*p<"0")) //有非法字符
{
ilen=0;
flen=0;
break;
}
if(mask&0X01)flen++;
else ilen++;
p++;
}
if(mask&0X02)buf++; //去掉负号
for(i=0;i<ilen;i++) //得到整数部分数据
{
ires+=NMEA_Pow(10,ilen-1-i)*(buf[i]-"0");
}
if(flen>5)flen=5; //最多取 5 位小数
*dx=flen;
//小数点位数
for(i=0;i<flen;i++) //得到小数部分数据
{
fres+=NMEA_Pow(10,flen-1-i)*(buf[ilen+1+i]-"0");
}
res=ires*NMEA_Pow(10,flen)+fres;
if(mask&0X02)res=-res;
return res; }
//分析 GPGSV 信息 //gpsx:nmea 信息结构体 //buf:接收到的 GPS 数据缓冲区首地址 void NMEA_GPGSV_Analysis(nmea_msg *gpsx,u8 *buf) {
u8 *p,*p1,dx;
u8 len,i,j,slx=0;
u8 posx;
p=buf;
p1=(u8*)strstr((const char *)p,"$GPGSV");
len=p1[7]-"0";
//得到 GPGSV 的条数
posx=NMEA_Comma_Pos(p1,3);
//得到可见卫星总数
if(posx!=0XFF)gpsx->svnum=NMEA_Str2num(p1+posx,&dx);
for(i=0;i<len;i++)
{
p1=(u8*)strstr((const char *)p,"$GPGSV");
for(j=0;j<4;j++)
{
posx=NMEA_Comma_Pos(p1,4+j*4);
if(posx!=0XFF)gpsx->slmsg[slx]、num=NMEA_Str2num(p1+posx,&dx); //得到卫星编号
else break;
posx=NMEA_Comma_Pos(p1,5+j*4);
if(posx!=0XFF)gpsx->slmsg[slx]、eledeg=NMEA_Str2num(p1+posx,&dx);//得到卫星仰角
else break;
posx=NMEA_Comma_Pos(p1,6+j*4);
if(posx!=0XFF)gpsx->slmsg[slx]、azideg=NMEA_Str2num(p1+posx,&dx);//得到卫星方位角
else break;
posx=NMEA_Comma_Pos(p1,7+j*4);
if(posx!=0XFF)gpsx->slmsg[slx]、sn=NMEA_Str2num(p1+posx,&dx); //得到卫星信噪比
else break;
slx++;
}
p=p1+1;//切换到下一个 GPGSV 信息
}
} //分析 GPGGA 信息 //gpsx:nmea 信息结构体 //buf:接收到的 GPS 数据缓冲区首地址 void NMEA_GPGGA_Analysis(nmea_msg *gpsx,u8 *buf) {
u8 *p1,dx;
u8 posx;
p1=(u8*)strstr((const char *)buf,"$GPGGA");
posx=NMEA_Comma_Pos(p1,6);
//得到 GPS 状态
if(posx!=0XFF)gpsx->gpssta=NMEA_Str2num(p1+posx,&dx);
posx=NMEA_Comma_Pos(p1,7);
//得到用于定位的卫星数
if(posx!=0XFF)gpsx->posslnum=NMEA_Str2num(p1+posx,&dx);
posx=NMEA_Comma_Pos(p1,9);
//得到海拔高度
if(posx!=0XFF)gpsx->altitude=NMEA_Str2num(p1+posx,&dx);
} //分析 GPGSA 信息 //gpsx:nmea 信息结构体 //buf:接收到的 GPS 数据缓冲区首地址 void NMEA_GPGSA_Analysis(nmea_msg *gpsx,u8 *buf) {
u8 *p1,dx;
u8 posx;
u8 i;
p1=(u8*)strstr((const char *)buf,"$GPGSA");
posx=NMEA_Comma_Pos(p1,2);
//得到定位类型
if(posx!=0XFF)gpsx->fixmode=NMEA_Str2num(p1+posx,&dx);
for(i=0;i<12;i++)
//得到定位卫星编号
{
posx=NMEA_Comma_Pos(p1,3+i);
if(posx!=0XFF)gpsx->possl[i]=NMEA_Str2num(p1+posx,&dx);
else break;
}
posx=NMEA_Comma_Pos(p1,15);
//得到 PDOP 位置精度因子
if(posx!=0XFF)gpsx->pdop=NMEA_Str2num(p1+posx,&dx);
posx=NMEA_Comma_Pos(p1,16);
//得到 HDOP 位置精度因子
if(posx!=0XFF)gpsx->hdop=NMEA_Str2num(p1+posx,&dx);
posx=NMEA_Comma_Pos(p1,17);
//得到 VDOP 位置精度因子
if(posx!=0XFF)gpsx->vdop=NMEA_Str2num(p1+posx,&dx);
} //分析 GPRMC 信息 //gpsx:nmea 信息结构体
//buf:接收到的 GPS 数据缓冲区首地址 void NMEA_GPRMC_Analysis(nmea_msg *gpsx,u8 *buf) {
u8 *p1,dx;
u8 posx;
u32 temp;
float rs;
p1=(u8*)strstr((const char *)buf,"GPRMC");//"$GPRMC",经常有&与 GPRMC 分开的情况,故只判断GPRMC、
posx=NMEA_Comma_Pos(p1,1);
//得到 UTC 时间
if(posx!=0XFF)
{
temp=NMEA_Str2num(p1+posx,&dx)/NMEA_Pow(10,dx);
//得到 UTC 时间,去掉 ms
gpsx->utc、hour=8+temp/10000;
if(gpsx->utc、hour>=24)
{
gpsx->utc、hour=gpsx->utc、hour-24;
}
gpsx->utc、min=(temp/100)%100;
gpsx->utc、sec=temp%100;
}
posx=NMEA_Comma_Pos(p1,3);
//得到纬度
if(posx!=0XFF)
{
temp=NMEA_Str2num(p1+posx,&dx);
gpsx->latitude=temp/NMEA_Pow(10,dx+2); //得到°
rs=temp%NMEA_Pow(10,dx+2);
//得到"
gpsx->latitude=gpsx->latitude*NMEA_Pow(10,5)+(rs*NMEA_Pow(10,5-dx))/60;//转换为°
}
posx=NMEA_Comma_Pos(p1,4);
//南纬还就是北纬
if(posx!=0XFF)gpsx->nshemi=*(p1+posx);
posx=NMEA_Comma_Pos(p1,5);
//得到经度
if(posx!=0XFF)
{
temp=NMEA_Str2num(p1+posx,&dx);
gpsx->longitude=temp/NMEA_Pow(10,dx+2); //得到°
rs=temp%NMEA_Pow(10,dx+2);
//得到"
gpsx->longitude=gpsx->longitude*NMEA_Pow(10,5)+(rs*NMEA_Pow(10,5-dx))/60;// 转 换为°
}
posx=NMEA_Comma_Pos(p1,6);
//东经还就是西经
if(posx!=0XFF)gpsx->ewhemi=*(p1+posx);
posx=NMEA_Comma_Pos(p1,9);
//得到 UTC 日期
if(posx!=0XFF)
{
temp=NMEA_Str2num(p1+posx,&dx);
//得到 UTC 日期
gpsx->utc、date=temp/10000;
gpsx->utc、month=(temp/100)%100;
gpsx->utc、year=2000+temp%100;
}
} //分析 GPVTG 信息 //gpsx:nmea 信息结构体 //buf:接收到的 GPS 数据缓冲区首地址 void NMEA_GPVTG_Analysis(nmea_msg *gpsx,u8 *buf) {
u8 *p1,dx;
u8 posx;
p1=(u8*)strstr((const char *)buf,"$GPVTG");
posx=NMEA_Comma_Pos(p1,7);
//得到地面速率
if(posx!=0XFF)
{
gpsx->speed=NMEA_Str2num(p1+posx,&dx);
if(dx<3)gpsx->speed*=NMEA_Pow(10,3-dx);
//确保扩大 1000 倍
} }
//提取 NMEA-0183 信息 //gpsx:nmea 信息结构体 //buf:接收到的 GPS 数据缓冲区首地址 void GPS_Analysis(nmea_msg *gpsx,u8 *buf) {
NMEA_GPGSV_Analysis(gpsx,buf); //GPGSV 解析
NMEA_GPGGA_Analysis(gpsx,buf); //GPGGA 解析
NMEA_GPGSA_Analysis(gpsx,buf); //GPGSA 解析
NMEA_GPRMC_Analysis(gpsx,buf); //GPRMC 解析
NMEA_GPVTG_Analysis(gpsx,buf); //GPVTG 解析 } //GPS 校验与计算 //buf:数据缓存区首地址 //len:数据长度 //cka,ckb:两个校验结果、 void Ublox_CheckSum(u8 *buf,u16 len,u8* cka,u8*ckb) {
u16 i;
*cka=0;*ckb=0;
for(i=0;i<len;i++)
{
*cka=*cka+buf[i];
*ckb=*ckb+*cka;
} } /////////////////////////////////////////UBLOX 配置代码///////////////////////////////////// //检查 CFG 配置执行情况 //返回值:0,ACK 成功 //
1,接收超时错误 //
2,没有找到同步字符 //
3,接收到 NACK 应答 u8 Ublox_Cfg_Ack_Check(void) {
u16 len=0,i;
u8 rval=0;
while((USART1_RX_STA&0X8000)==0 && len<100)//等待接收到应答
{
len++;
delay_ms(5);
}
if(len<250)
//超时错误、
{
len=USART1_RX_STA&0X7FFF; //此次接收到的数据长度
for(i=0;i<len;i++)if(USART1_RX_BUF[i]==0XB5)break;//查找同步字符 0XB5
if(i==len)rval=2;
//没有找到同步字符
else if(USART1_RX_BUF[i+3]==0X00)rval=3;//接收到 NACK 应答
else rval=0;
//接收到 ACK 应答
}else rval=1;
//接收超时错误
USART1_RX_STA=0;
//清除接收
return rval;
} //配置保存 //将当前配置保存在外部 EEPROM 里面
//返回值:0,执行成功;1,执行失败、 u8 Ublox_Cfg_Cfg_Save(void) {
u8 i;
_ublox_cfg_cfg *cfg_cfg=(_ublox_cfg_cfg *)USART1_TX_BUF;
cfg_cfg->header=0X62B5;
//cfg header
cfg_cfg->id=0X0906;
//cfg cfg id
cfg_cfg->dlength=13;
//数据区长度为 13 个字节、
cfg_cfg->clearmask=0;
//清除掩码为 0
cfg_cfg->savemask=0XFFFF;
//保存掩码为 0XFFFF
cfg_cfg->loadmask=0;
//加载掩码为 0
cfg_cfg->devicemask=4;
//保存在 EEPROM 里面
Ublox_CheckSum((u8*)(&cfg_cfg->id),sizeof(_ublox_cfg_cfg)-4,&cfg_cfg->cka,&cfg_cfg->ckb);
while(DMA1_Channel4->CNDTR!=0); //等待通道 7 传输完成
UART_DMA_Enable(DMA1_Channel4,sizeof(_ublox_cfg_cfg)); //通过 dma 发送出去
for(i=0;i<6;i++)if(Ublox_Cfg_Ack_Check()==0)break;
//EEPROM 写入需要比较久时间,所以连续判断多次
return i==6?1:0; } //配置 NMEA 输出信息格式 //msgid:要操作的 NMEA 消息条目,具体见下面的参数表 //
00,GPGGA;01,GPGLL;02,GPGSA; //
03,GPGSV;04,GPRMC;05,GPVTG; //
06,GPGRS;07,GPGST;08,GPZDA; //
09,GPGBS;0A,GPDTM;0D,GPGNS; //uart1set:0,输出关闭;1,输出开启、
//返回值:0,执行成功;其她,执行失败、 u8 Ublox_Cfg_Msg(u8 msgid,u8 uart1set) {
_ublox_cfg_msg *cfg_msg=(_ublox_cfg_msg *)USART1_TX_BUF;
cfg_msg->header=0X62B5;
//cfg header
cfg_msg->id=0X0106;
//cfg msg id
cfg_msg->dlength=8;
//数据区长度为 8 个字节、
cfg_msg->msgclass=0XF0;
//NMEA 消息
cfg_msg->msgid=msgid;
//要操作的 NMEA 消息条目
cfg_msg->iicset=1;
//默认开启
cfg_msg->uart1set=uart1set; //开关设置
cfg_msg->uart2set=1;
//默认开启
cfg_msg->usbset=1;
//默认开启
cfg_msg->spiset=1;
//默认开启
cfg_msg->ncset=1;
//默认开启
Ublox_CheckSum((u8*)(&cfg_msg->id),sizeof(_ublox_cfg_msg)-4,&cfg_msg->cka,&cfg_msg->ckb);
while(DMA1_Channel4->CNDTR!=0); //等待通道 7 传输完成
UART_DMA_Enable(DMA1_Channel4,sizeof(_ublox_cfg_msg)); //通过 dma 发送出去
return Ublox_Cfg_Ack_Check(); } //配置 NMEA 输出信息格式 //baudrate:波特率,4800/9600/19200/38400/57600/115200/230400
//返回值:0,执行成功;其她,执行失败(这里不会返回 0 了) u8 Ublox_Cfg_Prt(u32 baudrate) {
_ublox_cfg_prt *cfg_prt=(_ublox_cfg_prt *)USART1_TX_BUF;
cfg_prt->header=0X62B5;
//cfg header
cfg_prt->id=0X0006;
//cfg prt id
cfg_prt->dlength=20;
//数据区长度为 20 个字节、
cfg_prt->portid=1;
//操作串口 1
cfg_prt->reserved=0;
//保留字节,设置为 0
cfg_prt->txready=0;
//TX Ready 设置为 0
cfg_prt->mode=0X08D0;
//8 位,1 个停止位,无校验位
cfg_prt->baudrate=baudrate; //波特率设置
cfg_prt->inprotomask=0X0007;//0+1+2
cfg_prt->outprotomask=0X0007;//0+1+2
cfg_prt->reserved4=0;
//保留字节,设置为 0
cfg_prt->reserved5=0;
//保留字节,设置为 0
Ublox_CheckSum((u8*)(&cfg_prt->id),sizeof(_ublox_cfg_prt)-4,&cfg_prt->cka,&cfg_prt->ckb);
while(DMA1_Channel4->CNDTR!=0); //等待通道 7 传输完成
UART_DMA_Enable(DMA1_Channel4,sizeof(_ublox_cfg_prt)); //通过 dma 发送出去
delay_ms(200);
//等待发送完成
USART1_Init(baudrate); //重新初始化串口 1
return Ublox_Cfg_Ack_Check();//这里不会反回 0,因为 UBLOX 发回来的应答在串口重新初始化的时候已经被丢弃了、 }
//配置 UBLOX NEO-6 的时钟脉冲输出 //interval:脉冲间隔(us) //length:脉冲宽度(us) //status:脉冲配置:1,高电平有效;0,关闭;-1,低电平有效、 //返回值:0,发送成功;其她,发送失败、 u8 Ublox_Cfg_Tp(u32 interval,u32 length,signed char status) {
_ublox_cfg_tp *cfg_tp=(_ublox_cfg_tp *)USART1_TX_BUF;
cfg_tp->header=0X62B5;
//cfg header
cfg_tp->id=0X0706;
//cfg tp id
cfg_tp->dlength=20;
//数据区长度为 20 个字节、
cfg_tp->interval=interval; //脉冲间隔,us
cfg_tp->length=length;
//脉冲宽度,us
cfg_tp->status=status;
//时钟脉冲配置
cfg_tp->timeref=0;
//参考 UTC 时间
cfg_tp->flags=0;
//flags 为 0
cfg_tp->reserved=0;
//保留位为 0
cfg_tp->antdelay=820;
//天线延时为 820ns
cfg_tp->rfdelay=0;
//RF 延时为 0ns
cfg_tp->userdelay=0;
//用户延时为 0ns
Ublox_CheckSum((u8*)(&cfg_tp->id),sizeof(_ublox_cfg_tp)-4,&cfg_tp->cka,&cfg_tp->ckb);
while(DMA1_Channel4->CNDTR!=0); //等待通道 7 传输完成
UART_DMA_Enable(DMA1_Channel4,sizeof(_ublox_cfg_tp)); //通过 dma 发送出去
return Ublox_Cfg_Ack_Check(); } //配置 UBLOX NEO-6 的更新速率
//measrate:测量时间间隔,单位为 ms,最少不能小于 200ms(5Hz) //reftime:参考时间,0=UTC Time;1=GPS Time(一般设置为 1) //返回值:0,发送成功;其她,发送失败、 u8 Ublox_Cfg_Rate(u16 measrate,u8 reftime) {
_ublox_cfg_rate *cfg_rate=(_ublox_cfg_rate *)USART1_TX_BUF;
if(measrate<200)return 1; //小于 200ms,直接退出
cfg_rate->header=0X62B5; //cfg header
cfg_rate->id=0X0806;
//cfg rate id
cfg_rate->dlength=6;
//数据区长度为 6 个字节、
cfg_rate->measrate=measrate;//脉冲间隔,us
cfg_rate->navrate=1;
//导航速率(周期),固定为 1
cfg_rate->timeref=reftime;
//参考时间为 GPS 时间
Ublox_CheckSum((u8*)(&cfg_rate->id),sizeof(_ublox_cfg_rate)-4,&cfg_rate->cka,&cfg_rate->ckb);
while(DMA1_Channel4->CNDTR!=0); //等待通道 7 传输完成
UART_DMA_Enable(DMA1_Channel4,sizeof(_ublox_cfg_rate));//通过 dma 发送出去
return Ublox_Cfg_Ack_Check(); }
上一篇:网络协议分析实验报告