GPS 模塊廣泛用于電子應用中,以根據(jù)經度和緯度坐標跟蹤位置。車輛跟蹤系統(tǒng)、 GPS 時鐘、 事故檢測警報系統(tǒng)、交通導航、監(jiān)控系統(tǒng)等是 GPS 功能必不可少的幾個例子。GPS 提供海拔、緯度、經度、UTC 時間和有關特定位置的許多其他信息,這些信息來自多顆衛(wèi)星。要從 GPS 讀取數(shù)據(jù),需要一個微控制器,因此我們將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 模塊,通過串行通信提供位置詳細信息。它有四個引腳。
Ublox neo 6M GPS 模塊與 TTL 兼容,其規(guī)格如下。
從 GPS 獲取位置數(shù)據(jù)
GPS 模塊將以 9600 波特率在多個字符串中傳輸數(shù)據(jù)。如果我們使用波特率為 9600 的 UART 終端,我們可以看到 GPS 接收到的數(shù)據(jù)。
這是以 9600 波特率連接時 GPS 接收到的數(shù)據(jù)。
$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(全球定位系統(tǒng)固定數(shù)據(jù))字符串主要用于程序中,其他字符串被忽略。
$GPGGA,141848.00,2237.63306,N,08820.86316,E,1,03,2.56,1.9,M,-54.2,M,,*74
所以我們需要 5 號和 6 號來收集有關模塊位置或它所在位置的信息。在這個項目中,我們使用了一個 GPS 庫,它提供了一些函數(shù)來提取緯度和經度,所以我們不必擔心這一點。
電路原理圖
GPS與AVR Atemga16微控制器接口的電路圖如下:
整個系統(tǒng)由 12v 直流適配器供電,但電路工作在 5v 上,因此電源由 LM7805 穩(wěn)壓器調節(jié)至 5v。16x2 LCD 配置為 4 位模式 ,其引腳連接如電路圖所示。GPS 也由 5v 供電,其 tx 引腳直接連接到Atmega16 微控制器的 Rx 。一個 8MHz 晶體振蕩器用于為微控制器提供時鐘。
將 GPS 與 AVR 微控制器連接的步驟
設置微控制器的配置,包括振蕩器配置。
使用 USART 將 GPS 模塊連接到微控制器。
在 ISR 模式下初始化系統(tǒng) UART,波特率為 9600,LCD 為 4 位模式。
根據(jù)緯度和經度的長度取兩個字符數(shù)組。
每次接收一個字符位,并檢查它是否從 $ 開始。
如果接收到$,那么它是一個字符串,我們需要檢查$GPGGA,這6個字母包括$。
如果是 GPGGA,則接收完整的字符串并設置標志。
然后用兩個數(shù)組中的方向提取緯度和經度。
最后在 LCD 中打印經緯度數(shù)組。
代碼說明
最后給出了完整的代碼和演示視頻,這里解釋了代碼的一些重要部分。
首先在代碼中包含一些必需的標頭,然后為 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<
現(xiàn)在聲明并初始化一些變量和數(shù)組,用于存儲 GPS 字符串、緯度經度和標志。
字符緩沖區(qū)[100]; volatile char ind、flag、stringReceived; char gpgga[]={'$','G','P','G','G','A'}; 字符緯度[12]; 字符對數(shù)[12];
之后我們有一些 LCD Driver 函數(shù)來驅動 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 = 通道; }
現(xiàn)在如果接收到的字符串與 GPGGA 匹配成功,則在main函數(shù)中提取并顯示該位置的經緯度坐標:
液晶寫入(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
*
* 創(chuàng)建時間: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,
數(shù)據(jù),
};
字符緩沖區(qū);
volatile char ind、flag、stringReceived;
char gpgga[]={'$','G','P','G','G','A'};
字符緯度[12];
字符對數(shù)[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++;
如果(指數(shù)<7)
{
if(buf[ind-1] != gpgga[ind-1]) // $GPGGA
指數(shù)=0;
}
如果(指數(shù)>=50)
字符串接收=1;
}
無效串行寫入(字符 ch)
{
而 ((UCSRA & (1 << UDRE)) == 0);
UDR = 通道;
}
無效序列打?。ㄗ址?*str)
{
而(*str)
{
串行寫入(*str++);
}
}
無效串行打?。ㄗ址?*str)
{
序列打印(str);
串行寫入(0x0d);
串行寫入(0x0a);
}
主函數(shù)()
{
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]);
指數(shù)=0;
字符串接收=0;
串行打?。ā啊保?br />
液晶寫入(0x80,0);
lcdprint("緯度:");
serialprint("緯度:");
for(int i=15;i<27;i++)
{
緯度[i]=buf[i];
lcdwrite(緯度[i],1);
串行寫入(緯度 [i]);
如果(我==24)
{
lcdwrite('',1);
我++;
}
}
串行打?。ā啊保?br />
液晶寫入(192,0);
lcdprint("日志:");
serialprint("Logitude:");
for(int i=29;i<41;i++)
{
對數(shù)[i]=buf[i];
lcdwrite(logitude[i],1);
串行寫入(logitude [i]);
如果(我==38)
{
lcdwrite('',1);
我++;
}
}
串行打?。ā啊保?br />
串行沖洗();
_delay_ms(2000);
sei();
}
}
返回0;
}
-
ATmega16
+關注
關注
5文章
154瀏覽量
45750 -
GPS模塊
+關注
關注
0文章
87瀏覽量
16410 -
AVR微控制器
+關注
關注
0文章
11瀏覽量
6798
發(fā)布評論請先 登錄
相關推薦
評論