基于单片机的GPS串口中断接收程序
单片机解析GPS数据

三、单片机解读GPS信息的程序设计用单片机解读GPS信息是GPS模块使用最重要的环节,由于汲设到产品的保密问题,这里只介绍时间的处理方法,而方位、速度的处理方法不做介绍,但通过时间的处理方法,同样可以处理方位、速度。
1、获取GPS模块的输出信息由于GPS模块每秒输出一次:$GPGGA 、$GPGSA、$GPGSV、$GPRMC数据。
速率慢,因此必须采用中断方式接收!(采用查询会造成数据丢失),而且单片机只需要处理$GPRMC 信息,即可得到时间、方位、速度。
程序采用C51编制,在Keil C中编译!code unsigned char GPS_ASC[]="$GPRMC" ;//定义特征字符串unsigned char idata RsBuf[60];//**********************************************************//读取GPS模块串口数据, 采用中断方式void GetRs232_Data() interrupt 4{unsigned char i;unsigned int j;if (RI){RI=0;RsBuf[0]=SBUF;if (RsBuf[0] =='$'){//是GPS数据的开始,进入查询接收for (i=1;i<sizeof(GPS_ASC)-1;i++){j=GetUartDat();//接收下一个数据if (j<256) {RsBuf=(unsigned char)j;if (RsBuf!=GPS_ASC) return;}}//判别是否为$GPRMC数据,是继续接收!for (;i<sizeof(RsBuf);i++){j=GetUartDat();if (j<256) {RsBuf=(unsigned char)j;}else{break;}}// 接收完毕处理数据!if (1==JiaoYanDat(RsBuf)){FormatTimer(RsBuf);//格式化时间FormatSpeed(RsBuf);//处理速度}}}}// 2、接收数据的处理//数据处理前,必须要再次检验是否为$GPRMC信息。
基于单片机的GPS设计

基于单片机的GPS设计随着科技的快速发展,单片机已经成为现代电子技术中不可或缺的一部分。
为了更好地了解单片机的发展和应用,我们需要研究相关的外文文献,对于非母语读者来说,中文翻译也是必不可少的。
本文将介绍一些重要的单片机的外文文献和对应的中文翻译。
"Microcontroller Fundamentals" by John M. Hughes. This book provides a comprehensive introduction to microcontrollers, including their history, architecture, programming, and applications. It is an excellent resource for anyone who wants to learn about microcontrollers."Embedded Systems: A Perspective on MCU and SoC" by Yatin Chaudhary. This book provides an overview of embedded systems, including a detailed discussion on microcontrollers and system-on-chip (SoC) technology. It is a valuable resource for engineers and researchers in the field of embedded systems. "8051 Microcontroller: Architecture, Programming, and Applications" by K.K. Ray and M.K. Dash. This book provides a comprehensive guide to the 8051 microcontroller, including itsarchitecture, programming, and applications. It is an essential resource for students and professionals who want to learn about the 8051 microcontroller.《单片机基础》——李晓明译。
基于STM32F103X单片机与GPS定位的智能导盲系统设计

基于STM32F103X单片机与GPS定位的智能导盲系统设计摘要:在我国虽然盲道设立较为普遍,可是由于很多因素导致盲道设置不合理、被路边摊贩挤占,使得盲道形同虚设。
“盲杖+盲道”的出行方式已经不能够保证盲人的出行安全。
本项目是应用C 语言编程进行模块化设计,对盲人实时定位跟踪,引导行进与扫描物体,通过GPRS通信模块与上位机和手机APP进行通信,实时监控盲人的地理位置、行进路线和报警信息,并储存和在地图上显示。
1.前言盲人由于先天或后天的生理缺陷丧失了视觉,因此,在日常生活和安全行进方面受到很大的制约。
在我国,盲人目前的导盲辅具普遍是普通盲杖,这种导盲辅具不仅功能单一,而且很大程度上不能保证盲人的安全,意外事件屡屡发生。
另外导盲犬的成本高且使用不方便。
导盲机器人只能在平坦路面使用。
虽然智能盲杖的研发已成大势所趋,现有智能盲杖主要是依靠语音提示帮助盲人判别危险,盲人在获得信息后自己处理危险,因此在处理速度、实用性上优胜于传统的盲杖。
但是目前国内外针对智能盲杖的研发一直停留在理论阶段。
本项目主要为了让盲人能够和正常人一样,除了不能享受视觉上的冲击外,可以正常的出行去聆听外面的世界,感知周围的环境。
与传统的导盲手段相比,盲人可以还通过扫描系统在购物时去选择自己喜欢的东西,去获取更多的信息,让自己的生活多一分快乐。
同时依靠GPS和手机APP的使用使该智能导盲系统精度高,可靠性高,保障了使用者的生命安全。
安全,可靠性高的导盲系统使导盲人的生活充满乐趣,改变了人们心中盲人外出不安全的老旧观念,也使盲人的生活更加自由。
所以一种实用的多功能智能导盲系统,它能够帮助盲人在无需专人陪伴的情况下,独立外出行走,并且在出现紧急情况时,可以实现远程求助。
外出购物时,可以通过扫描识别来进行货物的兑换。
2.硬件设计系统主要由主控制器、超声波测距模块、红外线测距模块、GPS模块、GPRS模块、语音合成模块、报警模块,条码扫码模块构成。
GPS串口数据接收程序实例

[GPS串口数据接收程序实例]摘要:目前GPS(全球定位系统)定位应用市场日趋成熟,正在进入应用的高速发展时期,GPS串口数据接收程序实例。
本文以一款EverMore公司的GM-X205GPS接受模块为例,介绍了其数据格式,以及应用PIC16F874单片机RS232串口进行数据接收的程序。
关键词:GPS、NMEA格式、PIC16F874、串口数据接收1、GPS应用简介近年来GPS系统,已经在大地测绘、海上渔用、车辆定位监控、建筑、农业等各个领域得到广泛应用。
从九十年代我国引进GPS定位技术开始,经过十多年的市场培育,GPS定位应用进入了发展的最好时机,未来十年基于GPS的应用将会改变我们的生活和工作方式。
目前市场上的大部分GPS接受模块都是通过RS232串口与MCU进行数据传输的。
这些数据包括经度、纬度、海拔高度、时间、卫星使用情况等基本信息。
开发人员再依据这些基本数据,进行数据处理来完成整套的定位系统软件。
2、GM-X205模块数据格式在进行数据接受编程之前,先介绍一下该模块的数据格式。
它支持NMEA-0183输出格式,电子通信论文《GPS串口数据接收程序实例》。
◆分享好文◆信息如下:GGA位置测定系统定位资料(Global Positioning System Fix Data)VTG 方向及速度等相关资料(Course Over Ground and Ground Speed)由于文章篇幅问题,笔者在这里只以接收GGA数据为例,格式如下:$GPGGA,hhmmss,dddmm.mmmm,a,dddmm.mmmm,a,x,xx,x.x,x.x,M,,M,x.x,xxxx*CS例:$GPGGA,033744,2446.5241,N,12100.1536,E,1,10,0.8,133.4,M,,,,*1F说明见表:区域名称例单位说明1信息ID $GPGGA[1][2][3][4][5][6]。
stm32串口通信死在接收中断中的解决方法

stm32串⼝通信死在接收中断中的解决⽅法现象: 使⽤stm32f0xx系列的芯⽚,串⼝1使⽤接收中断时,当接收到⼀个数据时死在串⼝中断中,发⽣了串⼝中断溢出。
原因解释:在使⽤⼀个串⼝发数据的传感器过程中,发现程序第⼀次进⼊串⼝中断之后不再执⾏主函数的内容,中断中的内容也不执⾏。
查询⼤量资料后发现:串⼝在接收数据过多时,会出现串⼝溢出错误,并进⼊溢出中断(ORE中断)。
接下来是错误产⽣原因以及解决⽅法。
(1)什么是ORE中断?为什么会产⽣?产⽣原因如上所述。
ORE标志位在USART_SR寄存器,但值得注意的是,当我们打开串⼝接收中断时,同时也就打开了ORE中断。
(2)如何解决?看了上⾯的资料之后,我知道程序是死在了串⼝溢出中断。
处理中断时,我⾸先想到的是清除这个中断标志位,但是遇到了很多⿇烦。
解决⽅法: void USART1_IRQHandler(void){ /* 加⼊清除标志位,否则会卡死在串⼝中断服务函数中 */ uint8_t ucTemp; if(USART_GetITStatus(DEBUG_USARTx,USART_IT_RXNE)!=RESET) //检查 USART 是否发⽣中断 { USART_ClearITPendingBit(DEBUG_USARTx,USART_IT_RXNE); // 清中断标志 ucTemp=USART_ReceiveData(DEBUG_USARTx); } if(USART_GetFlagStatus(DEBUG_USARTx,USART_FLAG_ORE) == SET) // 检查 ORE 标志 { USART_ClearFlag(DEBUG_USARTx,USART_FLAG_ORE); USART_ReceiveData(DEBUG_USARTx); }}。
基于单片机的GPS定位系统设计

基于单片机的GPS定位系统设计摘要:GPS全球定位系统在实际生活中被广泛应用,是当今信息数字化时代发展中的重要组成部分。
因其具有性能好、精度高、应用广的特点,使其成为迄今为止最好的定位导航系统。
本次设计以单片机为核心,通过GPS接收模块接收GPS卫星信号,然后将数据发送到单片机的串口。
单片机执行串口中断,提取所需要的数据并进行处理,最后将处理的数据通过液晶屏显示,成功实现定位。
本系统由52单片机、GPS模块M-87、12864液晶屏等硬件组成,应用C语言编程,完成了GPS信息的提取、处理和显示。
系统可以显示当地经度、纬度、时间、高度等信息,是一台体积小巧、携带方便、可以独立使用的全天候实时的定位导航设备。
关键词:单片机;GPS接收模块;12864液晶屏;串行通信总体方案的设计:本次设计以单片机(STC89C52)为核心,首选通过GPS(M-87)接收模块接收GPS卫星信号,然后将数据发送到单片机的串口,单片机执行串口中断,提取所需要的数据并处理,最后将处理后的数据通过液晶显示屏(LCD12864)显示。
该GPS定位系统硬件电路主要由以下几个部分组成:(1) 控制部分:以STC89C52单片机为核心的小型控制系统;(2)接收部分:以GPS(M-87)接收模块为核心的GPS接收机;(3)显示部分:由LCD12864构成的液晶显示电路;(4)电源部分: 由三节1.5V干电池串连而成的电源进行供电。
该GPS定位系统软件部分主要由以下几个部分组成:(1)串口初始化程序:对TMOD、TH1、TL1、REN、RI、TI等进行赋初值;(2)液晶初始化程序:令PSB=1使LCD为并口方式及LCD开、关标设定等;(3)数据接收与处理程序:编写数据提取与处理程序,实时接收与处理数据。
(4)延时程序:编写延时函数,延时函数可以控制液晶屏内容的显示时长;由此可知:GPS接收模块将接收到的GPS卫星导航电文调制解码,转换为标准格式后,通过串行口将数据送给单片机,当单片机执行串口中断收到GPS接收模块发来的数据,经过片内程序的识别筛选,将筛选出来的数据进行处理后送到显示模块,最后通过液晶显示屏按照要求显示。
基于单片机的GPS定位系统设计【范本模板】
基于单片机的GPS定位系统设计摘要GPS是全球定位系统英文名词Global Positioning System的缩写.该系统是美国布设的第二代卫星无线电导航系统。
它能为用户提供全球性、全天候、连续、实时、高精度的三维坐标、三向速度和时间信息.其目的是在全球范围内对地面和空中目标进行准确定位和监测。
现在,GPS接收机作为一种先进的导航和定位仪器,已在军事及民用领域得到广泛的应用。
本设计是基于AT89C51单片机来实现的简易GPS定位信息显示系统。
本控制系统主要完成接受数据、时间显示、经度显示、纬度显示等常规功能.此方案基于单片机、GPS模块和12864液晶显示屏等硬件,并应用C语言实现了GPS信号的提取、显示及基本的键盘控制操作等。
经过实践测试,这种接收机可以达到基本GPS信息的接收以及显示,可以做到体积小、精度高、连续导航,并可广泛应用于个人野外旅游探险、出租汽车定位及海上作业等领域。
关键词:GPS定位系统,单片机,液晶显示屏DESIGN OF GPS RECEIVER BASED ON 51 SINGLE CHIPCOMPUTERABSTRACTGPS is the abbreviation of the English term Global Positioning System global positioning system. The system is the United States laid the second generation satellite radio navigation system. It can provide users with continuous, real—time,global, round—the—clock,high precision three dimensional coordinates, three velocity and time information. Aimed at targets on the ground and in the air around the world an accurate positioning and monitoring。
基于单片机的GPS全球卫星定位系统设计
目录第一章GPS简介及基本理论 (2)1.1 GPS的概述 (2)1.2 GPS的组成 (3)1.3 GPS的发展趋势 (3)1.4 Globalsat和HOLUX的EB-3531 (4)1.5 EB-3531的特点 (5)第二章硬件电路设计 (7)2.1 电源转换电路设计 (7)2.2 GPS接收模块与单片机接口电路设计 (9)2.3 单片机控制系统的硬件电路 (9)第三章软件部分设计 (11)3.1 串口通行模块 (11)3.2主程序设计 (13)第四章调试 (15)4.1 硬件调试 (15)4.2 软件调试 (15)第五章总结 (17)致谢 (18)参考文献 (19)第一章 GPS简介及基本理论1.1 GPS的概述GPS是英文Navigation Satellitte Timing and Ranging/Global Positioning System的字头缩写词(NAVSTAR/GPS)的简称。
它的含义是,利用卫星的测时和测距进行导航,以构成全球卫星定位系统。
现在国际上已经公认:将这一全球定位系统简称:GPS。
GPS系统的前身为美军研制的一种“子午仪”导航卫星系统(Transit),1958年研制,64年正式投入使用。
该系统用5到6颗卫星组成的星网工作,每天最多绕过地球13次,并且无法给出高度信息,在定位精度方面也不尽如人意。
然而,子午仪系统使得研发部门对卫星定位取得了初步的经验,并验证了由卫星系统进行定位的可行性,为GPS系统的研制埋下了铺垫。
由于卫星定位显示出在导航方面的巨大优越性及子午仪系统存在对潜艇和舰船导航方面的巨大缺陷。
美国海陆空三军及民用部门都感到迫切需要一种新的卫星导航系统。
为此,美国海军研究实验室(NRL)提出了名为Tinmation的用12到18颗卫星组成10000km高度的全球定位网计划,并于67年、69年和74年各发射了一颗试验卫星,在这些卫星上初步试验了原子钟计时系统,这是GPS系统精确定位的基础。
串口中断接收数据流程
串口中断接收数据流程串口(UART)中断接收数据是一个异步的过程,涉及一系列离散事件。
它允许微控制器在不连续地轮询串口状态的情况下接收串行数据。
1. 数据帧接收传输器将数据帧以串行比特流的形式发送到接收器。
数据帧由一个起始位、一个或多个数据位、一个奇偶校验位和一个停止位组成。
2. 起始位检测微控制器检测到串口线上电平从高转低,这表示起始位的开始。
3. 数据位接收微控制器在每个时钟周期采样串口线并读取数据位。
数据位数取决于串口配置,通常为 5、6、7 或 8 位。
4. 奇偶校验(可选)如果启用奇偶校验,微控制器会检查接收到的数据位的奇偶性和期望的奇偶性是否匹配。
5. 停止位检测接收器检测到串口线上电平从低转高,这表示停止位的开始。
6. 中断触发当接收到一个完整的帧时,微控制器会触发一个中断。
7. 中断服务程序(ISR)ISR负责读取接收到的数据帧并将其存储在缓冲区中。
ISR还可能会重置一些标志位,如数据溢出标志位,以确保正确接收后续数据帧。
影响因素串口中断接收数据流程的效率和可靠性受以下因素影响:波特率:波特率越低,接收数据所需的时间就越长。
数据位数:数据位数越多,每个帧的传输时间就越长。
奇偶校验:奇偶校验增加了额外的开销,但可以提高数据的可靠性。
中断响应时间:中断响应时间应足够快,以免丢失数据。
优化策略为了优化串口中断接收数据流程,可以采用以下策略:使用合适的波特率和数据位数:选择最能满足特定应用需求的波特率和数据位数。
仅在需要时启用奇偶校验:奇偶校验提供了可靠性,但增加了开销。
优化ISR:确保ISR高效且快速,以避免丢失数据。
使用正确的中断优先级:赋予串口接收中断一个适当的优先级,以确保它在需要时得到正确处理。
单片机程序
51 单片机处理GPS 信号程序附录B:程序#include "display.h"GPS_INFO GPS; //GPS 信息结构体GPS 为结构体类型变量uchar code beiwei[] = "北纬";uchar code nanwei[] = "南纬";uchar code dongjing[] = "东经";uchar code xijing[] = "西经";uchar code sudu[] = "速度: ";uchar code hangxiang[] = "航向: ";uchar code gaodu[] = "高度: ";uchar code jiaodu[] = "角度: ";uchar code haiba[] = "海拔: ";uchar code du[] = "度";uchar code meter[] = "米";uchar code kmperhour[] = "km/h";uchar code date[] = " 年月日";void Show_Float(float fla, uchar x, uchar y);void GPS_DispTime(void){ uchari = 0;ucharch;char time[5];Lcd_DispLine(0, 0, date); //年月日Int_To_Str(GPS.D.year,time); //将年转换成字符串,存在time 中Lcd_SetPos(0, 0); //设置显示地址51 单片机处理GPS 信号程序if(strlen(time)==4) //判断接收数据是否有效,有效则显示{ i = 0;while(time[i] != '\0'){ ch = time[i++]; Lcd_WriteDat(ch); //显示年}}Int_To_Str(GPS.D.month,time);Lcd_SetPos(0, 3);if(strlen(time)==2) //判断接收数据是否有效,有效则显示{ i = 0;while(time[i] != '\0'){ ch =time[i++];Lcd_WriteDat(ch);}}Int_To_Str(GPS.D.day,time);Lcd_SetPos(0, 5);if(strlen(time)==2) //判断接收数据是否有效,有效则显示{ i = 0;while(time[i] != '\0'){ ch =time[i++];Lcd_WriteDat(ch);}}Int_To_Str(GPS.D.hour,time);Lcd_SetPos(1, 1);if(strlen(time)==2) //判断接收数据是否有效,有效则显示{ i = 0;while(time[i] != '\0'){ch =time[i++];Lcd_WriteDat(ch);}}Lcd_WriteDat(' ');Lcd_WriteDat(':');Int_To_Str(GPS.D.minute,time);Lcd_SetPos(1, 3); if(strlen(time)==2) //判断接收数据是否有效,有效则显示{ i = 0;while(time[i] != '\0'){ch =time[i++];Lcd_WriteDat(ch);}}Lcd_WriteDat(' ');Lcd_WriteDat(':');Int_To_Str(GPS.D.second,time);Lcd_SetPos(1, 5);if(strlen(time)==2) //判断接收数据是否有效,有效则显示{i = 0;while(time[i] != '\0'){ch =time[i++];Lcd_WriteDat(ch);}}}void GPS_DisplayOne(void) //第一屏{ucharch, i;char info[10];ET0=0; //T0 的溢出中断允许位,禁止T0 的溢出中断clr_screen();//Lcd_WriteCmd(0x01); //清屏GPS_DispTime(); //显示日期,时间if (GPS.NS == 'N') //判断是北纬还是南纬Lcd_DispLine(2, 0, beiwei);else if (GPS.NS == 'S')Lcd_DispLine(2, 0, nanwei);if (GPS.EW == 'E') //判断是东经还是西经Lcd_DispLine(3, 0, dongjing);else if (GPS.EW == 'W')Lcd_DispLine(3, 0, xijing);Int_To_Str(titude_Degree,info); //纬度Lcd_SetPos(2, 2);if(strlen(info)==2){ //只有正常显示纬度,才显示纬分i = 0;while(info[i] != '\0'){ ch = info[i++];Lcd_WriteDat(ch);}Lcd_WriteDat(' ');Lcd_WriteDat(' ');Lcd_WriteDat(0xA1);Lcd_WriteDat(0xE3); //显示度的符号Int_To_Str(titude_Cent,info); //纬分if(strlen(info)==2){ //只有正常显示纬分,才显示纬秒i = 0;while(info[i] != '\0'){ ch = info[i++];Lcd_WriteDat(ch);}Lcd_WriteDat(0xA1);Lcd_WriteDat(0xE4); //显示秒的符号Int_To_Str(titude_Second,info); //纬秒if(strlen(info)==2){ i = 0;while(info[i] != '\0'){ ch = info[i++];Lcd_WriteDat(ch);}}}}Int_To_Str(GPS.longitude_Degree,info); //经度if(strlen(info)==3){ Lcd_DispLine(3, 2, info);Lcd_WriteDat(' ');Lcd_WriteDat(0xA1); Lcd_WriteDat(0xE3);Int_To_Str(GPS.longitude_Cent,info); //经分if(strlen(info)==2){ Lcd_DispLine(3, 5, info);Lcd_WriteDat(0xA1);Lcd_WriteDat(0xE4);Int_To_Str(GPS.longitude_Second,info); //经秒if(strlen(info)==2){ Lcd_DispLine(3, 7, info);}}}ET0=1;}void GPS_DisplayTwo(void) //第二屏用于显示单位{ clr_screen();//Lcd_WriteCmd(0x01); //清屏ET0=0;Lcd_DispLine(0, 0, sudu);Lcd_DispLine(1, 0, hangxiang);Lcd_DispLine(2, 0, gaodu);Lcd_DispLine(3, 0, haiba);Show_Float(GPS.speed, 0, 3);Lcd_DispLine(0, 6, kmperhour);Show_Float(GPS.direction, 1, 3);Lcd_DispLine(1, 6, du);Show_Float(GPS.height_ground, 2, 3);Lcd_DispLine(2, 6, meter);Show_Float(GPS.height_sea, 3, 3);Lcd_DispLine(3, 6, meter);ET0=1;}void Show_Float(float fla, uchar x, uchar y){ intintegar;char Info[10],ch;uchari;Lcd_SetPos(x, y);integar = (int)fla; // 显示整数部分Int_To_Str(fla,Info); //显示整数部分i = 0;while(Info[i] !='\0'){ ch=Info[i++];Lcd_WriteDat(ch);}Lcd_WriteDat('.'); //显示小数点fla = fla - integar; //显示小数部分fla = fla * 10; //0.1 // 显示0.1integar = (int) fla; fla = fla - integar; // 改变fla 的值,使fla 总是小于1ch = integar + 0x30;Lcd_WriteDat(ch);fla = fla*10; //0.01 // 显示0.01integar = (int) fla;fla = fla - integar; // 改变fla 的值,使fla 总是小于1ch = integar + 0x30 ;Lcd_WriteDat(ch);}GPS 程序:#include "GPS.h"#include "LCD.h"#include <string.h>uchar code init1[] = {"BASE-MCU GPS 终端"};uchar code init2[] = {"商院电信091 班"};uchar code init3[] = {"GPS 初始化......"};uchar code init4[] = {"搜索定位卫星...."};static ucharGetComma(ucharnum,char* str);static double Get_Double_Number(char *s); //得到双精度的数据static float Get_Float_Number(char *s); //得到单精度的数据static void UTC2BTC(DATE_TIME *GPS); //格林时间到北京时间的转换void GPS_Init(void) //GPS 初始化{ Lcd_DispLine(0, 0, init1);Lcd_DispLine(1, 0, init2);Lcd_DispLine(2, 0, init3);Lcd_DispLine(3, 0, init4);}intGPS_RMC_Parse(char *line,GPS_INFO *GPS) //运输定位数据最大帧70 { //*GPS 为结构体类型的指针ucharch, status, tmp;float lati_cent_tmp, lati_second_tmp; //经度的分、秒临时变量float long_cent_tmp, long_second_tmp; //纬度的分、秒临时变量float speed_tmp; //速度的临时变量char *buf = line;ch = buf[5];status = buf[GetComma(2, buf)]; //定位状态给status,判断是否是A,if (ch == 'C') //如果第五个字符是C,($GPRMC)推荐最小定位信息{ if (status == 'A') //如果数据有效,则分析‘V’无效,‘A’有效{ GPS -> NS = buf[GetComma(4, buf)];GPS -> EW = buf[GetComma(6, buf)];GPS->latitude = Get_Double_Number(&buf[GetComma(3, buf)]); // 经度GPS->longitude = Get_Double_Number(&buf[GetComma(5, buf)]); //纬度GPS->latitude_Degree = (int)GPS->latitude / 100; //分离纬度lati_cent_tmp = (GPS->latitude - GPS->latitude_Degree * 100);GPS->latitude_Cent = (int)lati_cent_tmp;lati_second_tmp = (lati_cent_tmp - GPS->latitude_Cent) * 60;GPS->latitude_Second = (int)lati_second_tmp;GPS->longitude_Degree = (int)GPS->longitude / 100; //分离经度long_cent_tmp = (GPS->longitude -GPS->longitude_Degree * 100); GPS->longitude_Cent = (int)long_cent_tmp;long_second_tmp = (long_cent_tmp -GPS->longitude_Cent) * 60; GPS->longitude_Second = (int)long_second_tmp;speed_tmp = Get_Float_Number(&buf[GetComma(7, buf)]); //速度(单位:海里/时) GPS->speed = speed_tmp * 1.85; //1 海里=1.85 公里GPS->direction = Get_Float_Number(&buf[GetComma(8, buf)]); //角度GPS->D.hour = (buf[7] - '0') * 10 + (buf[8] - '0'); //时间GPS->D.minute = (buf[9] - '0') * 10 + (buf[10] - '0');GPS->D.second = (buf[11] - '0') * 10 + (buf[12] - '0');tmp = GetComma(9, buf);GPS->D.day = (buf[tmp + 0] - '0') * 10 + (buf[tmp + 1] - '0'); //日期GPS->D.month = (buf[tmp + 2] - '0') * 10 + (buf[tmp + 3] - '0');GPS->D.year = (buf[tmp + 4] - '0') * 10 + (buf[tmp + 5] - '0')+2000;UTC2BTC(&GPS->D);return 1;}}return 0;}intGPS_GGA_Parse(char *line,GPS_INFO *GPS) //全球定位数据,最大帧为72 { //丛这个数据得到海拔的数据ucharch, status;char *buf = line; ch = buf[4];status = buf[GetComma(2, buf)];if (ch == 'G') //$GPGGA 丛这个数据得到海拔的数据{ if (status != ','){GPS->height_sea = Get_Float_Number(&buf[GetComma(9, buf)]);GPS->height_ground = Get_Float_Number(&buf[GetComma(11, buf)]);return 1;}}return 0;}static float Str_To_Float(char *buf) //字符串到单精度的转换函数{ float rev = 0;float dat;int integer = 1;char *str = buf; //inti;while(*str != '\0'){ switch(*str){ case '0':dat = 0;break;case '1':dat = 1;break;case '2':dat = 2;break;case '3':dat = 3;break;case '4':dat = 4;break;case '5':dat = 5;break;case '6':dat = 6;break;case '7':dat = 7;break;case '8':dat = 8;break;case '9':dat = 9;break;case '.':dat = '.';break;}if(dat == '.'){ integer = 0;i = 1;str ++;continue;}if( integer == 1 ){rev = rev * 10 + dat;}else{ rev = rev + dat / (10 * i);i = i * 10 ;}str ++;}return rev;}static float Get_Float_Number(char *s){ char buf[10];uchari;float rev;i=GetComma(1, s);i = i - 1;strncpy(buf, s, i);buf[i] = 0;rev=Str_To_Float(buf);return rev;}static double Str_To_Double(char *buf) //字符串到双精度的转换函数{ double rev = 0;double dat;int integer = 1;char *str = buf;inti;while(*str != '\0'){ switch(*str) {case '0':dat = 0;break;case '1':dat = 1;break;case '2':dat = 2;break;case '3':dat = 3;break;case '4':dat = 4;break;case '5':dat = 5;break;case '6':dat = 6;break;case '7':dat = 7;break;case '8':dat = 8;break;case '9':dat = 9;break;case '.':dat = '.';break; }if(dat == '.'){integer = 0;i = 1;str ++;continue;}if( integer == 1 ){ rev = rev * 10 + dat;}else{rev = rev + dat / (10 * i);i = i * 10 ;}str ++;}return rev;}static double Get_Double_Number(char *s){ char buf[10];uchari;double rev;i=GetComma(1, s);i = i - 1;strncpy(buf, s, i);buf[i] = 0;rev=Str_To_Double(buf);return rev;}static ucharGetComma(ucharnum,char *str){ uchari,j = 0;intlen=strlen(str); //字符串的长度for(i = 0;i <len;i ++){ if(str[i] == ',') //计算字符串中的逗号的个数j++;if(j == num)return i + 1; //把逗号后的字符下标值返回}return 0;}static void UTC2BTC(DATE_TIME *GPS){ GPS->second ++;if(GPS->second > 59){ GPS->second = 0;GPS->minute ++;if(GPS->minute > 59){ GPS->minute = 0;GPS->hour ++;}}GPS->hour = GPS->hour + 8;if(GPS->hour > 23){ GPS->hour -= 24;GPS->day += 1;if(GPS->month == 2 ||GPS->month == 4 ||GPS->month == 6 ||GPS->month == 9 ||GPS->month == 11 ){ if(GPS->day > 30){ GPS->day = 1;GPS->month++;}}else{ if(GPS->day > 31){ GPS->day = 1;GPS->month ++;}}if(GPS->year % 4 == 0 ){ if(GPS->day > 29 && GPS->month == 2){ GPS->day = 1;GPS->month ++;}}else{ if(GPS->day > 28 &&GPS->month == 2){ GPS->day = 1;GPS->month ++;}}if(GPS->month > 12){ GPS->month -= 12;GPS->year ++;}}}void Int_To_Str(intx,char *Str){ int t;char *Ptr,Buf[5];inti = 0;Ptr = Str;if(x < 10) // 当整数小于10 时,转化为"0x"的格式{ *Ptr ++ = '0';*Ptr ++ = x+0x30;}else{ while(x > 0){t = x % 10;x = x / 10;Buf[i++] = t+0x30; // 通过计算把数字转化成ASCII 码形式}i -- ;for(;i>= 0;i --) // 将得到的字符串倒序{*(Ptr++) = Buf[i];}}*Ptr = '\0';}LCD 程序:#include "LCD.h"void delay(uint z) // 延时1MS{ uint x, y;for (x = z; x > 0; x--)for(y = 110; y > 0; y--);}void clr_screen(){ Lcd_WriteCmd(0x34); //扩充指令操作delay(5);Lcd_WriteCmd(0x30); //基本指令操作delay(5);Lcd_WriteCmd(0x01); //清屏delay(5);}void Lcd_WriteCmd(ucharcmd) //LCD 命令写入函数{LCD_RS = 0;LCD_RW = 0;LCD_EN = 0;_nop_();_nop_();delay(5);P0 = cmd;DelayNOP();LCD_EN = 1;DelayNOP();LCD_EN = 0; ;}void Lcd_WriteDat(uchardat) //LCD 数据写入函数{LCD_RS = 1;LCD_RW = 0;LCD_EN = 0;P0 = dat;delay(5);DelayNOP();LCD_EN = 1;DelayNOP();LCD_EN = 0;}void Lcd_Init(void){ Lcd_WriteCmd(0x34); //扩充指令操作delay(5);Lcd_WriteCmd(0x30); //基本指令操作delay(5);Lcd_WriteCmd(0x0C); //显示开,关光标delay(5);Lcd_WriteCmd(0x01); //清除LCD 的显示内容delay(5);}void Lcd_SetPos(ucharX,uchar Y) //显示地址处理{ucharpos;if (X==0){X=0x80;}else if (X==1){X=0x90;}else if (X==2){X=0x88;}else if (X==3){X=0x98;}pos = X+Y ;Lcd_WriteCmd(pos); //显示地址}void Lcd_DispLine(uchar line, ucharpos, uchar *str){inti = 0;Lcd_SetPos(line, pos); //LCD 显示位置设定while (str[i] != '\0'){ Lcd_WriteDat(str[i]); //LCD 显示数据i++;}}源程序:#include <reg51.h>#include <stdio.h>#include <string.h>#include "GPS.h"#include "LCD.h"#include "display.h"sbit led1 = P2^0; //接收数据指示灯sbit led2 = P2^1; //GPRMC 数据有效指示灯sbit led3 = P2^2; //GPGGA 数据有效指示灯#define REV_YES led1 = 0#define REV_NO led1 = 1#define RMC_YES led2 = 0#define RMC_NO led2 = 1#define GGA_YES led3 = 0#define GGA_NO led3 = 1char xdatarev_buf[80]; //接收缓存ucharxdatarev_start = 0; //接收开始标志ucharxdatarev_stop = 0; //接收停止标志ucharxdatagps_flag = 0; //GPS 处理标志ucharxdatachange_page = 0; //换页显示标志ucharxdatanum = 0; //extern GPS_INFO GPS; //在display.c 中定义,使用时要加extern/*****************************//********初始化串口***********//******************************/void Uart_Init(void){TMOD = 0x21; //0010 0001 定时器1 工作在模式2(8 位自动重装)//定时器0 工作在模式1(16 位定时器/计数器)//SCON=0X50;PCON=0X00;TH0=0x3c;TL0=0xb0;TH1=0xFa; // 波特率为4800TL1=0xFa; //TR1=1; //开启定时器1REN=1; //允许接收数据SM0=0; //串口工作在第一模式SM1=1;TI=0; //发送中断清0RI=0; //接收中断清0EA=1; //开总中断ES=1; //串口1 中断允许ET0 = 1; //定时器0 中断允许}/****************************************主函数/****************************************/void main(void){ ucharerror_num = 0;Uart_Init(); //初始化串口Lcd_Init(); //初始化LCDGPS_Init(); //初始化GPSrev_stop=0; //接收停止标志REV_NO; //接收数据指示灯关while(1){if (rev_stop) //如果接收完一行{TR0 = 1; //开启定时器0REV_YES; //接收数据指示灯开if ( change_page % 2 == 1) //换页{if (GPS_GGA_Parse(rev_buf, &GPS)) //解析GPGGA{GGA_YES;GPS_DisplayTwo(); //显示第二页信息error_num = 0;gps_flag = 0; //GPS 处理标志rev_stop = 0; //接收停止标志REV_NO; //接收数据指示灯关}else{error_num++;if (error_num>= 20) //如果数据无效超过20 次{GGA_NO; //GPGGA 数据无效指示灯error_num = 20;GPS_Init(); //返回初始化}gps_flag = 0;rev_stop = 0;REV_NO;}}else{if (GPS_RMC_Parse(rev_buf, &GPS)) //解析GPRMC{RMC_YES;GPS_DisplayOne(); //显示GPS 第一页信息error_num = 0;gps_flag = 0;rev_stop = 0;REV_NO;}else{error_num++;if (error_num>= 20) //如果数据无效超过20 次{RMC_NO;error_num = 20;GPS_Init(); //返回初始化}gps_flag = 0;rev_stop = 0;REV_NO;}}}}}/***************************************************************//*************************定时器0 用作换页***********************/ /***************************************************************/void timer0(void) interrupt 1{ static uchar count = 0;TH0 = 0x3c;TL0 = 0xb0;if (count == 200) //2*5 秒钟{count = 0;change_page++; //换页if (change_page == 10)change_page=0;}}/***************************************************************//*************************串口数据接收**************************//***************************************************************/ void Uart_Receive(void) interrupt 4{ucharch;ES = 0; //串口1 中断禁止if (RI) //如果接收完成则进入{ch = SBUF;if ((ch == '$') && (gps_flag == 0)) //如果收到字符'$',便开始接收{rev_start = 1;rev_stop = 0; //接收停止标志}if (rev_start == 1) //标志位为1,开始接收{rev_buf[num++] = ch; //字符存到数组中if (ch == '\n') //如果接收到换行{rev_buf[num] = '\0';rev_start = 0;rev_stop = 1; //接收停止标志gps_flag = 1;num = 0;}}}RI = 0; //RI 清0,重新接收ES = 1; //串口1 中断允许}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include<reg52.h>#include "1602.h"sbit GPS_SPD=P1^1; //GPS模块速率设置sbit KEY1=P1^0; //显示内容分屏切换char code TIME_AREA= 8; //时区//GPS数据存储数组unsigned char JD[10]; //经度unsigned char JD_a; //经度方向unsigned char WD[9]; //纬度unsigned char WD_a; //纬度方向unsigned char date[6]; //日期unsigned char time[6]; //时间unsigned char speed[5]={'0','0','0','0','0'}; //速度unsigned char high[6]; //高度unsigned char angle[5]; //方位角unsigned char use_sat[2]; //使用的卫星数unsigned char total_sat[2]; //天空中总卫星数unsigned char lock; //定位状态//串口中断需要的变量unsigned char seg_count; //逗号计数器unsigned char dot_count; //小数点计数器unsigned char byte_count; //位数计数器unsigned char cmd_number; //命令类型unsigned char mode; //0:结束模式,1:命令模式,2:数据模式unsigned char buf_full; //1:整句接收完成,相应数据有效。
0:缓存数据无效。
unsigned char cmd[5]; //命令类型存储数组//显示需要的变量unsigned int dsp_count; //刷新次数计数器unsigned char time_count;bit page;void sys_init(void);bit chk_key(void);main(){unsigned char i;char Bhour;sys_init();lock=1;use_sat[0]='0';use_sat[1]='0';total_sat[0]='0';total_sat[1]='0';while(1){if(buf_full==0) //无GPS信号时{dsp_count++;if(dsp_count>=65000){LCD_cls(); //清屏LCD_write_string(0,0,"No GPS connect..");LCD_write_string(0,1,"Please Check..");while(buf_full==0);LCD_cls();dsp_count=0;}}else{ //有GPS信号时if(chk_key()){ //检测到按键切换显示page=!page;LCD_cls();}if(!page){ //页面1if(buf_full|0x01){ //GGA语句if(lock==0){ //如果未定位LCD_write_string(0,0,"*---.--.---- ");LCD_write_string(0,1,"* --.--.---- ");}else{ //如果已定位LCD_write_char(0,0,JD_a); //显示经度for(i=0;i<10;i++){LCD_write_char(i+1,0,JD[i]);}LCD_write_char(0,1,WD_a); //显示纬度LCD_write_char(1,1,' ');for(i=0;i<9;i++){LCD_write_char(i+2,1,WD[i]);}}LCD_write_char(14,1,use_sat[0]); //显示接收卫星数LCD_write_char(15,1,use_sat[1]);buf_full&=~0x01;dsp_count=0;}if(buf_full|0x02){ //GSV语句LCD_write_char(14,1,total_sat[0]);LCD_write_char(15,1,total_sat[1]);buf_full&=~0x02;dsp_count=0;}if(buf_full|0x04){if(lock==0){ //如果未定位LCD_write_string(0,0,"*---.--.---- ");LCD_write_string(0,1,"* --.--.---- ");}else{ //如果已定位LCD_write_char(0,0,JD_a); //显示经度for(i=0;i<10;i++){LCD_write_char(i+1,0,JD[i]);}LCD_write_char(0,1,WD_a); //显示纬度LCD_write_char(1,1,' ');for(i=0;i<9;i++){LCD_write_char(i+2,1,WD[i]);}}LCD_write_char(14,0,use_sat[0]); //显示接收卫星数LCD_write_char(15,0,use_sat[1]);buf_full&=~0x04;dsp_count=0;}}else{ //页面2if(buf_full|0x01){ //GGA语句buf_full&=~0x01;dsp_count=0;}if(buf_full|0x02){buf_full&=~0x02;dsp_count=0;}if(buf_full|0x04){ //RMC语句Bhour=((time[0]-0x30)*10+time[1]-0x30)+TIME_AREA;if(Bhour>=24){Bhour-=24;}else if(Bhour<0){Bhour+=24;}LCD_write_char(0,1,date[4]);LCD_write_char(1,1,date[5]);LCD_write_char(2,1,date[2]);LCD_write_char(3,1,date[3]);LCD_write_char(4,1,date[0]);LCD_write_char(5,1,date[1]);LCD_write_char(8,1,Bhour/10+0x30);LCD_write_char(9,1,Bhour%10+0x30);LCD_write_char(10,1,':');LCD_write_char(11,1,time[2]);LCD_write_char(12,1,time[3]);LCD_write_char(13,1,':');LCD_write_char(14,1,time[4]);LCD_write_char(15,1,time[5]);LCD_write_string(5,0,"knot A");if(lock=='0'){ //如果未定位LCD_write_string(0,0,"---.-");LCD_write_string(11,0,"---.-");}else{ //已经定位for(i=0;i<5;i++){ //knot显示LCD_write_char(i,0,speed[i]);}for(i=0;i<5;i++){LCD_write_char(11+i,0,angle[i]);}}buf_full&=~0x04;dsp_count=0;}}}}}bit chk_key(void){if(!KEY1){delayms(10);if(!KEY1){while(!KEY1);delayms(10);return(1);}}return(0);}//系统初始化void sys_init() {unsigned char i;SCON = 0x50; /* SCON: mode 1, 8-bit UART, enable rcvr */TMOD = 0x21; /* TMOD: timer 1, mode 2, 8-bit reload */if(GPS_SPD){TH1 = 0xfa; /* TH1: reload value for 4800 baud @ 11.059MHz */ }else{TH1 = 0xfd; /* TH1: reload value for 9600 baud @ 11.059MHz */ }TR1 = 1; /* TR1: timer 1 run */LCD_init(8); //初始化LCDLCD_write_string(0,0," GPS SIRF II 2 ");LCD_write_string(0,1," 11-11-23 1342 ");for(i=1;i<4;i++){delayms(250);}//LCD_cls();IE=0x90; //开总中断、串口中断}//串口接收中断void uart(void) interrupt 4{unsigned char tmp;if(RI){tmp=SBUF;// SBUF=tmp;// if(TI)TI=0;switch(tmp){case '$':cmd_number=0; //命令类型清空mode=1; //接收命令模式byte_count=0; //接收位数清空break;case ',':seg_count++; //逗号计数加1byte_count=0;break;case '*':switch(cmd_number){case 1:buf_full|=0x01;break;case 2:buf_full|=0x02;break;case 3:buf_full|=0x04;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;}}else if(cmd[3]=='S'){if(cmd[4]=='V'){cmd_number=2;mode=2;seg_count=0;byte_count=0;}}else if(cmd[2]=='R'){if(cmd[3]=='M'){if(cmd[4]=='C'){cmd_number=3;mode=2;seg_count=0;byte_count=0;}}}}}}}else if(mode==2){//接收数据处理switch (cmd_number){case 1: //类型1数据接收。