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 模塊,通過串行通信提供位置詳細信息。它有四個引腳。
Ublox neo 6M GPS 模塊與 TTL 兼容,其規格如下。
從 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微控制器接口的電路圖如下:
整個系統由 12v 直流適配器供電,但電路工作在 5v 上,因此電源由 LM7805 穩壓器調節至 5v。16x2 LCD 配置為 4 位模式 ,其引腳連接如電路圖所示。GPS 也由 5v 供電,其 tx 引腳直接連接到Atmega16 微控制器的 Rx 。一個 8MHz 晶體振蕩器用于為微控制器提供時鐘。
將 GPS 與 AVR 微控制器連接的步驟
設置微控制器的配置,包括振蕩器配置。
使用 USART 將 GPS 模塊連接到微控制器。
在 ISR 模式下初始化系統 UART,波特率為 9600,LCD 為 4 位模式。
根據緯度和經度的長度取兩個字符數組。
每次接收一個字符位,并檢查它是否從 $ 開始。
如果接收到$,那么它是一個字符串,我們需要檢查$GPGGA,這6個字母包括$。
如果是 GPGGA,則接收完整的字符串并設置標志。
然后用兩個數組中的方向提取緯度和經度。
最后在 LCD 中打印經緯度數組。
代碼說明
最后給出了完整的代碼和演示視頻,這里解釋了代碼的一些重要部分。
首先在代碼中包含一些必需的標頭,然后為 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,
數據,
};
字符緩沖區;
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;
}
-
ATmega16
+關注
關注
5文章
154瀏覽量
45835 -
GPS模塊
+關注
關注
0文章
87瀏覽量
16465 -
AVR微控制器
+關注
關注
0文章
11瀏覽量
6824
發布評論請先 登錄
相關推薦
評論