0 卖盘信息
BOM询价
您现在的位置: 首页 > 电子资讯 >设计应用 > 基于51单片机的定位系统设计

基于51单片机的定位系统设计

来源:
2024-01-05
类别:设计应用
eye 30
文章创建人 拍明芯城

1、基于51单片机GPS定位系统设计

基于51单片机GPS定位系统设计

GPS(Global Positioning System,全球定位系统),是一个由24颗卫星组成的卫星系统。可以保证在任意时刻,任何地点都同时检测到4颗卫星,以保证卫星可以采集到该观测点的经纬度和高度,从而实现导航、定位、授时等功能。现在在很多领域都有用到GPS技术,比如可以用来引导汽车、飞机、船舶以及个人准确的到达目的地,本文就是以保证个人的安全、准确出行研究的GPS定位系统,设计制作一个单片机系统,单片机系统由电源电路、晶振电路、复位电路、LCD驱动电路等组成,此系统用以读取GPS模块的数据并处理,最后显示在LCD12864上面,用户可以实时通过读取12864显示的内容了解自己的位置以及当前时间,同时由于用到有单片机,以后还可以在上面加很多想要的功能,是一个可扩展、很具有使用价值的系统。

1、 系统方案选择和论证

1.1、引言

GPS 是英文Global Positioning System(全球定位系统)的简称,而其中文简称为“球位系”。GPS起始于1958年美国军方的一个项目,1964年投入使用。是20世纪70年代由美国陆海空三军联合研制的新一代空间卫星导航定位系统 。其主要目的是为陆、海、空三大领域提供实时、 全天候和全球性的导航服务,并用于情报收集、核爆监测和应急通讯等一些军事目的。经过20余年的研究实验,耗资300亿美元,到1994年,全球覆盖率高达98%的24颗GPS卫星星座己布设完成。随着人民生活水平的发展,GPS技术被越来越多的应用在个人PDA、个人车载终端、手机等设备上。人们通过GPS,能准确知道自己所在的位置,从实现到导航、确定旅游路线、获取地理信息等功能。本文介绍的GPS导航系统,以单片机作为主控芯片,配以GPS、12864显示屏,构建了一个GPS信息显示的系统。本系统在一定程度上推动了GPS导航设备研究的发展。

1704426677185063259.png

1.2 方案说明

1.2.1、 总体设计方案

个人手持设备要求是功耗要足够低、操作简单、界面美观、方便观看。

为完成相应功能,本设计提出的方案如图1.1所示。系统包括以下几个基本模块:电源模块、主控模块、显示模块、GPS定位模块。GPS模块负责接收卫星信息,单片机模块负责读取GPS模块数据并处理,显示模块主要负责将GPS模块接收到的数据显示出来供用户随时观看。

1.2.2、 系统功能说明

(1).定位功能

GPS通过接收卫星信号,可以准确地定出其所在的位置,位置误差小于10米。利用GPS,在12864上面显示当前位置。

(2).查询时间功能

GPS还可以接收卫星发下来的时间信息,利用单片机控制12864显示出当前时间,用户可以很方便的了解时间。

1.3、 部分模块设计方案

1.3.1、 控制模块设计方案

单片机最小系统由晶振电路、复位电路、电源电路等组成

1.3.2、 显示电路设计方案

本项目选用LCD12864作为显示屏,电路简单,选用并行通信方式

1.3.3、 GPS模块选择方案

方案一:采用串口接口GPS模块。优点:便于驱动,程序简单,价格便宜。缺点:体积较大。

方案二:采用usb接口GPS模块。优点:便于携带。缺点:驱动相对较难、价格相对较贵。

1.4、总体方案确定

1.4.1、系统硬件方案

1704426703456004964.png

表1.1系统硬件方案

1704426734229079748.png

2、 系统的硬件设计与实现

系统硬件特性如下图:

该系统是用手工做的腐蚀板,成本很低,性能稳定,同时用LCD12864作为显示屏显示位置及时间等信息,显示的容量大数据量小,一个页面可以显示8*4个汉字或16*4个字符。

2.1、 主控芯片电路

主控芯片为AT89S52,该芯片性能稳定、工艺精良。

图2.1为主控芯片电路,AT89S52是一种低功耗、高性能CMOS 8位微控制器,具有8K 在系统可编程Flash 存储器。使用Atmel 公司高密度非易失性存储器技术制造,与工业80C51 产品指令和引脚完全兼容。片上Flash允许程序存储器在系统可编程,亦适于常规编程器。在单芯片上,拥有灵巧的8 位CPU 和在系统可编程Flash,使得AT89S52在众多嵌入式控制应用系统中得到广泛应用,这里采用AT89S52单片机作为控制芯片,实现了成本低,开发简单等特点。

1.png

2.2、 复位电路

图2.2为系统复位电路,为确保系统中电路稳定可靠工作,复位电路是必不可少的一部分,复位电路的第一功能是上电复位。一般单片机电路正常工作需要供电电源为5V±5%,即4.75~5.25V。由于单片机电路是时序数字电路,它需要稳定的时钟信号,因此在电源上电时,只有当VCC超过4.75V低于5.25V以及晶体振荡器稳定工作时,复位信号才被撤除,单片机电路开始正常工作。这种复位电路的工作原理是:VCC上电时,C1充电,在10K电阻上出现电压,使得单片机复位;几个毫秒后,C1充满,10K电阻上电流降为0,电压也为0,使得单片机进入工作状态。工作期间,按下S1,C1放电。S1松手,C1又充电,在10K电阻上出现电压,使得单片机复位。几个毫秒后,单片机进入工作状态

2.3、 晶振电路

图2.3为震荡电路,每个单片机系统里都有晶振,全称叫晶体震荡器,在单片机系统里晶振的作用非常大,它结合单片机内部的电路,产生单片机所必须的时钟频率,单片机的一切指令的执行都是建立在这个基础上的,晶振的提供的时钟频率越高,那单片机的运行速度也就越快,如图,在晶振两边添加两个30pF(27--33pF)电容,使震荡更加稳定。震荡电路接在AT89S52单片机的18、19两个引脚上,给单片机提供震荡信号

2.4、 电源电路

图2.3为电源电路,用的是六脚开关控制电源通断,同时控制了电源的正负极,安全方便,同时有一个电源指示灯,上面加有一个1K的限流电阻。该电路实现了对系统的电源控制,同时显示了电路的状态,方便大家操作。

2.5、 显示电路

图2.4为12864显示电路,该12864的数据口用的AT89S52的P0口,由于P0口内部没有加上拉电阻,需外接10K的上拉电阻,才能保证数据的正常传输。12864的3脚为背光调节的引脚,当3脚的电压不同时背光的亮度就不同,这里设计了一个电路来调节3脚的电压,就是利用一个滑动变阻器一个脚接电源电压,一个脚接地,调节滑动变阻器就可以改变中间那个引脚的电压,我们只需将中间那个引脚和12864的3脚相连接就行了。

2.7 电路图的打印

由于采用的是曝光显影法制作电路板,故打印电路图前,要先对电路图进行打印设置。

由于我们是制作单面板,多余的线路可用跳线连接。打印前,先进行页面设置,具体设置参数如图2.6.1所示,在Mechanical层放置填充方块,覆盖整个电路图。然后进行打印设置:

点击文件,打印设置,然后点击高级选项,在高级选项中选择将要打印的层,本系统中需打印的层如图2.6.2所示:

然后点击左下角的特性设置各层的打印颜色。Bottom Layer 设置为白色,Mechanical层设置为黑色,Multi-Layer设置成白色。设置好后,将打印比例设置为1.0即可进行打印,打印时要注意用硫酸纸或菲林纸,我们是将线布在底层,打印可以选择镜像打印,就是将图2.6.2中Mirror这个选项勾上,到时候正面曝光,也可以将就按照图2.6.2设置,曝光时就背面曝光。

3、 系统的软件设计

3.1、系统概述

本系统的所有程序均采用C语言编写,开发工具为keil,开发环境为windows。应用软件开发的模块化思想来开发这个项目,程序定义了许多子程序来分别管理各个模块,通过对各个子程序的操作,来构建整个程序框架。各个子程序即可单独提取出作为独立的一个有机代码,大大增加了项目的健壮性及可移植性。

3.2、软件详细设

3.2.1 头文件

本系统写了很多头文件,里面包含了很多子模块的信息,各个子模块相互分开,加大了项目的可移植性,如在其它的项目中要使用这些子模块,只需要将C文件和H文件复制过去就行了。包含的头文件如下:

#include

#include

#include

#include "GPS.h"

#include "LCD.h"

#include "display.h"

3.2.2、系统IO定义

整个系统用到了很多独立的IO,在控制12864的读写中要定义几个IO,在控制GPS模块的数据传输中都要用到单片机IO,具体定义IO情况如下:

3.2.3、主函数

主函数,项目入口,用于启动其他模块,并在屏幕上显示主界面窗口,主函数具体如下:

/****************************************

主函数

/****************************************/

void main(void)

{

uchar error_num = 0;

Uart_Init(); //初始化串口

Lcd_Init(); //初始化LCD

GPS_Init(); //初始化GPS

rev_stop=0;

REV_NO;

while(1)

{

if (rev_stop) //如果接收完一行

{

TR0 = 1; //开启定时器

REV_YES;

if (change_page % 2 == 1) //换页

{

if (GPS_GGA_Parse(rev_buf, &GPS)) //解析GPGGA

{

GGA_YES;

GPS_DisplayTwo(); //显示第二页信息

error_num = 0;

gps_flag = 0;

rev_stop = 0;

REV_NO;

}

else

{

error_num++;

if (error_num >= 20) //如果数据无效超过20次

{

GGA_NO;

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;

led1 = 1;

}

else

{

error_num++;

if (error_num >= 20) //如果数据无效超过20次

{

RMC_NO;

error_num = 20;

GPS_Init(); //返回初始化

}

gps_flag = 0;

rev_stop = 0;

REV_NO;

}

}

}

}

}

由于GPS与单片机通信是选用的串口,在程序中首先初始化了串口,在初始化了LCD12864,然后初始化GPS,做好了准备工作后,就一直等待从GPS接收数据。

3.2.4、延时子函数

在整个系统中都要用到延时函数,这个时间的取定决定这整个系统的工作效率,如果延时时间短了就会造成LCD12864显示不正常,还有就是GPS数据传输不成功;但是延时时间过长又会导致系统的效率低下,所以一个准确的延时函数是很重要的,具体的延时函数如下:

void delay(uint z)

{

uint x, y;

for (x = z; x > 0; x--)

for(y = 110; y > 0; y--);

}

void timer0(void) interrupt 1

{

static uchar count = 0;

TH0 = 0x3c;

TL0 = 0xb0;

count++;

if (count == 200) //2*5秒钟

{

count = 0;

change_page++; //换页

if (change_page == 10)

change_page = 0;

}

}

上面是一个延时1ms(晶振为11.0592M)的函数下面是一个中断函数,用于12864显示用的。

3.2.5、12864子模块

12864的显示函数,先要写地址,然后在写数据,在这个过程前还要检测12864是否忙,就是是否在接收上次的数据,具体的函数如下:

#ifndef __LCD_H_

#define __LCD_H_

#include

#include

#define uchar unsigned char

#define uint unsigned int

#define LCD_data P2 //数据口

sbit LCD_RS = P0^7; //寄存器选择输入

sbit LCD_RW = P0^6; //液晶读/写控制

sbit LCD_EN = P0^5; //液晶使能控制

sbit LCD_PSB = P0^4; //串/并方式控制

#define DelayNOP(); {_nop_();_nop_();_nop_();_nop_();};

void clr_screen();

void delay(uint z);

void Lcd_WriteCmd(uchar cmd);

void Lcd_WriteDat(uchar dat);

void Lcd_Init(void);

void Lcd_SetPos(uchar X,uchar Y);

void Lcd_DispLine(uchar line, uchar pos, uchar *str);

#endif //__LCD_H_

#include "LCD.h"

void delay(uint z)

{

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);

}

static bit Lcd_Busy(void)

{

bit result;

LCD_RS = 0;

LCD_RW = 1;

LCD_EN = 1;

DelayNOP();

result = (bit)(P0&0x80);

LCD_EN = 0;

return(result);

}

void Lcd_WriteCmd(uchar cmd)

{

LCD_RS = 0;

LCD_RW = 0;

LCD_EN = 0;

_nop_();

_nop_();

LCD_data = cmd;

DelayNOP();

LCD_EN = 1;

DelayNOP();

LCD_EN = 0;

}

void Lcd_WriteDat(uchar dat)

{

LCD_RS = 1;

LCD_RW = 0;

LCD_EN = 0;

LCD_data = dat;

DelayNOP();

LCD_EN = 1;

DelayNOP();

LCD_EN = 0;

}

void Lcd_Init(void)

{

LCD_PSB = 1; //并口方式

Lcd_WriteCmd(0x34); //扩充指令操作

delay(5);

Lcd_WriteCmd(0x30); //基本指令操作

delay(5);

Lcd_WriteCmd(0x0C); //显示开,关光标

delay(5);

Lcd_WriteCmd(0x01); //清除LCD的显示内容

delay(5);

}

void Lcd_SetPos(uchar X,uchar Y)

{

uchar pos;

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, uchar pos, uchar *str)

{

int i = 0;

Lcd_SetPos(line, pos);

while (str[i] != '')

{

Lcd_WriteDat(str[i]);

i++;

}

}

12864每一行的地址为,第一行是0x80,第二行是0x90,第三行是0x88,第四行是0x98。

12864每一行的地址为,第一行是0x80,第二行是0x90,第三行是0x88,第四行是0x98。

3.2.6、GPS子模块

这些函数用来读取GPS接收器传来的数据,并进行分析处理。

void GPS_Init(void)

{

Lcd_DispLine(0, 0, init1);

Lcd_DispLine(1, 0, init2);

Lcd_DispLine(2, 0, init3);

Lcd_DispLine(3, 0, init4);

}

int GPS_RMC_Parse(char *line,GPS_INFO *GPS)

{

uchar ch, 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)];

if (ch == 'C') //如果第五个字符是C,($GPRMC)

{

if (status == '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;

}

int GPS_GGA_Parse(char *line,GPS_INFO *GPS)

{

uchar ch, 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;

int i;

while(*str != '')

{

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];

uchar i;

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;

int i;

while(*str != '')

{

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];

uchar i;

double rev;

i=GetComma(1, s);

i = i - 1;

strncpy(buf, s, i);

buf[i] = 0;

rev=Str_To_Double(buf);

return rev;

}

static uchar GetComma(uchar num,char *str)

{

uchar i,j = 0;

int len=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(int x,char *Str)

{

int t;

char *Ptr,Buf[5];

int i = 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 = '';

4、 系统测试

在做完上述的步骤后,我们可以进行系统测试。

刚开始时都一直搜索不到卫星,后面到处查找资料,终于找到问题所在,原来在室内基本上是搜不到卫星的,后面在室外进行测试,系统可以工作了,能够准确的定位。

具体如图:

(这里你自己照几张12864显示图片就可以了)

5、 总结

通过这次的毕业设计,我在更加灵活、牢固地掌握了所学的相关专业知识的同时。也大量学习了单片机方面的相关知识。至此,GPS定位系统经过最初设计、实现及应用检验,已经具备基本的功能,可初步满足个人移动导航信息系统的需求。当然由于时间和能力的有限,这款产品也有其一定的不足,值得进一步的深入研究,例如:在打开GPS接收模块之后,系统的响应速度将有显著的下降,还有就是显示的是数字,还没有转化为地图。问题可能在硬件平台的处理速度和可调用的资源有限,也有可能在软件接收上的程序结构不合理。GPS接收信号有时会发生信号接收的不稳定,出现信号的偏移,超过标称的误差值。问题可能在开发平台的设计电路中对于数据信号线的排版上,没有使信号线等距,也没有设置合理的信号隔离和保护带,导致最终出现了不应有的误差。但从软件上着手,如何纠正这样的误差也是值得研究的一个方向。在本课题中只实现了从任意点至任意点的导航,导航功能可以从软件方面继续深入的研究,包括以后开发对地图格式的选择等。这些都是将来值得完善之处。

参考文献:

杨颂华 数字电子技术基础.西安电子科技大学出版社 2009.12

曹国华 单片机原理及接口技术 西安电子科技大学出版社 2007.12

肖洪兵 跟我学用单片机. 北京:北京航空航天大学出版社,2002.8

何立民 单片机高级教程. 第1版.北京:北京航空航天大学出版社,2001

赵晓安 MCS-51单片机原理及应用. 天津:天津大学出版社,2001.3

李广第 单片机基础. 第1版.北京:北京航空航天大学出版社,1999

2、基于单片机的GPS定位系统

1、设计需求及目标

系统由电源电路、晶振电路、复位电路、LCD驱动电路等组成,此系统用以读取GPS模块的数据并处理,最后在LCD液晶显示屏上显示经纬度和时间,用户可以实时通过读取显示的内容了解自己的位置以及当前时间,并可以实现时间自动校准,定位精度为15m。

2、设计思路及方案

系统硬件部分电路大致上可以分成稳压电源、单片机小系统及外围电路和LCD显示屏电路三部分。电路为单片机89C52控制的GPS器件,实现定位系统数据的采集和现实。其中所使用的器件主要是3个,单片机89C52、GPS模块GARMIN GPS25以及LCD显示模块MGLS-12032A。在这里仅列出单片机和LCD接口部分电路的器件名称和相关的主要功能。以单片机为核心将GPS数据发送模块,LCD1602显示模块系统的结合在一起形成一个整体,实现特定功能。


image.png

3、基于51单片机的GPS全球定位系统

本文是在PXA270嵌入式开发板和GPS模块上开发实现的。在Linux下的嵌入式开发环境中,利用C++设计完成定位。嵌入式系统利用软件设计主要完成GPS定位信号的处理、电子地图的移植、地球坐标的转换、定位的显示等功能。

1 系统概述

嵌入式系统是控制、监视或者辅助装置、机器和设备运行装置;是软件和硬件的综合体,可涵盖机械等附属装置;有着友好的人机界面,支持LCD及GPS模块;主要完成提取GPS定位信号的数据、坐标转换、电子地图的显示等功能。软件设计流程如图1所示。



2 嵌入式系统软件设计

2.1 GPS模块输出的信息的提取

GPS模块通电后,会自动搜索卫星信号,并把计算数据从串口输出。所有GPS接收机以通用的NMEA格式输出数据。NMEA-0183协议定义的语句较多,但常用且兼容性较广的语句只有:$GPGGA、$GPGSA、$GPGSV、$GPRMC、$GPVTG、$GPGLL等。如图2所示。



用串口连接宿主机与开发板的串口0。宿主机进入Linux,打开Minicom终端。设置波特率115 200,8位数据,1位停止,无校验,无流控。串口的设备文件为/dev/ttyS*,其中,ttyS0为串口1,ttyS1为串口2,以此类推。在对串口通信之前,首先要对串口参数进行初始化、设置它的属性以保证通信双方的通信参数保持一致。初始化完串口,就可以进行读取操作了。由于GPS发送的数据类型都是以&GPGGA符

号开头,所以检测&GPGGA符号,进而进行下一步的处理。关键代码如下:



2.2 坐标转换

GPS模块输出的地理坐标是WGS-84坐标系。而国内地图一般是以54北京坐标系作高斯-克吕格平面投影。所以必须作一个坐标转换,即将GPS坐标(WGS-84坐标系)转换到电子地图坐标(54北京坐标系)。坐标转换的具体步骤如下:

(1)空间直角坐标转换成国家大地坐标,国家大地坐标转换成地图平面坐标。



(2)由于x,y的具体推算过程复杂,这里就不全部列举,其结果如下



(3)地图平面坐标转换成屏幕坐标。例地图比例尺为1:k,窗口要显示的区域长、宽各为M和N,窗口像素点位A×B点,则定位数据xs,ys在窗口上坐标分别为



2.3 电子地图重构

一般来说,电子地图包含的数据格式都不能直接用在嵌入式平台,所以需要对电子地图的数据进行提取、存储、重构。目前主要使用的是桌面电子地图系统MapInfo,它是美国MapInfo公司的桌面地理信息系统软件,具有数据可视化、信息地图化的桌面解决方案。MapInfo数据格式主要分为tab和mif两种格式。MIF格式是MapInfo公司提供的一种与外界交换数据的机制。它主要用于保存空间对象的几何数据。将电子地图的数据读出后,再在嵌入式平台下,用绘图工具重新组成电子地图即可。部分实现代码如下





03 仿真测试

点测试、线测试、面测试如图3所示。



4 结束语

整个测距定位系统在PXA270嵌入式开发系统下完成,工程系统庞大,整个系统基本功能已实现。由于本系统软硬件平台有较强的升级能力,许多指标与功能可以进一步完善与提高。从GPS定位数据到电子地图数据的转换,需要一系列复杂的算法,这些算法有待进一步改进和简化,以提高系统运行效率和数据准确性。


4、基于单片机的GPS定位系统的设计,在哪可以找到原理图和程序

关键是下面的结构体:

typedef struct _nmeaINFO

{

     double  lat;     //纬度

   double  lon;    //经度    /**< Longitude in NDEG - +/-[degree][min].[sec/60] */

    double  elv;        /**高度< Antenna altitude above/below mean sea level (geoid) in meters */

    double  speed;      /*移动速度*< Speed over the ground in kilometers/hour */

    double  direction;  /**移动方向< Track angle in degrees True */

........

} nmeaINFO;

5、基于单片机的毕业设计题目哪些简单点

基于单片机的毕业设计简单点的题目如下:

一、智能家居控制系统

在单片机、传感器、通讯技术和家电控制等方面进行设计,实现智能家居的自动化管理,如温度控制、照明控制、窗帘控制等功能,实现智能家居系统的智能化、舒适化。

二、智能绿植养护系统

基于单片机、传感器、液晶屏和控制器等硬件设计,将温度、湿度光照等环境参数进行检测和记录,并通过控制器实现水肥自动喂养.光照调控、温湿度自动调节等功能,保证绿植的正常生长。

三、电子词典设计

该项目主要是基于单片机和学习型记忆卡等硬件设备,以及各种词库和语音合成技术,构建一个功能完备、使用简单、体积小巧的电子词典系统,使用户可以快速查阅和记忆单词、词组、成语等语言内容。

四、智能交通信号灯控制系统

结合单片机、通讯技术、图像处理等技术,实现智能交通信号灯控制,减缓城市交通拥堵,提高道路交通效率,保障行车安全。该项目设计难度较高,需要涉及到通讯信号的处理、图像的处理及其特征提取等关键技术的研究。

五、智能医疗诊断系统

基于单片机、传感器、采样电路、信号处理算法、人工智能等硬件及软件技术,构建一个智能医疗诊断系统,能够检测患者的生理指标,并根据患者的身体状况和历史病例,提供医学诊断结果和治疗建议。

六、智能家庭安防系统

该系统可以通过单片机、配合传感器、通讯模块等硬件,实现对家庭室内和室外环境的实时监测,防盗报警、行程化控制、视频监控等多个功能,提高家庭的安全系数。

责任编辑:David

【免责声明】

1、本文内容、数据、图表等来源于网络引用或其他公开资料,版权归属原作者、原发表出处。若版权所有方对本文的引用持有异议,请联系拍明芯城(marketing@iczoom.com),本方将及时处理。

2、本文的引用仅供读者交流学习使用,不涉及商业目的。

3、本文内容仅代表作者观点,拍明芯城不对内容的准确性、可靠性或完整性提供明示或暗示的保证。读者阅读本文后做出的决定或行为,是基于自主意愿和独立判断做出的,请读者明确相关结果。

4、如需转载本方拥有版权的文章,请联系拍明芯城(marketing@iczoom.com)注明“转载原因”。未经允许私自转载拍明芯城将保留追究其法律责任的权利。

拍明芯城拥有对此声明的最终解释权。

相关资讯