單片機(jī)+北斗模塊實(shí)現(xiàn)定位

本文原創(chuàng)淹辞,轉(zhuǎn)載請(qǐng)注明出處。小編可能以后不會(huì)在簡(jiǎn)書上更新了俘侠,因?yàn)檫@里的markdown 編輯器太不好用了象缀,沒(méi)有CSDN 上面的好用,也希望粉絲們多多關(guān)注本人CSDN(一樣的昵稱呦)爷速。點(diǎn)擊友方藍(lán)字即可瀏覽小編CSDN內(nèi)容 csdn

導(dǎo)航是繼移動(dòng)通信之后發(fā)展最快的信息產(chǎn)業(yè)之一央星,只要是設(shè)計(jì)到位置、速度惫东、時(shí)間信息的領(lǐng)域斗魚衛(wèi)星導(dǎo)航技術(shù)相關(guān)莉给。中國(guó)北斗衛(wèi)星導(dǎo)航系統(tǒng)是我國(guó)自主研制的全球?qū)Ш较到y(tǒng),是繼美國(guó)定位系統(tǒng)(GPS)廉沮、俄羅斯格洛納斯衛(wèi)星導(dǎo)航系統(tǒng)之后的第三個(gè)成熟的衛(wèi)星導(dǎo)航系統(tǒng)颓遏。隨著北斗導(dǎo)航系統(tǒng)的不斷完善,基于北斗導(dǎo)航系統(tǒng)的定位也應(yīng)用的越來(lái)越廣泛滞时。小編采用的STC12C5A32S2單片機(jī)結(jié)合衛(wèi)星接收模塊UM220-III設(shè)計(jì)的北斗導(dǎo)航系統(tǒng)接收機(jī)叁幢,UM220-III是三模接收模塊,能夠同時(shí)接受GPS坪稽、北斗的信號(hào)曼玩。這次的設(shè)計(jì)主要完成了導(dǎo)航信息接收機(jī)的基本設(shè)計(jì),實(shí)現(xiàn)了獲取實(shí)時(shí)的位置經(jīng)緯度窒百、標(biāo)準(zhǔn)時(shí)間等相關(guān)信息的顯示功能黍判。

1 原理介紹

采用以單片機(jī)為核心,讀取北斗導(dǎo)航系統(tǒng)模塊的標(biāo)準(zhǔn)數(shù)據(jù)篙梢,并在 LCD 屏幕上顯示當(dāng)前的經(jīng)緯度信息顷帖。具體的系統(tǒng)方案圖如下:


方案設(shè)計(jì).PNG

1.1北斗 UM220-III 模塊簡(jiǎn)介

(1)接口電路
北斗模塊芯片電路由北斗模塊UM220-III N 和其附加電子器件組成。其中北斗模塊外接4組排針,在芯片與電源之間串聯(lián)電感的作用是起差模濾波作用窟她,防止電流突變對(duì)芯片產(chǎn)生損壞陈症,并聯(lián)電感的作用是提高芯片運(yùn)行的穩(wěn)定性,防止產(chǎn)生噪聲震糖。
模塊輸入端口(UM220-III N 包括:RXD录肯、GPIO、SDA 吊说,SCL 等 如下圖)為防止輸入端不定態(tài)對(duì)模塊造成影響论咏,模塊內(nèi)置上拉電阻至VCC,因此在模塊未加電時(shí)颁井,如果上述端口有數(shù)據(jù)輸入厅贪,會(huì)在模塊VCC上形成串電,又可能造成模塊上電失敗雅宾。


內(nèi)置電路圖.PNG

case1:設(shè)計(jì)中使用 nRESET功能
在模塊上電后养涮,將nRESET拉低5 ms以上,即可確保模塊正常啟動(dòng)眉抬。
case2:設(shè)計(jì)中未使用nRESET
在模塊上電之前贯吓,保證模塊已連接輸入端口為高阻態(tài)或低電平,以避免串電蜀变。使用串口1的典型用戶悄谐,需要吧RXD1設(shè)置為高阻態(tài)或低電平,未使用的其他PIN懸空库北。程序流程圖如下:


流程圖.PNG

(2)LCD 液晶顯示器
LCD液晶顯示器數(shù)據(jù)由單片機(jī)p0口進(jìn)行控制爬舰,p2口進(jìn)行指令控制操作。LCD1602是一種專門用來(lái)顯示字母寒瓦,數(shù)字情屹,符號(hào)等的點(diǎn)陣型液晶模塊。1602:顯示的內(nèi)容主要是16*2孵构,即可以顯示兩行屁商,每行16個(gè)字符液晶顯示模塊。相應(yīng)的管教功能颈墅,百度上都是可以查閱的蜡镶,所以小編這里就不贅述了。
(3)UM220-III 通信協(xié)議簡(jiǎn)介

在Unicore 協(xié)議中恤筛,輸入和輸出的語(yǔ)句被稱為消息官还。每條消息均為ASCII 字符組成的字符串。
消息的基本格式為:GNAME,data1,data2,data3,……[*cc]\r\n 所有的消息都以 ''(0x24)開始毒坛,后面緊跟著的就是消息名望伦。之后的跟的就是不定數(shù)目的參數(shù)和數(shù)據(jù)林说。消息名與數(shù)據(jù)之間均以逗號(hào)隔開(0x2c)進(jìn)行分割。最后一個(gè)參數(shù)是可選的校驗(yàn)和屯伞,以 '*'(0x2A)與前面的數(shù)據(jù)分割最后腿箩,輸入的消息以 ' \r\n' 結(jié)束。每條消息的總長(zhǎng)度不超過(guò)256個(gè)字節(jié)劣摇,消息名和參數(shù)珠移,校驗(yàn)和中的字母不區(qū)分大小寫。
某些輸入命令的某些參數(shù)可以省略(在命令描述中被標(biāo)記為可選)末融。這些參數(shù)可以為空钧惧,即在兩個(gè)逗號(hào)之間沒(méi)有任何字符。

設(shè)定串口配置.PNG

2 調(diào)試方法

由1.1的原理簡(jiǎn)介可知勾习,此次課題實(shí)現(xiàn)主要由 5 部分組成:系統(tǒng)初始化浓瞪、設(shè)定顯示模式、讀取預(yù)顯示內(nèi)容巧婶、送掃描脈沖乾颁、送顯示數(shù)據(jù)。
這里對(duì)單片機(jī)與模塊的連接做簡(jiǎn)要說(shuō)明艺栈。
UM220/um220-3-n 上帶有兩組 TTL 電平(2.85V)钮孵,一組標(biāo)準(zhǔn)電平 RS232電平。當(dāng)單片機(jī)的RS232電平接口接到UM220模塊上的RS232上眼滤,正常通信。UM220模塊上的RS232接口是DB9 母頭历涝,可以使用公頭的連接線與RS230的接口相連诅需,注意的是通信線需要交叉連接,就像TTL電平中的TXD - - RXD,RXD--TXD 一樣荧库,RS232電平通信中也是有2根通信電纜堰塌,一個(gè)是發(fā)送端(PCXD),一個(gè)是接收端(PCRXD)分衫。若板子上的RS232 的接口是DB9 母頭场刑,那么 2 3針就是 PCRXD 和 PCTXD .第五針就是GND,若沒(méi)有串口線來(lái)連接UM220模塊的話蚪战,可以考慮在DB9下面的2 3 5 針 焊接出3跟線跟單片機(jī)的RS232連接牵现。
若單片機(jī)是3.3V時(shí),可以將單片機(jī)的TTL 接口連接到模塊上的TTL接口邀桑。連接好后就可以編寫程序了瞎疼。
注意,我們使用的 52 單片機(jī)的驅(qū)動(dòng)程序壁畸,使用的是12mhz的晶振贼急,波特率為9600.

3 程序編寫

程序主要是由5部分組成:系統(tǒng)初始化茅茂,設(shè)定顯示模式。讀取預(yù)顯示內(nèi)容太抓,送掃描脈沖空闲,送顯示數(shù)據(jù)。小編只放主程序部分好了:

3.1 定義端口及變量
#include <REG52.H>
#include <stdio.h>
#include <intrins.h>
#include <lcd1602.h>
#include <uart.h>
#include <delay.h>
#include "string.h"
#include <stdlib.h>

unsigned char  flag_rec=0;    //接收數(shù)據(jù)標(biāo)志
unsigned char num_rec=0;      // 計(jì)數(shù)標(biāo)志      
//char code TIME_AREA= 8;       //時(shí)區(qū)走敌,我們不需要它
unsigned char flag_data;    //數(shù)據(jù)緩沖器
//only displaty cmd $GPGGA information
unsigned char JD[16];       //longitude
unsigned char JD_a;     //經(jīng)度方向
unsigned char WD[15];       //latitude
unsigned char WD_a;     // 緯度方向
unsigned char date[6];      //data
unsigned char time[6];      //data
unsigned char time1[6];     //data
unsigned char speed[5]={'0','0','0','0','0'};       // 速度
unsigned char high[6];      // 高度
unsigned char angle[5];     //方位角
unsigned char use_sat[2];   // 衛(wèi)星計(jì)數(shù)器
unsigned char total_sat[2]; //衛(wèi)星總數(shù)
unsigned char lock;         //位置狀態(tài)

//date handing variable
unsigned char seg_count;    // 逗號(hào)計(jì)數(shù)器
unsigned char dot_count;    //小數(shù)點(diǎn)計(jì)數(shù)器
unsigned char byte_count;   // 位計(jì)數(shù)器
unsigned char cmd_number;   // 命令模式
unsigned char mode;         
unsigned char buf_full;     
unsigned char cmd[5];       // 存儲(chǔ)命令模式

//serial disconnect timer
unsigned  long int tt=0;
主函數(shù) 系統(tǒng)初始化
//main
void main () 
{   
  int jd_second,wd_second;  // 中間變量
    init_uart();         //初始化序列號(hào)
  lcd_init() ;       // 初始化 lcd1602
  delay(200);
  LCD_Write_String(0,0,"Please Waiting...");   //    "Please Waiting" when it is boot up
  delay(200);
  delay(200);
  delay(200);
  delay(200);
  delay(200);
  delay(200);
  delay(200);
  delay(200);
  delay(200);
  delay(200);                             // 延遲顯示
  write_com(0x01);          // 清屏

設(shè)置延時(shí)函數(shù),以形成視覺(jué)暫留

while(1)
{
tt++;
if(tt>10000)
  {
    tt=10000;
    write_com(0x01);
    LCD_Write_String(3,0,"No Data!");
    LCD_Write_String(3,1,"No Data!");
    delay(200);
    delay(200);
    delay(200);
    delay(200);
    delay(200);
   }

···

讀取預(yù)顯示內(nèi)容碴倾,設(shè)置顯示模式,轉(zhuǎn)16進(jìn)制為10進(jìn)制
 if(flag_rec==1)             // 獲取gps數(shù)據(jù)
  {
    flag_rec=0;               // 清除標(biāo)志符
    if (lock==1)              //  獲取位置信息
        {  
      //
      LCD_Write_String(0,0,"JD  :");    // 顯示經(jīng)度
      LCD_Write_String(6,0,JD);           // 顯示數(shù)據(jù)
      LCD_Write_String(9,0,".");           // 進(jìn)制轉(zhuǎn)換
      LCD_Write_String(10,0,JD+3);           
      jd_second=60*atof((char *)(JD+5));     
      LCD_Write_Char(13,0,jd_second/10+'0');  // 將上一步轉(zhuǎn)換得到浮點(diǎn)數(shù)據(jù)打印在lcd
      LCD_Write_Char(14,0,jd_second%10+'0');  // 將上面得到的數(shù)據(jù)分為兩部分悔常,分別打印在LCD 上
      LCD_Write_Char(15,0,' ');                //填充空間

      delay(200);                         // 保護(hù)lcd
      LCD_Write_String(0,1,"WD  :");     // 顯示下一行
      LCD_Write_String(6,1,WD);
      LCD_Write_String(8,1,"."); 
      LCD_Write_String(9,1,WD+2);           // 小數(shù)點(diǎn)
      wd_second=60*atof((char *)(WD+4));// 將字符串轉(zhuǎn)換成浮點(diǎn)數(shù)
      LCD_Write_Char(12,1,wd_second/10+'0');
      LCD_Write_Char(13,1,wd_second%10+'0');
      LCD_Write_String(14,1,"  ");
      delay(200);
   }
  }
 }
    }

串口中斷函數(shù)及模式判斷

判斷的主要依據(jù)就是接收端接受消息與預(yù)結(jié)果匹配影斑,通過(guò)設(shè)置數(shù)組[i,j]和if函數(shù)進(jìn)行判斷匹配(發(fā)送報(bào)文的消息內(nèi)容見(jiàn)1.3的UM220的通信協(xié)議詳解)


       //serial interruupt service function
       void ser_int (void) interrupt 4
      {
    unsigned char tmp;
    if(RI)
    {
    tt=0;
        RI=0;
        tmp=SBUF;            // 從緩沖區(qū)接收數(shù)據(jù)
        switch(tmp)   //if $GPGGA,$GNGSW,$GNRMC,get data then processing it
        {
      //date start with $
            case '$':
                cmd_number=0;       // 清除命令模式
                mode=1;             // 選項(xiàng)命令接收模式
                byte_count=0;       //清除位計(jì)數(shù)器
                flag_data=1;     // 設(shè)置數(shù)據(jù)標(biāo)志
                flag_rec=1;     // 設(shè)置數(shù)據(jù)接收標(biāo)志
            break;

            case ',':         //Eg:$GNRMC,134645.000,A,2603.964436,N,11912.410232,E,0.000,15.744,030718,,E,A*0B
                seg_count++;        // 計(jì)數(shù)器增加
                byte_count=0;
                break;

            case '*':
                switch(cmd_number)
                {
                    case 1:
                        buf_full|=0x01;   //00000001
                        break;
                    case 2:
                        buf_full|=0x02;  //00000010
                        break;
                    case 3:
                        buf_full|=0x04;  //00000100
                        break;
                }

                mode=0;         //clear mode
                break;
            default:

                   // 接受數(shù)據(jù)
                if(mode==1) 
                {
                    cmd[byte_count]=tmp;    // 獲取數(shù)據(jù)和存儲(chǔ)緩沖區(qū)   
                        if(byte_count>=4)                                                   
                    {           
                        if(cmd[0]=='G')           // 第一個(gè)字符
                        {
                            if(cmd[1]=='N')
                            {
                                if(cmd[2]=='G')
                                {
                                    if(cmd[3]=='G')
                                    {
                                        if(cmd[4]=='A')//判斷$GNGGA
                                        {
                                            cmd_number=1;      //數(shù)據(jù)類型
                                            mode=2;            //接收日期
                                            seg_count=0;       //逗號(hào)計(jì)數(shù)器置0
                                            byte_count=0;      //位計(jì)數(shù)器清除
                                        }
                                    }
                                    else if(cmd[3]=='S')       //命令模式$GNGSV
                                    {
                                        if(cmd[4]=='V')
                                        {
                                            cmd_number=2;
                                            mode=2;                //獲取數(shù)據(jù)
                                            seg_count=0;
                                            byte_count=0;
                                        }
                                    }
                                }
                                else if(cmd[2]=='R')   //命令模式 $GNRMC
                                {
                                    if(cmd[3]=='M')
                                    {
                                        if(cmd[4]=='C')
                                        {
                                            cmd_number=3;
                                            mode=2;         //存儲(chǔ)數(shù)據(jù)
                                            seg_count=0;
                                            byte_count=0;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                               //日期處理
                else if(mode==2)
                {
                    
                    switch (cmd_number)  //if receive data
                    {
                        case 1:             //get and store data,$GPGGA,[],[],[],[],[],[],[],[],[].....
                            switch(seg_count)   //  comma 計(jì)數(shù)器
                            {
                                case 2:     // 2rd逗號(hào)后的緯度
                                    if(byte_count<9)
                                    {
                                        WD[byte_count]=tmp;   //獲取緯度
                                    }
                                    break;
                                case 3:     //緯度方向
                                    if(byte_count<1)
                                    {
                                        WD_a=tmp;
                                    }
                                    break;
                                case 4:     //經(jīng)度
                                    if(byte_count<10)
                                    {
                                        JD[byte_count]=tmp; //存儲(chǔ)
                                    }
                                    break;
                                case 5:     //經(jīng)度方向
                                    if(byte_count<1)
                                    {
                                        JD_a=tmp;
                                    }
                                    break;
                                case 6:     //location
                                    if(byte_count<1)
                                    {
                                        lock=tmp;
                                    }
                                    break;
                                case 7:     
                                    if(byte_count<2)
                                    {
                                        use_sat[byte_count]=tmp;
                                    }
                                    break;
                                case 9:     // 高度
                                    if(byte_count<6)
                                    {
                                        high[byte_count]=tmp;
                                    }
                                    break;
                            }
                            break;


                        case 2: //命令模式  $GPGSV
                            switch(seg_count)
                            {
                                case 3:     // 衛(wèi)星總數(shù)
                                    if(byte_count<2)
                                    {
                                        total_sat[byte_count]=tmp;
                                    }
                                    break;
                            }
                            break;


                                             //命令模式3:無(wú)SUE
                        case 3:             //$GPRMC
                            switch(seg_count)
                            {
                                case 1:     //time
                                    if(byte_count<6)
                                    {               
                                        time[byte_count]=tmp;   
                                    }
                                    break;
                                case 2:     // 位置           
                                    if(byte_count<1)
                                    {
                                      if (tmp=='V') {lock=0;}
                                      else
                                      {
                                        lock=1;
                                       }
                                    }
                                    break;
                                case 3:     //lititude          
                                    if(byte_count<9)
                                    {
                                        WD[byte_count]=tmp;//我們只需要一次
                                    }
                                    break;
                                case 4:                         
                                    if(byte_count<1)
                                    {
                                        WD_a=tmp;
                                    }
                                    break;
                                case 5:     //          
                                    if(byte_count<10)
                                    {
                                        JD[byte_count]=tmp;  //do not get again
                                    }
                                    break;
                                case 6:     // 直線方向 
                                    if(byte_count<1)
                                    {
                                        JD_a=tmp;
                                    }
                                    break;
                                case 7:     // 速度處理     
                                    if(byte_count<5)
                                    {
                                        speed[byte_count]=tmp;
                                    }
                                    break;
                                case 8:     // 方向角              
                                    if(byte_count<5)
                                    {
                                        angle[byte_count]=tmp;
                                    }
                                    break;
                                case 9:     //other         
                                    if(byte_count<6)
                                    {
                                        date[byte_count]=tmp;
                                    }
                                    break;

>                           }
                            break;
                    }
                }
                byte_count++;       // 位計(jì)數(shù)器++
                break;
        }
    }

4 結(jié)果顯示

1.PNG

IMG_20190630_091924.jpg

IMG_20190630_103508.jpg
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市机打,隨后出現(xiàn)的幾起案子矫户,更是在濱河造成了極大的恐慌,老刑警劉巖残邀,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件皆辽,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡芥挣,警方通過(guò)查閱死者的電腦和手機(jī)驱闷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)空免,“玉大人空另,你說(shuō)我怎么就攤上這事√Q猓” “怎么了扼菠?”我有些...
    開封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)坝咐。 經(jīng)常有香客問(wèn)我循榆,道長(zhǎng),這世上最難降的妖魔是什么墨坚? 我笑而不...
    開封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任秧饮,我火速辦了婚禮,結(jié)果婚禮上泽篮,老公的妹妹穿的比我還像新娘盗尸。我一直安慰自己,他們只是感情好咪辱,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開白布振劳。 她就那樣靜靜地躺著,像睡著了一般油狂。 火紅的嫁衣襯著肌膚如雪历恐。 梳的紋絲不亂的頭發(fā)上寸癌,一...
    開封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音弱贼,去河邊找鬼蒸苇。 笑死,一個(gè)胖子當(dāng)著我的面吹牛吮旅,可吹牛的內(nèi)容都是我干的溪烤。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼庇勃,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼檬嘀!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起责嚷,我...
    開封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤鸳兽,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后罕拂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體揍异,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年爆班,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了衷掷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡柿菩,死狀恐怖戚嗅,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情枢舶,我是刑警寧澤渡处,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站祟辟,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏侣肄。R本人自食惡果不足惜旧困,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望稼锅。 院中可真熱鬧吼具,春花似錦、人聲如沸矩距。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)锥债。三九已至陡蝇,卻和暖如春痊臭,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背登夫。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工广匙, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人恼策。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓鸦致,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親涣楷。 傳聞我的和親對(duì)象是個(gè)殘疾皇子分唾,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354