久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 12069|回復: 19
打印 上一主題 下一主題
收起左側(cè)

基于51單片機的GPS定位系統(tǒng)程序設計 LCD12864顯示

  [復制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:258336 發(fā)表于 2019-4-23 11:37 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
新人一枚,由于某些需要制作這一塊的東西,就把自己的理解寫在這里,歡迎各位大佬交流。
GPS定位的基本工作原理是:導航衛(wèi)星上搭載了專用的無線電設備,可向地面用戶不斷的發(fā)射固定頻段的無線電信號,用戶利用導航接收機收到衛(wèi)星上的導航信號后,通過時間測距或多普勒測速獲得自己相對于衛(wèi)星的距離參數(shù),并根據(jù)衛(wèi)星發(fā)播的軌道、時間參數(shù)等信息求得衛(wèi)星的實時位置,進而解算出自身的地理位置坐標和速度矢量。
衛(wèi)星星文信息的解算我們大可不必深究,市面上有現(xiàn)成的集成模塊可以實現(xiàn)衛(wèi)星信號的解算輸出,并且?guī)缀跛械哪K都遵循或至少兼容統(tǒng)一的串口通信協(xié)議--NMEA 0183。
   

     多數(shù)GPS模塊的引腳主要為VCC、GND、TXD、RXD、PPS。其中TXD、RXD為串口通信接口,PPS為秒脈沖輸出接口,用于同步授時。模塊的串口輸出如圖所示(可用一個USB轉(zhuǎn)TTL模塊將GPS模塊和電腦相連,再用串口助手或模塊自帶的配置軟件查看GPS模塊串口的輸出)



     由此可見,GPS模塊每秒各輸出一次$GPGGA $GPGSA $GPGSV $GPGLL $GPRMC $GPVTG語句,其中最常用的語句為$GPRMC。它的基本格式如下:
$GPRMC,(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)*hh(CR)(LF)
        (1) UTC時間,hhmmss(時分秒)
        (2) 定位狀態(tài),A=有效定位,V=無效定位
        (3) 緯度ddmm.mmmmm(度分)
        (4) 緯度半球N(北半球)或S(南半球)
        (5) 經(jīng)度dddmm.mmmmm(度分)
        (6) 經(jīng)度半球E(東經(jīng))或W(西經(jīng))
        (7) 地面速率(000.0~999.9節(jié))
        (8) 地面航向(000.0~359.9度,以真北方為參考基準)
        (9) UTC日期,ddmmyy(日月年)
        (10)磁偏角(000.0~180.0度,前導位數(shù)不足則補0)
        (11) 磁偏角方向,E(東)或W(西)
        (12) 模式指示(A=自主定位,D=差分,E=估算,N=數(shù)據(jù)無效)
      可以通過GPS模塊的配置軟件讓模塊只輸出這一條語句,也可以通過判斷第四位的字符是不是"M"從這幾條語句中篩選出$GPRMC語句。編程的流程圖如下圖所示:

     這樣解碼的效率較低,但不影響效果?梢栽诖诮邮罩袛嗬锒x一個5位的命令類型數(shù)組,在中斷內(nèi)就判斷命令的類型,這樣免去了每條命令都完全接收的麻煩。這里衛(wèi)星解碼過后的定位數(shù)據(jù)、時間數(shù)據(jù)可以直接用1602和12864顯示。由于我的課設需求是要有一個基于LabView的上位機顯示,所以還需要考慮串口被占用的問題。由于還有其他數(shù)據(jù)需要處理,加之用普通IO口模擬串口輸出效率較低需要占用較多資源,所以暫定用三態(tài)門拓展串口。以后不定期再更新完善,歡迎各位交流指點。1602和12864顯示的代碼就添加在附件里了。

V1.0第一次編寫
V1.1更改一些外部中斷的BUG
V1.2加入UTC時間/日期和北京時間/日期的轉(zhuǎn)換,包括閏年、日/月/年的進位計算

單片機源程序如下:
  1. #include "main.h"
  2. #include "LCD12864.h"
  3. #include "GPS.h"

  4. //定義變量
  5. unsigned char KEY_NUM = 0;
  6. bit Page = 0;
  7. unsigned char xdata Display_GPGGA_Buffer[68];
  8. unsigned char xdata Display_GPRMC_Buffer[68];
  9. bit Flag_OV = 0;
  10. bit Flag_Calc_GPGGA_OK = 0;
  11. bit Flag_Calc_GPRMC_OK = 0;

  12. //****************************************************
  13. //主函數(shù)
  14. //****************************************************
  15. void main()
  16. {
  17.         unsigned char i = 0;
  18.         LCD12864_Reset();                                                                //初始化液晶
  19.         LCD12864_HAIZI_SET();                                                        //設置為普通模式
  20.         
  21.         Delay_ms(100);
  22.         

  23.         LCD12864_NoWaitIdle_COM_Write(0x80);                                                //指針設置
  24.         LCD12864_write_word("※※※※※※※※");
  25.         LCD12864_NoWaitIdle_COM_Write(0x90);                                                //指針設置
  26.         LCD12864_write_word("    歡迎使用    ");                        
  27.         LCD12864_NoWaitIdle_COM_Write(0x88);                                                //指針設置
  28.         LCD12864_write_word("正在初始化GPS...");
  29.         LCD12864_NoWaitIdle_COM_Write(0x98);                                                //指針設置
  30.         LCD12864_write_word("※※※※※※※※");

  31.         Uart_Init();

  32.         while(1)
  33.         {
  34.                 Scan_Key();
  35.                 if(Flag_GPS_OK == 1 && RX_Buffer[4] == 'G' && RX_Buffer[6] == ',' && RX_Buffer[13] == '.')                        //確定是否收到"GPGGA"這一幀數(shù)據(jù)
  36.                 {
  37.                         for( i = 0; i < 68 ; i++)
  38.                         {
  39.                                 Display_GPGGA_Buffer[i] = RX_Buffer[i];        
  40.                         }
  41.                         Hour = (Display_GPGGA_Buffer[7]-0x30)*10+(Display_GPGGA_Buffer[8]-0x30)+8;                        //UTC時間轉(zhuǎn)換到北京時間UTC+8   
  42.                                                                                                                                                                                                 //0X30為ASCII碼轉(zhuǎn)換為數(shù)字
  43.                                 if( Hour >= 24)                                //溢出
  44.                         {
  45.                                 Hour %= 24;                                //獲取當前Hour
  46.                                 Flag_OV = 1;                        //日期進位
  47.                         }
  48.                         else
  49.                         {
  50.                                 Flag_OV = 0;
  51.                         }

  52.                         Min_High = Display_GPGGA_Buffer[9];
  53.                         Min_Low = Display_GPGGA_Buffer[10];
  54.         
  55.                         Sec_High = Display_GPGGA_Buffer[11];
  56.                         Sec_Low = Display_GPGGA_Buffer[12];

  57.                         Flag_Calc_GPGGA_OK = 1;
  58.                 }

  59.                 if(Page == 0 && Flag_Calc_GPGGA_OK == 1)
  60.                 {
  61.                         LED1 = ~LED1;
  62.                         Flag_Calc_GPGGA_OK = 0;
  63.                
  64.                         LCD12864_NoWaitIdle_COM_Write(0x80);                        //設置指針
  65.                         LCD12864_write_word("★");                                //顯示內(nèi)容
  66.                         LCD12864_Data_Write(Hour/10+0x30);
  67.                         LCD12864_Data_Write(Hour%10+0x30);
  68.                         LCD12864_write_word("時");
  69.         
  70.                         LCD12864_Data_Write(Min_High);
  71.                         LCD12864_Data_Write(Min_Low);
  72.                         LCD12864_write_word("分");
  73.         
  74.                         LCD12864_Data_Write(Sec_High);
  75.                         LCD12864_Data_Write(Sec_Low);
  76.                         LCD12864_write_word("秒");
  77.                         LCD12864_write_word("★");
  78.         
  79.         
  80.                         LCD12864_NoWaitIdle_COM_Write(0x90);                        //設置指針
  81.                         LCD12864_write_word("緯度:");                                //顯示內(nèi)容
  82.                         
  83.                         LCD12864_Data_Write(Display_GPGGA_Buffer[28]);                        //N 或者 S
  84.                         LCD12864_Data_Write(' ');

  85.                         LCD12864_Data_Write(Display_GPGGA_Buffer[17]);                        //緯度
  86.                         LCD12864_Data_Write(Display_GPGGA_Buffer[18]);                        //緯度
  87.                         LCD12864_write_word("°");
  88.                         LCD12864_Data_Write(Display_GPGGA_Buffer[19]);                        //緯度
  89.                         LCD12864_Data_Write(Display_GPGGA_Buffer[20]);                        //緯度
  90.                         LCD12864_write_word("' ");


  91.                         LCD12864_NoWaitIdle_COM_Write(0x88);                        //設置指針
  92.                         LCD12864_write_word("經(jīng)度:");                                //顯示內(nèi)容
  93.                         
  94.                         LCD12864_Data_Write(Display_GPGGA_Buffer[42]);                        //E 或者 W

  95.                         LCD12864_Data_Write(Display_GPGGA_Buffer[30]);                        //經(jīng)度
  96.                         LCD12864_Data_Write(Display_GPGGA_Buffer[31]);        
  97.                         LCD12864_Data_Write(Display_GPGGA_Buffer[32]);        
  98.                         LCD12864_write_word("°");
  99.                         LCD12864_Data_Write(Display_GPGGA_Buffer[33]);                        
  100.                         LCD12864_Data_Write(Display_GPGGA_Buffer[34]);               
  101.                         LCD12864_write_word("' ");

  102.                         LCD12864_NoWaitIdle_COM_Write(0x98);                        //設置指針
  103.                         LCD12864_write_word("海拔:    ");                                //顯示內(nèi)容
  104.                         
  105.                         LCD12864_Data_Write(Display_GPGGA_Buffer[54]);        
  106.                         LCD12864_Data_Write(Display_GPGGA_Buffer[55]);        
  107.                         LCD12864_Data_Write(Display_GPGGA_Buffer[56]);        
  108.                         LCD12864_Data_Write(Display_GPGGA_Buffer[57]);
  109.                         LCD12864_write_word("米");                        
  110.                 }
  111.                
  112.                 if(Flag_GPS_OK == 1 && RX_Buffer[4] == 'M' && RX_Buffer[52] == ',' && RX_Buffer[59] == ',')                        //確定是否收到"GPRMC"這一幀數(shù)據(jù)
  113.                 {
  114.                         for( i = 0; i < 68 ; i++)
  115.                         {
  116.                                 Display_GPRMC_Buffer[i] = RX_Buffer[i];        
  117.                         }

  118.                         Year_High = Display_GPRMC_Buffer[57];
  119.                         Year_Low = Display_GPRMC_Buffer[58];

  120.                         Month_High = Display_GPRMC_Buffer[55];
  121.                         Month_Low = Display_GPRMC_Buffer[56];

  122.                         Day_High = Display_GPRMC_Buffer[53];
  123.                         Day_Low = Display_GPRMC_Buffer[54];


  124.                         if(Flag_OV == 1)                        //有進位
  125.                         {
  126.                                 UTCDate2LocalDate();                        //UTC日期轉(zhuǎn)換為北京時間               
  127.                         }

  128.                         Flag_Calc_GPRMC_OK = 1;
  129.                 }

  130.                 if(Page == 1 && Flag_Calc_GPRMC_OK == 1)
  131.                 {
  132.                         LED1 = ~LED1;
  133.                         Flag_Calc_GPRMC_OK = 0;
  134.                         
  135.                         LCD12864_NoWaitIdle_COM_Write(0x80);                        //設置指針
  136.                         LCD12864_write_word("20");
  137.                         LCD12864_Data_Write(Year_High);
  138.                         LCD12864_Data_Write(Year_Low);
  139.                         LCD12864_write_word("年");
  140.         
  141.                         LCD12864_Data_Write(Month_High);
  142.                         LCD12864_Data_Write(Month_Low);
  143.                         LCD12864_write_word("月");
  144.         
  145.                         LCD12864_Data_Write(Day_High);
  146.                         LCD12864_Data_Write(Day_Low);
  147.                         LCD12864_write_word("日");
  148.                         
  149.                         
  150.                         LCD12864_NoWaitIdle_COM_Write(0x90);                        //設置指針
  151.                         LCD12864_write_word("速度:  ");                                //顯示內(nèi)容

  152.                         LCD12864_Data_Write(' ');
  153.                         LCD12864_Data_Write(Display_GPRMC_Buffer[46]);               
  154.                         LCD12864_Data_Write(Display_GPRMC_Buffer[47]);               
  155.                         LCD12864_Data_Write(Display_GPRMC_Buffer[48]);                        
  156.                         LCD12864_Data_Write(Display_GPRMC_Buffer[49]);        
  157.                         LCD12864_Data_Write(Display_GPRMC_Buffer[50]);
  158.                         
  159.                         LCD12864_write_word("米");
  160.                                                 
  161.                 }               
  162.         }
  163. }

  164. //****************************************************
  165. //UTC日期與當?shù)厝掌谵D(zhuǎn)換
  166. //****************************************************
  167. void UTCDate2LocalDate(void)
  168. {
  169.         Day = (Day_High - 0x30) * 10 + (Day_Low-0x30) + 1;                //日  加一
  170.         Month = (Month_High - 0x30) * 10 + (Month_Low - 0x30);
  171.         Year = 2000 + (Year_High - 0x30) * 10 + (Year_Low - 0x30);
  172.         
  173.         MaxDay = GetMaxDay(Month,Year);                                //獲取當月 天數(shù) 最大值
  174.         if(Day > MaxDay)                //溢出
  175.         {
  176.                 Day = 1;
  177.                 Month += 1;
  178.                 if(Month > 12)
  179.                 {
  180.                         Year+=1;
  181.                 }
  182.         }

  183.         Day_High = Day/10 + 0x30;                                //轉(zhuǎn)換日期值為ASCII
  184.         Day_Low = Day%10 + 0x30;

  185.         Month_High = Month/10 + 0x30;                        //轉(zhuǎn)換月份值為ASCII
  186.         Month_Low = Month%10 + 0x30;

  187.         Year_High = Year%100/10 + 0x30;                        //轉(zhuǎn)換年份值為ASCII
  188.         Year_Low = Year%10 + 0x30;                        
  189. }

  190. //****************************************************
  191. //獲取當月日期最大值
  192. //****************************************************
  193. unsigned char GetMaxDay(unsigned char Month_Value,unsigned int Year_Value)
  194. {
  195.         unsigned char iDays;
  196.         switch(Month_Value)
  197.         {
  198.                 case 1:
  199.                 case 3:
  200.                 case 5:
  201.                 case 7:
  202.                 case 8:
  203.                 case 10:
  204.                 case 12:
  205.                         {
  206.                                 iDays = 31;
  207.                         }
  208.                         break;
  209.                 case 2:
  210.                         {
  211.                                 //2月份比較特殊,需要根據(jù)是不是閏年來判斷當月是28天還29天
  212.                                 iDays = IsLeapYear(Year_Value)?29:28;
  213.                         }
  214.                         break;
  215.                 case 4:
  216.                 case 6:
  217.                 case 9:
  218.                 case 11:
  219.                         {
  220.                                 iDays = 30;
  221.                         }
  222.                         break;
  223.                 default : break;
  224.         }
  225.         return(iDays);                                                
  226. }

  227. //****************************************************
  228. //閏年檢測
  229. //****************************************************
  230. ……………………

  231. …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼


所有資料51hei提供下載:
51GPS信息獲取例程.zip (372.2 KB, 下載次數(shù): 277)


評分

參與人數(shù) 1黑幣 +100 收起 理由
admin + 100 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏12 分享淘帖 頂1 踩
回復

使用道具 舉報

沙發(fā)
ID:603958 發(fā)表于 2019-10-16 13:34 | 只看該作者
學習一下,
回復

使用道具 舉報

板凳
ID:484435 發(fā)表于 2019-10-16 14:10 | 只看該作者
謝謝分享,謝謝分享
回復

使用道具 舉報

地板
ID:37851 發(fā)表于 2019-10-16 16:20 | 只看該作者
不錯  前來學習
回復

使用道具 舉報

5#
ID:37851 發(fā)表于 2019-10-16 16:21 | 只看該作者
謝謝分享,謝謝分享
回復

使用道具 舉報

6#
ID:499701 發(fā)表于 2019-10-17 13:37 | 只看該作者
學習一下,謝謝分享
回復

使用道具 舉報

7#
ID:613618 發(fā)表于 2019-10-17 16:00 來自手機 | 只看該作者
寫得不錯
回復

使用道具 舉報

8#
ID:679011 發(fā)表于 2020-3-16 22:04 | 只看該作者
請問PPS是要接地嗎?
回復

使用道具 舉報

9#
ID:720122 發(fā)表于 2020-4-1 12:40 | 只看該作者
學習一下
回復

使用道具 舉報

10#
ID:716703 發(fā)表于 2020-4-1 14:47 | 只看該作者
不錯,謝謝分享
回復

使用道具 舉報

11#
ID:725775 發(fā)表于 2020-4-11 11:51 | 只看該作者
這個電路圖是怎樣連的?求解
回復

使用道具 舉報

12#
ID:258336 發(fā)表于 2020-4-27 13:49 | 只看該作者
葉瑞鳳 發(fā)表于 2020-3-16 22:04
請問PPS是要接地嗎?

pps是gps的秒脈沖輸出接口,用來校正本地晶振的誤差的,如果授時精度要求不是特別高的話這個接口就用不上。
回復

使用道具 舉報

13#
ID:258336 發(fā)表于 2020-4-27 13:54 | 只看該作者
噗哈哈 發(fā)表于 2020-4-11 11:51
這個電路圖是怎樣連的?求解

gps模塊的TXD接單片機的RXD,gps模塊的RXD接單片機的TXD。GPS模塊的供電可以接在單片機的開發(fā)板上也可以單獨供電。主要就這四根線。
回復

使用道具 舉報

14#
ID:79544 發(fā)表于 2020-5-5 09:50 | 只看該作者
感謝樓主分享,學習啦。。。
回復

使用道具 舉報

15#
ID:745627 發(fā)表于 2020-5-6 22:50 來自手機 | 只看該作者
師傅 幾個問題問一下:1、如果不需要顯示的話,程序刪除那些?2、經(jīng)緯度信息(其他不要)最后儲存在哪里?怎樣調(diào)用?先謝謝師傅了
回復

使用道具 舉報

16#
ID:751709 發(fā)表于 2020-5-14 15:34 | 只看該作者
我在做這個lcd顯示時總是出錯。。就連光標都出不來。特意找資料來看看
回復

使用道具 舉報

17#
ID:258336 發(fā)表于 2020-5-19 15:04 來自手機 | 只看該作者
1057544247 發(fā)表于 2020-5-6 22:50
師傅 幾個問題問一下:1、如果不需要顯示的話,程序刪除那些?2、經(jīng)緯度信息(其他不要)最后儲存在哪里? ...

1、需要刪除lcd的初始化,讀,寫等子程序。2、這個程序是實時的,經(jīng)緯度的數(shù)據(jù),每秒都會刷新。
回復

使用道具 舉報

18#
ID:258336 發(fā)表于 2020-5-19 15:06 來自手機 | 只看該作者
嗨過頭了有點累 發(fā)表于 2020-5-14 15:34
我在做這個lcd顯示時總是出錯。。就連光標都出不來。特意找資料來看看

這個你要好好的查一查硬件電路有沒有接錯,lcd的各個端口有沒有和程序里相對應
回復

使用道具 舉報

19#
ID:926023 發(fā)表于 2021-5-23 21:58 | 只看該作者
感謝樓主答疑解惑
回復

使用道具 舉報

20#
ID:1011393 發(fā)表于 2022-4-11 21:48 | 只看該作者
謝謝樓主分享!
我在STC15單片機上使用了你的程序,剛開始一直沒有反應,我以為程序還是有些小問題,后來過了幾分鐘突然發(fā)現(xiàn)它能夠準確顯示數(shù)據(jù)了!我便重新啟動,然后也還是過了很長一段時間才顯示,請問這個是什么原因呀?
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 亚洲欧洲av在线 | 日本一区二区三区视频在线 | 成人免费小视频 | 免费高潮视频95在线观看网站 | 91看片网 | 亚洲精品二区 | 夜夜骑首页 | 久久国产精品视频 | 免费特级黄毛片 | 狠狠撸在线视频 | 午夜影院在线观看 | 精品国产欧美一区二区 | 在线国产一区 | 日韩成人久久 | 国产在线播 | 日韩黄色小视频 | 99久久久久 | 亚洲一区二区免费 | 欧洲精品一区 | 亚洲精品乱码久久久久久按摩观 | 粉嫩一区二区三区国产精品 | 国产乱码精品一区二区三区五月婷 | 成人三级网址 | 欧美国产日韩在线观看 | 欧美日韩综合精品 | 日韩一区中文字幕 | 欧美日韩一区二区视频在线观看 | 久久久久国产精品一区二区 | 国产视频在线观看一区二区三区 | 玖玖视频 | 黄色一级片视频 | 成人综合伊人 | 国产精品美女久久久久久久久久久 | 毛片免费视频 | 人人射人人插 | 三级黄色片在线 | 精品小视频 | 欧美激情欧美激情在线五月 | 日韩黄色小视频 | 欧美成人精品欧美一级 | 欧美性乱 |