基于51单片机的GPS定位12864显示

一,材料准备

lcd12864带中文字库

neo-6m模块

stc89c52rc最小系统板

有源天线(方便搜索卫星) 

杜邦线若干

stc官方发布的单片机最小系统电路

建议在单片机最小系统板上完成项目

neo-6m

二,解析GPS信息:

选择接收$GPGGA等数据,从中解析数据

GPGGA的语句解析

更多资料参考网站GPS - NMEA sentence information 

三,代码实现

部分代码如下:

main.c

//main.c of gps program
//所有中文应使用utf-8编码格式
//chan led p^2.1
#include "main.h"
#include "LCD12864.h"
#include "GPS.h"

//定义变量
unsigned char KEY_NUM = 0;
bit Page = 0;
unsigned char xdata Display_GPGGA_Buffer[68];
unsigned char xdata Display_GPRMC_Buffer[68];
bit Flag_OV = 0;
bit Flag_Calc_GPGGA_OK = 0;
bit Flag_Calc_GPRMC_OK = 0;

//****************************************************
//主函数
//****************************************************
void main()
{
	unsigned char i = 0;
	LCD12864_Reset();								//初始化液晶
	LCD12864_HAIZI_SET();							//设置为普通模式
	
	Delay_ms(100);
	

	LCD12864_COM_Write(0x80);						//指针设置
	LCD12864_write_word("GPS定位系统");
	LCD12864_COM_Write(0x90);						//指针设置
	LCD12864_write_word("※※正在准备※※");			
	LCD12864_COM_Write(0x88);						//指针设置
	LCD12864_write_word("正在尝试连接卫星");
	LCD12864_COM_Write(0x98);						//指针设置
	LCD12864_write_word("suns1209");

	Uart_Init();

	while(1)
	{
		Scan_Key();
		if(Flag_GPS_OK == 1 && RX_Buffer[4] == 'G' && RX_Buffer[6] == ',' && RX_Buffer[13] == '.')			//确定是否收到"GPGGA"这一帧数据
		{
			for( i = 0; i < 68 ; i++)
			{
				Display_GPGGA_Buffer[i] = RX_Buffer[i];	
			}
			Hour = (Display_GPGGA_Buffer[7]-0x30)*10+(Display_GPGGA_Buffer[8]-0x30)+8;			//UTC时间转换到北京时间UTC+8    
																								//0X30为ASCII码转换为数字
				if( Hour >= 24)				//溢出
			{
				Hour %= 24;				//获取当前Hour
				Flag_OV = 1;			//日期进位
			}
			else
			{
				Flag_OV = 0;
			}

			Min_High = Display_GPGGA_Buffer[9];
			Min_Low = Display_GPGGA_Buffer[10];
	
			Sec_High = Display_GPGGA_Buffer[11];
			Sec_Low = Display_GPGGA_Buffer[12];

			Flag_Calc_GPGGA_OK = 1;
		}

		if(Page == 0 && Flag_Calc_GPGGA_OK == 1)
		{
//			LED1 = ~LED1;
			Flag_Calc_GPGGA_OK = 0;
		
			LCD12864_COM_Write(0x80);			//设置指针
			LCD12864_write_word("@");				//显示内容
			LCD12864_Data_Write(Hour/10+0x30);
			LCD12864_Data_Write(Hour%10+0x30);
			LCD12864_write_word("时");
	
			LCD12864_Data_Write(Min_High);
			LCD12864_Data_Write(Min_Low);
			LCD12864_write_word("分");
	
			LCD12864_Data_Write(Sec_High);
			LCD12864_Data_Write(Sec_Low);
			LCD12864_write_word("秒");
			LCD12864_write_word("@");
	
	
			LCD12864_COM_Write(0x90);			//设置指针
			
			LCD12864_Data_Write(Display_GPGGA_Buffer[28]);			//N 或者 S
			LCD12864_Data_Write(' ');

			LCD12864_Data_Write(Display_GPGGA_Buffer[17]);			//纬度
			LCD12864_Data_Write(Display_GPGGA_Buffer[18]);			//纬度
			LCD12864_Data_Write(Display_GPGGA_Buffer[19]);			//纬度
			LCD12864_Data_Write(Display_GPGGA_Buffer[20]);			//纬度
			LCD12864_Data_Write(Display_GPGGA_Buffer[21]);			//纬度
			LCD12864_Data_Write(Display_GPGGA_Buffer[22]);			//纬度
			LCD12864_Data_Write(Display_GPGGA_Buffer[23]);			//纬度
			LCD12864_Data_Write(Display_GPGGA_Buffer[24]);			//纬度
			LCD12864_Data_Write(Display_GPGGA_Buffer[25]);			//纬度
			LCD12864_Data_Write(Display_GPGGA_Buffer[26]);			//纬度
			LCD12864_write_word("    ");


			LCD12864_COM_Write(0x88);			//设置指针
			
			LCD12864_Data_Write(Display_GPGGA_Buffer[42]);			//E 或者 W
			LCD12864_Data_Write(' ');

			LCD12864_Data_Write(Display_GPGGA_Buffer[30]);			//经度
			LCD12864_Data_Write(Display_GPGGA_Buffer[31]);	
			LCD12864_Data_Write(Display_GPGGA_Buffer[32]);	
			LCD12864_Data_Write(Display_GPGGA_Buffer[33]);			//经度
			LCD12864_Data_Write(Display_GPGGA_Buffer[34]);	
			LCD12864_Data_Write(Display_GPGGA_Buffer[35]);
			LCD12864_Data_Write(Display_GPGGA_Buffer[36]);	
			LCD12864_Data_Write(Display_GPGGA_Buffer[37]);
			LCD12864_Data_Write(Display_GPGGA_Buffer[38]);	
			LCD12864_Data_Write(Display_GPGGA_Buffer[39]);
			LCD12864_Data_Write(Display_GPGGA_Buffer[40]);
			LCD12864_write_word("   ");	

			LCD12864_COM_Write(0x98);			//设置指针
                   LCD12864_write_word("rate: ");				//显示内容

			LCD12864_Data_Write(' ');
			LCD12864_Data_Write(Display_GPRMC_Buffer[46]);		
			LCD12864_Data_Write(Display_GPRMC_Buffer[47]);		
			LCD12864_Data_Write(Display_GPRMC_Buffer[48]);			
			LCD12864_Data_Write(Display_GPRMC_Buffer[49]);	
			LCD12864_Data_Write(Display_GPRMC_Buffer[50]);
			
			LCD12864_write_word("m/s");
			
		}
		
		if(Flag_GPS_OK == 1 && RX_Buffer[4] == 'M' && RX_Buffer[52] == ',' && RX_Buffer[59] == ',')			//确定是否收到"GPRMC"这一帧数据
		{
			for( i = 0; i < 68 ; i++)
			{
				Display_GPRMC_Buffer[i] = RX_Buffer[i];	
			}

			Year_High = Display_GPRMC_Buffer[57];
			Year_Low = Display_GPRMC_Buffer[58];

			Month_High = Display_GPRMC_Buffer[55];
			Month_Low = Display_GPRMC_Buffer[56];

			Day_High = Display_GPRMC_Buffer[53];
			Day_Low = Display_GPRMC_Buffer[54];


			if(Flag_OV == 1)			//有进位
			{
				UTCDate2LocalDate();			//UTC日期转换为北京时间		
			}

			Flag_Calc_GPRMC_OK = 1;
		}

		if(Page == 1 && Flag_Calc_GPRMC_OK == 1)
		{
//			LED1 = ~LED1;
			Flag_Calc_GPRMC_OK = 0;
			
			LCD12864_COM_Write(0x80);			//设置指针
			LCD12864_write_word("20");
			LCD12864_Data_Write(Year_High);
			LCD12864_Data_Write(Year_Low);
			LCD12864_write_word("年");
	
			LCD12864_Data_Write(Month_High);
			LCD12864_Data_Write(Month_Low);
			LCD12864_write_word("月");
	
			LCD12864_Data_Write(Day_High);
			LCD12864_Data_Write(Day_Low);
			LCD12864_write_word("日");
			
			
			LCD12864_COM_Write(0x90);			//设置指针.        
                   LCD12864_write_word("high:    ");				//显示内容
			
			LCD12864_Data_Write(Display_GPGGA_Buffer[54]);	
			LCD12864_Data_Write(Display_GPGGA_Buffer[55]);	
			LCD12864_Data_Write(Display_GPGGA_Buffer[56]);	
			LCD12864_Data_Write(Display_GPGGA_Buffer[57]);
			LCD12864_write_word("米");			
						
		}		
	}
}


void UTCDate2LocalDate(void)
{
	Day = (Day_High - 0x30) * 10 + (Day_Low-0x30) + 1;		//日  加一
	Month = (Month_High - 0x30) * 10 + (Month_Low - 0x30);
	Year = 2000 + (Year_High - 0x30) * 10 + (Year_Low - 0x30);
	
	MaxDay = GetMaxDay(Month,Year);				//获取当月 天数 最大值
	if(Day > MaxDay)		//溢出
	{
		Day = 1;
		Month += 1;
		if(Month > 12)
		{
			Year+=1;
		}
	}

	Day_High = Day/10 + 0x30;				//转换日期值为ASCII
	Day_Low = Day%10 + 0x30;

	Month_High = Month/10 + 0x30;			//转换月份值为ASCII
	Month_Low = Month%10 + 0x30;

	Year_High = Year%100/10 + 0x30;			//转换年份值为ASCII
	Year_Low = Year%10 + 0x30;			
}

//****************************************************
//获取当月日期最大值
//****************************************************
unsigned char GetMaxDay(unsigned char Month_Value,unsigned int Year_Value)
{
	unsigned char iDays;
	switch(Month_Value)
	{
		case 1:
		case 3:
		case 5:
		case 7:
		case 8:
		case 10:
		case 12:
			{
				iDays = 31;
			}
			break;
		case 2:
			{
				//2月份比较特殊,需要根据是不是闰年来判断当月是28天还29天
				iDays = IsLeapYear(Year_Value)?29:28;
			}
			break;
		case 4:
		case 6:
		case 9:
		case 11:
			{
				iDays = 30;
			}
			break;
		default : break;
	}
	return(iDays);						
}


bit IsLeapYear(unsigned int uiYear)
{
	return (((uiYear%4)==0)&&((uiYear%100)!=0))||((uiYear%400)==0);
}



void Scan_Key()
{
	if( KEY4 == 0 )	 					//按键1扫描
	{
		Delay_ms(10);					//延时去抖
		if( KEY4 == 0 )
		{
			while(KEY4 == 0);			//等待松手
			KEY_NUM = 4;
			Page = ~Page;
			LCD12864_COM_Write(0X01);	//清屏
		}
	}
}

void Delay_ms(unsigned int n)
{
	unsigned int  i,j;
	for(i=0;i<n;i++)
		for(j=0;j<123;j++);
}

2,lcd12864.h

//lcd12864.h
#ifndef __LCD12864_H__
#define __LCD12864_H__

#include <reg52.h>
#include <intrins.h>

//引脚定义,可以根据自己开发板更改
sbit LCD12864_RS_PORT  = P1^2;  
sbit LCD12864_RW_PORT = P1^1;
sbit LCD12864_E_PORT    = P1^0;
#define LCD12864_DA_PORT P0


//函数或者变量声明
extern void LCD12864_WaitIdle();
extern void LCD12864_COM_Write( unsigned char com_da);
extern void LCD12864_NoWaitIdle_COM_Write(unsigned char com_da);
extern void LCD12864_Data_Write(unsigned char da);
extern void lcd_delay_ms(unsigned char x);
extern void LCD12864_Reset();
extern void LCD12864_write_word(unsigned char *s);
//extern void LCD12864_PHOTO_SET();
extern void LCD12864_HAIZI_SET();
//extern void LCD12864_HAIZI_WRITE(unsigned char xpos,unsigned char ypos,unsigned char daH,unsigned char daL);
//extern void LCD12864_PHOTO_WRITE(unsigned char *img);


#endif

rw、rs、e口引脚定义可以根据自己需要更改

本人使用的单片机开发板

四,注意事项

1,代码中所有中文使用utf-8编码,否则编译后显示乱码

2,编译前对keil软件安装0xfd补丁(资料包里有),否则编译后显示乱码

3,lcd12864采用并口接线

4,lcd12864的对比度出厂已经设置,本项目不使用vo口

5,应该在室外开阔条件下搜索卫星信号

五,运行实例

六,资源链接 

https://sunm.lanzouj.com/iETyO1v1ploj
密码:sunm

本文章部分素材来源于网络,如有侵权请联系删除!

  • 10
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值