GPS模块与ATmega16接口查找位置坐标的方式

描述

  GPS 模块广泛用于电子应用中,以根据经度和纬度坐标跟踪位置。车辆跟踪系统、 GPS 时钟、 事故检测警报系统、交通导航、监控系统等是 GPS 功能必不可少的几个例子。GPS 提供海拔、纬度、经度、UTC 时间和有关特定位置的许多其他信息,这些信息来自多颗卫星。要从 GPS 读取数据,需要一个微控制器,因此我们将GPS 模块与 AVR 微控制器Atmega16 连接,并在16x2 LCD 显示屏上打印经度和纬度。

  所需组件

  Atmega16/32

  GPS 模块(uBlox Neo 6M GPS)

  长线天线

  16x2 液晶

  2.2k电阻

  1000uf电容

  10uF电容

  连接线

  LM7805

  直流插孔

  12v 直流适配器

  小贴士

  PCB或通用PCB

  Ublox Neo 6M 是一个串行 GPS 模块,通过串行通信提供位置详细信息。它有四个引脚。

GPS模块

GPS模块

  Ublox neo 6M GPS 模块与 TTL 兼容,其规格如下。

GPS模块

  从 GPS 获取位置数据

  GPS 模块将以 9600 波特率在多个字符串中传输数据。如果我们使用波特率为 9600 的 UART 终端,我们可以看到 GPS 接收到的数据。

 这是以 9600 波特率连接时 GPS 接收到的数据。

 

$GPRMC,141848.00,A,2237.63306,N,08820.86316,E,0.553,,100418,,,A*73 
$GPVTG,,T,,M,0.553,N,1.024,K,A*27 
$GPGGA,141848.00, 2237.63306,N,08820.86316,E,1,03,2.56,1.9,M,-54.2, M,,*74 
$GPGSA,A,2,06,02,05,,,,,,,,,,2.75, 2.56,1.00*02 
$GPGSV,1,1,04,02,59,316,30,05,43,188,25,06,44,022,23,25,03,324,*76 
$GPGLL,2237.63306,N,08820.86316,E,141848.00 ,A,A*65

 

当我们使用 GPS 模块 跟踪任何位置时,我们只需要坐标,我们可以在 $GPGGA 字符串中找到它。只有 $GPGGA(全球定位系统固定数据)字符串主要用于程序中,其他字符串被忽略。 

 

$GPGGA,141848.00,2237.63306,N,08820.86316,E,1,03,2.56,1.9,M,-54.2,M,,*74

 

  所以我们需要 5 号和 6 号来收集有关模块位置或它所在位置的信息。在这个项目中,我们使用了一个 GPS 库,它提供了一些函数来提取纬度和经度,所以我们不必担心这一点。

  电路原理图

  GPS与AVR Atemga16微控制器接口的电路图如下:

GPS模块

  整个系统由 12v 直流适配器供电,但电路工作在 5v 上,因此电源由 LM7805 稳压器调节至 5v。16x2 LCD 配置为 4 位模式 ,其引脚连接如电路图所示。GPS 也由 5v 供电,其 tx 引脚直接连接到Atmega16 微控制器的 Rx 。一个 8MHz 晶体振荡器用于为微控制器提供时钟。

GPS模块

  将 GPS 与 AVR 微控制器连接的步骤

  设置微控制器的配置,包括振荡器配置。

  设置 LCD 的所需端口,包括 DDR 寄存器。

  使用 USART 将 GPS 模块连接到微控制器。

  在 ISR 模式下初始化系统 UART,波特率为 9600,LCD 为 4 位模式。

  根据纬度和经度的长度取两个字符数组。

  每次接收一个字符位,并检查它是否从 $ 开始。

  如果接收到$,那么它是一个字符串,我们需要检查$GPGGA,这6个字母包括$。

  如果是 GPGGA,则接收完整的字符串并设置标志。

  然后用两个数组中的方向提取纬度和经度。

  最后在 LCD 中打印经纬度数组。

GPS模块

代码说明

最后给出了完整的代码和演示视频,这里解释了代码的一些重要部分。

首先在代码中包含一些必需的标头,然后为 LCD 和 UART 配置编写位掩码的 MACROS。

 

#define F_CPU 8000000ul 
#include  
#include  
#include 

/***MACROS*/ 
#define USART_BAUDRATE 9600 
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)

#define LCDPORTDIR DDRB 
#define LCDPORT PORTB 
#define rs 0 
#define rw 1 
#define en 2

#define RSLow (LCDPORT&=~(1<

 

现在声明并初始化一些变量和数组,用于存储 GPS 字符串、纬度经度和标志。

 

字符缓冲区[100];
volatile char ind、flag、stringReceived;
char gpgga[]={'$','G','P','G','G','A'};

字符纬度[12];
字符对数[12];

 

之后我们有一些 LCD Driver 函数来驱动 LCD。

 

无效 lcdwrite(char ch,char r) 
{ 
     LCDPORT=ch & 0xF0; 
     RW 低;
     如果(r == 1)
     RSHigh;
     否则
     RS低;
     EN高;
     _delay_ms(1); 
     低; 
     _delay_ms(1); 
     LCDPORT=ch<<4 & 0xF0; 
     RW 低;
     如果(r == 1)
     RSHigh;
     否则
     RS低;
     EN高;
     _delay_ms(1); 
     低; 
     _delay_ms(1); 
}

void lcdprint(char *str) 
{ 
     while(*str) 
     { 
          lcdwrite(*str++,DATA); 
          //__delay_ms(20); 
     } 
}

无效 lcdbegin() 
{ 
     char lcdcmd[5]={0x02,0x28,0x0E,0x06,0x01}; 
     for(int i=0;i<5;i++) 
     lcdwrite(lcdcmd[i], CMD); 
}

 

之后,我们初始化了 与 GPS的串行通信,并将接收到的字符串与 "GPGGA" 进行比较: 

 

void serialbegin() 
{ 
     UCSRC = (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); 
     UBRRH = (BAUD_PRESCALE >> 8); 
     UBRRL = BAUD_PRESCALE;
     UCSRB=(1<=50) 
           stringReceived=1; 
}

void serialwrite(char ch) 
{ 
     while ((UCSRA & (1 << UDRE)) == 0); 
     UDR = 通道;
}

 

现在如果接收到的字符串与 GPGGA 匹配成功,则在main函数中提取并显示该位置的经纬度坐标:

 

液晶写入(0x80,0);
                lcdprint("纬度:"); 
                serialprint("纬度:"); 
                for(int i=15;i<27;i++) 
                {
                     纬度[i]=buf[i]; 
                     lcdwrite(纬度[i],1); 
                     串行写入(纬度 [i]);
                     if(i==24) 
                     { 
                          lcdwrite(' ',1); 
                          我++;
                     } 
                } 
                serialprintln(""); 
                液晶写入(192,0);
                lcdprint("日志:"); 
                serialprint("Logitude:");
                for(int i=29;i<41;i++) 
                { 
                     logitude[i]=buf[i]; 
                     lcdwrite(logitude[i],1); 
                     串行写入(logitude [i]);
                     if(i==38) 
                     { 
                           lcdwrite(' ',1); 
                           我++;
                     } 
                }

 

  这就是GPS 模块如何与 ATmega16 接口以查找位置坐标的方式。

/*

* GPS_interfacing.c

*

* 创建时间:2019 年 8 月 26 日晚上 10:17:24

* 作者:埃文

*/





#define F_CPU 8000000ul

#include

#include

#include



/***宏*/



#define USART_BAUDRATE 9600

#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)



#define LCDPORTDIR DDRB

#define LCDPORT PORTB

#定义rs 0

#define rw 1

#define en 2



#define RSLow (LCDPORT&=~(1<
#define RSHigh (LCDPORT|=(1<
#define RWLow (LCDPORT&=~(1<
#define ENLow (LCDPORT&=~(1<
#define ENHigh (LCDPORT|=(1<




枚举

{

CMD=0,

数据,

};



字符缓冲区GPS模块

volatile char ind、flag、stringReceived;

char gpgga[]={'$','G','P','G','G','A'};



字符纬度[12];

字符对数[12];



无效串行写入(字符 ch);



无效 lcdwrite(char ch,char r)

{

LCDPORT=ch & 0xF0;

RW 低;

如果(r == 1)

RS高;

别的

RS低;

EN高;

_delay_ms(1);

低;

_delay_ms(1);



LCDPORT=ch<<4 & 0xF0;

RW 低;

如果(r == 1)

RS高;

别的

RS低;

EN高;

_delay_ms(1);

低;

_delay_ms(1);

}



无效液晶打印(字符 *str)

{

而(*str)

{

lcdwrite(*str++,DATA);

//__delay_ms(20);

}

}



无效液晶开始()

{

字符 lcdcmd[5]={0x02,0x28,0x0E,0x06,0x01};

for(int i=0;i<5;i++)

lcdwrite(lcdcmd[i], CMD);

}



无效序列开始()

{

UCSRC = (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1);

UBRRH = (BAUD_PRESCALE >> 8);

UBRRL = BAUD_PRESCALE;

UCSRB=(1<
}



ISR(USART_RXC_vect)

{

字符 ch=UDR;

buf[ind]=ch;

IND++;

如果(指数<7)

{

if(buf[ind-1] != gpgga[ind-1]) // $GPGGA

指数=0;

}

如果(指数>=50)

字符串接收=1;

}



无效串行写入(字符 ch)

{

而 ((UCSRA & (1 << UDRE)) == 0);

UDR = 通道;

}



无效序列打印(字符 *str)

{

而(*str)

{

串行写入(*str++);

}

}



无效串行打印(字符 *str)

{

序列打印(str);

串行写入(0x0d);

串行写入(0x0a);

}



主函数()

{

LCDPORTDIR=0xFF;

序列开始();

serialprint("萨达姆汗");

液晶开始();

lcdprint("GPS 接口");

液晶写入(192,CMD);

lcdprint("使用 Atmega16");

_delay_ms(2000);

液晶写入(1,0);

lcdprint("正在等待 GPS");

_delay_ms(2000);

sei();

而(1)

{

如果(字符串接收 == 1)

{

cli();

serialprint("收到的字符串:");

for(int i=0;i
串行写入(buf[i]);

指数=0;

字符串接收=0;

串行打印(“”);

液晶写入(0x80,0);

lcdprint("纬度:");

serialprint("纬度:");

for(int i=15;i<27;i++)

{

纬度[i]=buf[i];

lcdwrite(纬度[i],1);

串行写入(纬度 [i]);

如果(我==24)

{

lcdwrite('',1);

我++;

}

}

串行打印(“”);

液晶写入(192,0);

lcdprint("日志:");

serialprint("Logitude:");

for(int i=29;i<41;i++)

{

对数[i]=buf[i];

lcdwrite(logitude[i],1);

串行写入(logitude [i]);

如果(我==38)

{

lcdwrite('',1);

我++;

}



}

串行打印(“”);

串行冲洗();

_delay_ms(2000);

sei();

}

}

返回0;

}

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分