|
利用GPS北斗ATGM336H-5N模塊輸出的原始定位信息,發(fā)到單片機(jī)后進(jìn)行處理,提取有用的信息如經(jīng)緯度、速度、海拔、日期等,通過串口發(fā)到電腦的串口調(diào)試助手進(jìn)行顯示,并顯示到LCD屏幕。
12.jpg (274.91 KB, 下載次數(shù): 1077)
下載附件
2017-11-2 01:10 上傳
程序的功能有GPS信息顯示與發(fā)送(LCD顯示經(jīng)緯度、海拔、速度,電腦串口接收時(shí)間、日期、經(jīng)緯度、海拔、速度數(shù)據(jù))
GPS原始數(shù)據(jù)捕獲(從一開始通電時(shí)不完整到過一會(huì)后完整)見附件
GPS原始數(shù)據(jù)捕獲與簡(jiǎn)單分析:
$GNGGA,120726.000,3208.0858,N,11841.7828,E,1,05,4.3,12.7,M,0.0,M,,*40
$GNGLL,3208.0858,N,11841.7828,E,120726.000,A,A*43
$GPGSA,A,3,12,25,,,,,,,,,,,6.9,4.3,5.4*3F
$BDGSA,A,3,10,04,07,,,,,,,,,,6.9,4.3,5.4*28
$GPGSV,3,1,12,04,,,21,10,66,313,,12,42,100,34,14,21,289,*49
$GPGSV,3,2,12,15,18,086,,18,79,174,27,20,13,143,24,21,18,203,*73
$GPGSV,3,3,12,24,40,042,,25,37,150,31,31,10,230,,32,33,301,*7A
$BDGSV,1,1,04,03,,,35,04,32,122,34,07,54,184,34,10,33,200,36*50
$GNRMC,120726.000,A,3208.0858,N,11841.7828,E,0.11,303.11,031017,,,A*70
$GNVTG,303.11,T,,M,0.11,N,0.20,K,A*21
$GNZDA,120726.000,03,10,2017,00,00*4E
$GPTXT,01,01,01,ANTENNA OK*35
原始數(shù)據(jù)中逗號(hào)數(shù)量和順序的統(tǒng)計(jì):
--------------------------
1 2 3 4 5 6 7 8 9 a b c d
$GNGGA,034214.000,3208.1201,N,11841.7167,E,1,07,1.7,7.7,M,0.0,M,,*7 OK*
1 2 3 4 5 6 7 8 9 abc
$GNRMC,034214.000,A,3208.1201,N,11841.7167,E,2.71,336.76,041017,,,A*700
--------------------------
GPS原始數(shù)據(jù)及處理后的數(shù)據(jù)
(見附件)
單片機(jī)源程序如下:
- /*******************************************************************************
- 單片機(jī)的RXD端口接收來(lái)自GPS模塊的數(shù)據(jù),把數(shù)據(jù)進(jìn)行處理,并顯示到Lcd上,同時(shí)
- 通過TXD端口經(jīng)過USB-TTL模塊發(fā)送到電腦的串口調(diào)試軟件上顯示。
- 注意事項(xiàng):
- 1、串口調(diào)試軟件的波特率要設(shè)為9600;
- 2、單片機(jī)與USB-TTL模塊兩者要共地。。。ㄎ乙膊恢獮槭裁,攤手.jpg)
- *******************************************************************************/
- #include "reg52.h"
- #include "main.h"
- #include "LCD1602.h"
- #include "GPS.h"
- unsigned char xdata Display_GPGGA_Buffer[68]={0}; //用于儲(chǔ)存GPGGA的數(shù)據(jù)
- unsigned char xdata Display_GPRMC_Buffer[68]={0}; //用于儲(chǔ)存GPRMC的數(shù)據(jù)
- unsigned int k=0,qian_a=0,hou_a=0,qian_b=0,hou_b=0,qian_c=0,hou_c=0; //存儲(chǔ)前后逗號(hào)的位置序號(hào)的變量
- bit qian_OK=0; //已找出前面的逗號(hào)的標(biāo)志變量
- bit First_Share_OK=0; //已開始LCD顯示的標(biāo)志變量
- bit jiajian=1; //進(jìn)行加或減的標(biāo)志變量
- //bit Page = 0;
- bit Flag_OV = 0; //日期需進(jìn)位的標(biāo)志變量
- bit Flag_Calc_GPGGA_OK = 0; //GPGGA完整有效的數(shù)據(jù)已收到的標(biāo)志變量
- bit Flag_Calc_GPRMC_OK = 0; //GPRMC完整有效的數(shù)據(jù)已收到的標(biāo)志變量
- //****************************************************
- //主函數(shù)
- //****************************************************
- void main()
- {
- unsigned int i = 0;
- unsigned int j=0;
- Init_LCD1602(); //LCD初始化
- LCD1602_write_com(0x80); //LCD指針設(shè)置到第一行第一列
- LCD1602_write_word("Searching data. "); //顯示正在搜索數(shù)據(jù)
- Uart_Init(); //串口初始化
- while(1)
- {
- // Scan_Key();
- qian_OK=0; //標(biāo)志變量歸零
- k=0; //累計(jì)量歸零
- if (First_Share_OK==0) //讓變量j在0~10000之間來(lái)回增減,增加到10000時(shí)顯示". ",減到0時(shí)顯示" .",實(shí)現(xiàn)兩點(diǎn)來(lái)回閃動(dòng)
- {
- if (jiajian==1)
- {
- j++;
- if (j==10000)
- {
- jiajian=0;
- LCD1602_write_com(0x8e);
- LCD1602_write_data('.');
- LCD1602_write_com(0x8f);
- LCD1602_write_data(' ');
- }
- }
- else
- {
- j--;
- if (j==0)
- {
- jiajian=1;
- LCD1602_write_com(0x8e);
- LCD1602_write_data(' ');
- LCD1602_write_com(0x8f);
- LCD1602_write_data('.');
- }
- }
- }
- //代碼詳見附件
- // {
- // UartPrintf("----------------------------------------------\r\n");
- // UartPrintf(RX_Buffer);
- // UartPrintf("\r\n");
- // }
-
- if ( Flag_GPS_OK == 1
- && RX_Buffer[1] == 'G'
- && RX_Buffer[3] == 'G'
- && RX_Buffer[4] == 'G'
- && RX_Buffer[5] == 'A'
- && (RX_Buffer[28] == 'N'|| RX_Buffer[28] == 'S')
- && (RX_Buffer[41] == 'E'|| RX_Buffer[41] == 'W') ) //確認(rèn)是否收到"GPGGA"這一幀完整有效的數(shù)據(jù)
- {
- for( i = 0; i < 67 ; i++) //必須為i<67,因?yàn)橐_保Display_GPGGA_Buffer[67]為'\0',便于串口發(fā)送
- {
- Display_GPGGA_Buffer[i] = RX_Buffer[i]; //儲(chǔ)存到數(shù)組中
- }
- Flag_Calc_GPGGA_OK = 1; //收到完整有效數(shù)據(jù)后,置為1
- }
- if(Flag_Calc_GPGGA_OK == 1) //已收到完整有效的數(shù)據(jù),可以進(jìn)行顯示,
- {
- Flag_Calc_GPGGA_OK = 0; //標(biāo)志位歸零
- if (First_Share_OK == 0)
- {
- First_Share_OK=1; //"Searching data. "不需再顯示,標(biāo)志變量置為1
- LCD1602_write_com(0x01); //先清屏
- }
-
- LCD1602_write_com(0x80);
- LCD1602_write_data(Display_GPGGA_Buffer[28]); //顯示 N 或者 S
- LCD1602_write_word(": ");
- LCD1602_write_data(Display_GPGGA_Buffer[18]); //緯度
- LCD1602_write_data(Display_GPGGA_Buffer[19]);
- LCD1602_write_data(0xdf); //度符號(hào)的ASCII碼,16進(jìn)制
- LCD1602_write_data(Display_GPGGA_Buffer[20]); //緯度
- LCD1602_write_data(Display_GPGGA_Buffer[21]);
- LCD1602_write_word("'"); //秒
- for (i=0;i<68;i++) //由于海拔有時(shí)是1位數(shù)有時(shí)是2位數(shù)有時(shí)是3位數(shù),不定
- { //而確定的是其數(shù)值在第9與第10個(gè)逗號(hào)之間,所以用此算法輸出海拔
- if ( Display_GPGGA_Buffer[i]==',' ) //逐個(gè)檢索
- k++; //k計(jì)算逗號(hào)數(shù)量
- if (k==9&&qian_OK==0)
- qian_a=i,qian_OK=1; //找到第9個(gè),則記錄其序號(hào),同時(shí)標(biāo)志變量置為1
- if (k==10) //海拔數(shù)據(jù)位于第9~10個(gè)逗號(hào)之間
- {
- hou_a=i; //記錄第10個(gè)的序號(hào)
- k=0; //歸零
- qian_OK=0; //重置為0
- break; //找到后直接跳出循環(huán)
- }
- }
- LCD1602_write_com(0x89); //準(zhǔn)備在第一行第9列輸出海拔數(shù)據(jù)
- switch(hou_a-qian_a-1) //計(jì)算海拔數(shù)據(jù)的長(zhǎng)度
- {
- case 3:LCD1602_write_word(" ");break; //根據(jù)海拔數(shù)據(jù)長(zhǎng)度輸出對(duì)應(yīng)所需的空格數(shù),使其顯示方式為右對(duì)齊
- case 4:LCD1602_write_word(" ");break;
- case 5:LCD1602_write_word(" ");break;
- case 6:break;
- case 7:break;
- }
- for (i=qian_a+1; i<=hou_a-1; i++)
- LCD1602_write_data(Display_GPGGA_Buffer[i]); //輸出海拔
- LCD1602_write_data('m'); //顯示單位
-
- LCD1602_write_com(0xc0); //在第2行第1列開始輸出經(jīng)度
- LCD1602_write_data(Display_GPGGA_Buffer[41]); //輸出E 或者 W
- LCD1602_write_data(':');
- LCD1602_write_data(Display_GPGGA_Buffer[30]); //經(jīng)度
- LCD1602_write_data(Display_GPGGA_Buffer[31]);
- LCD1602_write_data(Display_GPGGA_Buffer[32]);
- LCD1602_write_data(0xdf);
- LCD1602_write_data(Display_GPGGA_Buffer[33]);
- LCD1602_write_data(Display_GPGGA_Buffer[34]);
- LCD1602_write_word("'");
- UartPrintf("----------------------------------------------\r\n"); //串口發(fā)送數(shù)據(jù)到電腦
- UartPrintf("Original data(1):\r\n");
- UartPrintf(Display_GPGGA_Buffer); //直接把首地址作為實(shí)參
- UartPrintf("......\r\n");
- UartPrintf("Processed data(1): \r\n");
- UartPrintData(Display_GPGGA_Buffer[28]); //N 或者 S
- UartPrintf(": ");
- UartPrintData(Display_GPGGA_Buffer[18]); //發(fā)送緯度
- UartPrintData(Display_GPGGA_Buffer[19]);
- UartPrintData('*'); //串口無(wú)法發(fā)送擴(kuò)展的ASCII碼(大于127),所以用*代替度數(shù)符號(hào)
- UartPrintData(Display_GPGGA_Buffer[20]);
- UartPrintData(Display_GPGGA_Buffer[21]);
- UartPrintData('\'');
- UartPrintf("\r\n"); //發(fā)送回車換行
-
- UartPrintData(Display_GPGGA_Buffer[41]); //E 或者 W
- UartPrintf(": ");
- UartPrintData(Display_GPGGA_Buffer[30]);
- UartPrintData(Display_GPGGA_Buffer[31]);
- UartPrintData(Display_GPGGA_Buffer[32]);
- UartPrintData('*');
- UartPrintData(Display_GPGGA_Buffer[33]); //發(fā)送經(jīng)度
- UartPrintData(Display_GPGGA_Buffer[34]);
- UartPrintData('\'');
- UartPrintf("\r\n");
- UartPrintf("Altitude: ");
- for (i=qian_a+1; i<=hou_a-1; i++) //發(fā)送海拔
- UartPrintData(Display_GPGGA_Buffer[i]);
- UartPrintf(" m");
- UartPrintf("\r\n");
-
- }
- // 這部分代碼詳見附件
- && RX_Buffer[1] == 'G'&& RX_Buffer[3] == 'R'&& RX_Buffer[4] == 'M'&& RX_Buffer[5] == 'C')
- // {
- // UartPrintf(RX_Buffer);
- // UartPrintf("\r\n");
- // }
-
- if( Flag_GPS_OK == 1
- && RX_Buffer[1] == 'G'
- && RX_Buffer[3] == 'R'
- && RX_Buffer[4] == 'M'
- && RX_Buffer[5] == 'C'
- && RX_Buffer[18]== 'A') //確認(rèn)是否收到"GPRMC"這一幀完整有效的數(shù)據(jù)
- {
- for( i = 0; i < 67 ; i++)
- {
- Display_GPRMC_Buffer[i] = RX_Buffer[i];
- }
-
- Flag_Calc_GPRMC_OK = 1;
-
- Hour = (Display_GPRMC_Buffer[7]-0x30)*10+(Display_GPRMC_Buffer[8]-0x30)+8; //UTC時(shí)間轉(zhuǎn)換到北京時(shí)間(東八區(qū)),0x30即48
- if( Hour >= 24) //如果溢出
- {
- Hour %= 24; //獲取實(shí)際Hour
- Flag_OV = 1; //日期進(jìn)位的標(biāo)志變量置為1
- }
- else
- {
- Flag_OV = 0;
- }
- Min_High = Display_GPRMC_Buffer[9];
- Min_Low = Display_GPRMC_Buffer[10]; //獲取時(shí)間數(shù)據(jù)
- Sec_High = Display_GPRMC_Buffer[11];
- Sec_Low = Display_GPRMC_Buffer[12];
- for (i=0;i<68;i++) //由于日期數(shù)據(jù)前面的速度數(shù)據(jù)也是位數(shù)不定,所以速度數(shù)據(jù)位數(shù)也不定,故亦用此算法精確地確定日期數(shù)據(jù)位置
- {
- if ( Display_GPRMC_Buffer[i]==',' )
- k++;
- if (k==9&&qian_OK==0) //日期數(shù)據(jù)位于第9~10個(gè)逗號(hào)之間
- qian_b=i,qian_OK=1;
- if (k==10)
- {
- hou_b=i;
- k=0;
- qian_OK=0;
- break;
- }
- }
- Year_High = Display_GPRMC_Buffer[qian_b+5]; //獲取日期
- Year_Low = Display_GPRMC_Buffer[qian_b+6];
- Month_High = Display_GPRMC_Buffer[qian_b+3];
- Month_Low = Display_GPRMC_Buffer[qian_b+4];
- Day_High = Display_GPRMC_Buffer[qian_b+1];
- Day_Low = Display_GPRMC_Buffer[qian_b+2];
- if(Flag_OV == 1) //如果日期須進(jìn)位
- {
- UTCDate2LocalDate(); //UTC日期進(jìn)位并轉(zhuǎn)換為北京時(shí)間
- }
- }
- if(Flag_Calc_GPRMC_OK == 1) //GPRMC數(shù)據(jù)完整有效則顯示
- {
- Flag_Calc_GPRMC_OK = 0;
- if (First_Share_OK == 0)
- {
- First_Share_OK=1;
- LCD1602_write_com(0x01);
- }
- for (i=0;i<68;i++) //由于速度數(shù)據(jù)也是位數(shù)不定,故亦用此算法精確地確定速度數(shù)據(jù)位置
- {
- if ( Display_GPRMC_Buffer[i]==',' )
- k++;
- if (k==7&&qian_OK==0) //速度數(shù)據(jù)位于第7~8個(gè)逗號(hào)之間
- qian_c=i,qian_OK=1;
- if (k==8)
- {
- hou_c=i;
- k=0;
- qian_OK=0;
- break;
- }
- }
- LCD1602_write_com(0xc9); //準(zhǔn)備在第2行第9列顯示
- switch(hou_c-qian_c-2) //原式為(hou_c-1)-qian_c-1。由于速度不太準(zhǔn)還浮動(dòng),故只讓它顯示一位小數(shù)
- {
- case 3:LCD1602_write_word(" ");break; //使右對(duì)齊
- case 4:break;
- case 5:break;
- }
- for (i=qian_c+1; i<=hou_c-2; i++) //(原式為hou_c-1-1)
- LCD1602_write_data(Display_GPRMC_Buffer[i]); //顯示速度
- LCD1602_write_word("m/s"); //顯示單位
- UartPrintf("\r\n");
- UartPrintf("Original data(2):\r\n");
- UartPrintf(Display_GPRMC_Buffer);
- UartPrintf("......\r\n");
- UartPrintf("Processed data(2): \r\n");
- UartPrintf("Time: ");
- UartPrintData(Hour/10+0x30); //串口發(fā)送時(shí)間
- UartPrintData(Hour%10+0x30);
- UartPrintData(':');
- UartPrintData(Min_High);
- UartPrintData(Min_Low);
- UartPrintData(':');
- UartPrintData(Sec_High);
- UartPrintData(Sec_Low);
- UartPrintf("\r\n");
- UartPrintf("Date: "); //發(fā)送日期
- UartPrintf("20");
- UartPrintData(Display_GPRMC_Buffer[qian_b+5]);
- UartPrintData(Display_GPRMC_Buffer[qian_b+6]);
- UartPrintData('-');
- UartPrintData(Display_GPRMC_Buffer[qian_b+3]);
- UartPrintData(Display_GPRMC_Buffer[qian_b+4]);
- UartPrintData('-');
- UartPrintData(Display_GPRMC_Buffer[qian_b+1]);
- UartPrintData(Display_GPRMC_Buffer[qian_b+2]);
- UartPrintf("\r\n");
- UartPrintf("Speed: ");
- for (i=qian_c+1; i<=hou_c-1; i++)
- UartPrintData(Display_GPRMC_Buffer[i]);
- UartPrintf(" m/s\r\n"); //發(fā)送速度,2位小數(shù)都發(fā)
- UartPrintf("----------------------------------------------\r\n");//分隔符
-
- }
-
- }
- }
- //****************************************************
- //UTC日期與當(dāng)?shù)厝掌谵D(zhuǎn)換
- //****************************************************
- void UTCDate2LocalDate(void)
- {
- Day = (Day_High - 0x30) * 10 + (Day_Low-0x30) + 1; //日期進(jìn)一
- Month = (Month_High - 0x30) * 10 + (Month_Low - 0x30);
- Year = 2000 + (Year_High - 0x30) * 10 + (Year_Low - 0x30);
-
- MaxDay = GetMaxDay(Month,Year); //獲取當(dāng)月天數(shù)最大值
- if(Day > MaxDay) //如果溢出
- {
- Day = 1;
- Month += 1;
- if(Month > 12)
- {
- Year+=1;
- }
- }
- Day_High = Day/10 + 0x30; //轉(zhuǎn)換日期值為ASCII
- Day_Low = Day%10 + 0x30;
- Month_High = Month/10 + 0x30;
- Month_Low = Month%10 + 0x30;
- Year_High = Year%100/10 + 0x30;
- Year_Low = Year%10 + 0x30;
- }
- //****************************************************
- //獲取當(dāng)月日期最大值
- //****************************************************
- 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月份比較特殊,需要根據(jù)是不是閏年來(lái)判斷當(dāng)月是28天還29天
- iDays = IsLeapYear(Year_Value) ? 29 : 28 ;
- }
- break;
- case 4:
- case 6:
- case 9:
- case 11:
- {
- iDays = 30;
- }
- ……………………
- …………限于本文篇幅 余下代碼請(qǐng)從51黑下載附件…………
復(fù)制代碼
所有資料51hei提供下載:
GPS(LCD,USart).zip
(101.7 KB, 下載次數(shù): 363)
2017-11-1 21:40 上傳
點(diǎn)擊文件名下載附件
GPS信息發(fā)到單片機(jī),經(jīng)過處理,發(fā)到串口,并顯示到LCD 下載積分: 黑幣 -5
|
評(píng)分
-
查看全部評(píng)分
|