51单片机解析卫星定位数据源码+DHT11,1602显示

什么都不多说,直接看代码:

    #include <REG52.H>
    #include <stdio.h>
    #include <intrins.h>
    ////////////========================================================================================

    /*
    1602A(16*2)模拟口线接线方式
    连接线图:   
           ---------------------------------------------------
           |LCM-----51   |  LCM-----51   |  LCM------51      |
           --------------------------------------------------|
           |DB0-----P0.0 |  DB4-----P0.4 |  RW-------P1.5    |
           |DB1-----P0.1 |  DB5-----P0.5 |  RS-------P1.4    |
           |DB2-----P0.2 |  DB6-----P0.6 |  E--------P1.6    |
           |DB3-----P0.3 |  DB7-----P0.7 |  V0接10K电阻到GND |
           ---------------------------------------------------
    温湿度DHT11接线:模块data接   P3^2
    ******************/
    sbit Data= P3^2;   //定义数据线      温湿度传感器DHT11数据接入
    unsigned char rec_dat[9];   //用于显示的接收数据数组  

    unsigned char  flag_rec=0;     
    unsigned char  num_rec=0;

    unsigned char code kaijihuamian[]="BeiDou_DHT11";    //开机显示
    unsigned char code kaijihuamian2[]="AnShan_17-12-01";
    unsigned char code receiving[]="Receiving!";
    unsigned char code nodata[]="No BD data!";
    unsigned char code LCD_161[]="BD_HeGuang Studios";
    unsigned char code LCD_162[]="TEL:15117255049";

    char code TIME_AREA= 8;     //时区
    unsigned char flag_data;    //数据标志位

    //BD数据存储数组
    unsigned char JD[10];       //经度
    unsigned char JD_a;     //经度方向
    unsigned char WD[9];        //纬度
    unsigned char WD_a;     //纬度方向
    unsigned char date[6];      //日期
    unsigned char time[6];      //时间
    unsigned char time1[6];     //时间
    unsigned char speed[5]={'0','0','0','0','0'};       //速度
    unsigned char high[6];      //高度
    unsigned char angle[5];     //方位角
    unsigned char use_sat[2];   //使用的卫星数
    unsigned char total_sat[2]; //天空中总卫星数
    unsigned char lock;         //定位状态

    //串口中断需要的变量
    unsigned char seg_count;    //逗号计数器
    unsigned char dot_count;    //小数点计数器
    unsigned char byte_count;   //位数计数器
    unsigned char cmd_number;   //命令类型
    unsigned char mode;         //0:结束模式,1:命令模式,2:数据模式
    unsigned char buf_full;     //1:整句接收完成,相应数据有效。0:缓存数据无效。
    unsigned char cmd[5];       //命令类型存储数组

    sbit rs = P1^4;
    sbit rw = P1^5;
    sbit ep = P1^6;

    //-----------------------------------------------------------------------------------------------
    //延时子程序
    void delayms(unsigned char ms)
    {
        unsigned char i;
        while(ms--)
        {
        for(i = 0; i < 120; i++);
        }
    }


    bit lcd_bz(void)
    {                           // 测试LCD忙碌状态
        bit result;
        rs = 0;
        rw = 1;
        ep = 1;
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        result = (bit)(P0 & 0x80);
        ep = 0;
        return result;  
    }

    void lcd_wcmd(unsigned char cmd)
    {                           // 写入指令数据到LCD
        while(lcd_bz());
        rs = 0;
        rw = 0;
        ep = 0;
        _nop_();
        _nop_();    
        P0 = cmd;
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        ep = 1;
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        ep = 0;     
    }

    void lcd_pos(unsigned char pos)
    {                           //设定显示位置
        lcd_wcmd(pos | 0x80);
    }

    void lcd_pos_2(unsigned char pos)
    {                           //设定显示位置
        lcd_wcmd(pos | 0xC0);
    }

    void lcd_wdat(unsigned char dat)    
    {                           //写入字符显示数据到LCD
        while(lcd_bz());
        rs = 1;
        rw = 0;
        ep = 0;
        P0 = dat;
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        ep = 1;
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        ep = 0; 
    }
    void lcd_string(unsigned char *ptr,unsigned char pos)
    {

        unsigned char i;
        lcd_pos(pos);
        while(*(ptr+i) != '\0')
        {                       // 显示字符"welcome!"
            lcd_wdat(*(ptr+i));
            i++;
        }       

    }

    lcd_init()
    {                           //LCD初始化设定
        lcd_wcmd(0x38);         //
        delayms(1);
        lcd_wcmd(0x0c);         //
        delayms(1);
        lcd_wcmd(0x06);         //
        delayms(1);
        lcd_wcmd(0x01);         //清除LCD的显示内容
        delayms(1);
    }
    //-----------------------------------------------------------------------------------------------
    //延时子程序
    void delaym(unsigned int ms)
    {
        unsigned int i,j;
        for(i = 0;i < ms ;i++)
        {
            for(j = 0;j < 125 ;j++)
                ;
        }
    }

    void DHT11_delay_us(unsigned char n)
    {
        while(--n);
    }

    void DHT11_delay_ms(unsigned int z)
    {
       unsigned int i,j;
       for(i=z;i>0;i--)
          for(j=110;j>0;j--);
    }

    void DHT11_start()
    {
       Data=1;
       DHT11_delay_us(2);
       Data=0;
       DHT11_delay_ms(20);   //延时18ms以上
       Data=1;
       DHT11_delay_us(30);
    }
    //-----------------------   温湿度读取   -----------------------------------

    unsigned char DHT11_rec_byte()      //接收一个字节
    {
       unsigned char i,dat=0;
      for(i=0;i<8;i++)    //从高到低依次接收8位数据
       {          
          while(!Data);   ////等待50us低电平过去
          DHT11_delay_us(8);     //延时60us,如果还为高则数据为1,否则为0 
          dat<<=1;           //移位使正确接收8位数据,数据为0时直接移位
          if(Data==1)    //数据为1时,使dat加1来接收数据1
             dat+=1;
          while(Data);  //等待数据线拉低    
        }  
        return dat;
    }

    void DHT11_receive()      //接收40位的数据
    {
        unsigned char R_H,R_L,T_H,T_L,RH,RL,TH,TL,revise; 
        DHT11_start();
        if(Data==0)
        {
            while(Data==0);   //等待拉高     
            DHT11_delay_us(40);  //拉高后延时80us
            R_H=DHT11_rec_byte();    //接收湿度高八位  
            R_L=DHT11_rec_byte();    //接收湿度低八位  
            T_H=DHT11_rec_byte();    //接收温度高八位  
            T_L=DHT11_rec_byte();    //接收温度低八位
            revise=DHT11_rec_byte(); //接收校正位

            DHT11_delay_us(25);    //结束

            if((R_H+R_L+T_H+T_L)==revise)      //校正
            {
                RH=R_H;
                RL=R_L;
                TH=T_H;
                TL=T_L;
            } 
            /*数据处理,方便显示*/
            rec_dat[0]='0'+(RH/10);
            rec_dat[1]='0'+(RH%10);
            rec_dat[2]='R';
            rec_dat[3]='H';
            rec_dat[4]=' ';
            rec_dat[5]=' ';
            rec_dat[6]='0'+(TH/10);
            rec_dat[7]='0'+(TH%10);
            rec_dat[8]='C';
        }
    }

    //-------------------------   <初始化设置 结束>   -------------------------------------
    void DHT11_main(unsigned int zxi){      
        lcd_init();            //初始化1602
        lcd_wcmd(0x01);     //清除LCD的显示内容
        delaym(1);
        //============温湿度读取============================================================
        DHT11_delay_ms(1500);    //DHT11上电后要等待1S以越过不稳定状态在此期间不能发送任何指令
      DHT11_receive();  
        lcd_pos(3);         // 设置显示位置
        for(zxi = 0;zxi<6;zxi++)
        {
            lcd_wdat(kaijihuamian[zxi+6]);  // 显示字符dht11
        }
        zxi = 0;
        delayms(100);
        lcd_pos_2(2);              
        while(rec_dat[zxi] != '\0'){
            lcd_wdat(rec_dat[zxi]); //显示
            zxi++;
        }
        delaym(1000);               
    }
    //==================================================================================
    //发送字节
    void sendbyte(unsigned char ptr)
    {
        SBUF=ptr;
        while(TI==0);
        TI=0;
    }
    //---------------------------------------------------------------------------
    //发送数据流
    void sendstring(unsigned char *ptr,unsigned char len)
    {

        int i=0;
        while(i<len)
        {   
            SBUF=*(ptr+i);               //SUBF接受/发送缓冲器
            while(TI==0);
            TI=0;
            i++;    
        }
        num_rec=0;  

    }
    void init_all(void) //9600  11.05926
    {

        SCON = 0x50;      //REN=1允许串行接受状态,串口工作模式1                  
        TMOD|= 0x20;      //定时器工作方式2                    
        PCON|= 0x80;                                                          
        TH1 = 0xFa;     //baud*2  /* reload value 9600、数据位8、停止位1。效验位无 (11.0592)             
      TL1 = 0xF3;         
        TR1  = 1;                                                             
        ES   = 1;        //开串口中断                  
        EA   = 1;        // 开总中断
        lcd_init() ;

    } 
    //将UTC时间转成BJ时间
    void trans_time(void)
    {
        unsigned char temp,hour_shi,hour_ge;
        temp=(time[0]-'0')*10+(time[1]-'0');
        if(temp<=16)
        {
            temp=temp+8;
            hour_shi=temp/10;
            hour_ge=temp%10;
            time[0]=hour_shi+'0';
            time[1]=hour_ge+'0';    
        }
        else
        {
            temp=temp+8-24;
            time[0]='0';
            time[1]=temp%10+'0';    
        }
    } 
    //判断是否有BD数据 有1,无0
    bit BD_data(void)
    {
        if(buf_full&0x01!=0)
            return 1;
        else 
            return 0;   
    }
    //----------------------------------------------------------------------------
    void main () 
    {   
        unsigned int X;
        unsigned char i;
        init_all(); 
        lcd_wcmd(0x01);         //清除LCD的显示内容
        delayms(10);
        i = 0;
        X = 0;
        lcd_pos(1);         // 设置显示位置
        while(kaijihuamian[i] != '\0')
        {
            lcd_wdat(kaijihuamian[i]);  // 显示字符时间
            i++;
        }
        delayms(10);
        i=0  ;
        lcd_pos_2(0);           // 设置显示位置
        while(kaijihuamian2[i] != '\0')
        {
            lcd_wdat(kaijihuamian2[i]); // 显示字符时间
            i++;
        }
        i = 0;
        delayms(5000);
        lcd_wcmd(0x01);         //清除LCD的显示内容
        delayms(10);
        while(1)
        {
            if(flag_data==0)// 如果没有数据
            {
                lcd_wcmd(0x01);         //清除LCD的显示内容
                delayms(10);
                i=0  ;
                lcd_pos(2);         // 设置显示位置
                while(nodata[i] != '\0')
                {
                    lcd_wdat(nodata[i]);    // 显示字符
                    i++;
                }
                delayms(1000);
                lcd_wcmd(0x01);         //清除LCD的显示内容
                delayms(10);    
                //第三页开始==================================================================
                DHT11_main(i);// 显示字符DHT11 温度 湿度 信息
                delaym(3000);
                i = 0;
                lcd_wcmd(0x01);         
                delaym(1);
                //第四页开始==================================================================
                lcd_pos(0);         // 设置显示位置
                while(LCD_161[i] != '\0'){
                    lcd_wdat(LCD_161[i]);   // 显示字符禾灮信息
                    i++;
                }
                delayms(1);
                i=0  ;
                lcd_pos_2(0);           // 设置显示位置
                while(LCD_162[i] != '\0'){
                    lcd_wdat(LCD_162[i]);   // 显示字符禾灮信息
                    i++;
                }   
                //结束==================================================================
                delayms(5000);
                lcd_wcmd(0x01);         //清除LCD的显示内容
                delayms(1);
            }
            if(flag_rec==1)             //data 解码完毕
            {
                flag_rec=0;  //清数据有效标志位         
                if (lock==1) //如果已经定位
                {

                    for(X;X <10;X++){           
                        trans_time();//UTC--BJ TIME转换为北京时间                      
                        lcd_pos_2(0);           // 设置显示位置     
                        lcd_wdat(' ');         //显示 北京时间        
                        lcd_wdat(time[5]);  
                    }
                        delayms(1);          //第一页显示完毕======经纬度+北京时间====定位+授时
                        lcd_wcmd(0x01);         //清除LCD的显示内容
                        delayms(1);
                        X = 0;
                    for(X;X <10;X++){
                        //第二页开始=================================================================================
                        lcd_pos(0);         // 设置显示位置
                        lcd_wdat('H');              // 显示海拔 卫星个数
                        delayms(100);
                        lcd_pos(1);            
                        while(high[i] != '\0'){
                            lcd_wdat(high[i]);  //显示海拔
                            i++;
                        }
                        delayms(100);
                        while(use_sat[i] != '\0'){
                            lcd_wdat(use_sat[i]);   // // 显示 卫星个数
                            i++;
                        }
                        delayms(100);
                        i=0  ;  

                        //delayms(5000);         //第二页显示完毕======显示海拔+卫星个数===速度+方位
                        //lcd_wcmd(0x01);           //清除LCD的内容

                        while(angle[i] != '\0'){
                            lcd_wdat(angle[i]); // // 显示 方位角    
                            i++;
                        }
                        i=0  ;  
                    }
                    delayms(10);         //第二页显示完毕======显示海拔+卫星个数===速度+方位
                    lcd_wcmd(0x01);         //清除LCD的显示内容
                    delayms(1);
                    X = 0;

                    //第三页开始==================================================================
                    DHT11_main(i);// 显示字符DHT11 温度 湿度 信息
                    delaym(3000);
                    i = 0;
                    lcd_wcmd(0x01);         
                    delaym(1);
                    //第四页开始==================================================================
                    lcd_pos(0);         // 设置显示位置
                    while(LCD_161[i] != '\0'){
                        lcd_wdat(LCD_161[i]);   // 显示字符禾灮信息
                        i++;
                    }
                    delayms(1);
                    i=0  ;
                    lcd_pos_2(0);           // 设置显示位置
                    while(LCD_162[i] != '\0'){
                        lcd_wdat(LCD_162[i]);   // 显示字符禾灮信息
                        i++;
                    }   
                    //结束==================================================================
                    delayms(5000);

                    delayms(1);         //显示完毕======显示禾灮信息
                    lcd_wcmd(0x01);         //清除LCD的显示内容
                    delayms(1); 
                }
                else if(lock==0)
                {      //未定位    //display relative message              
                    lcd_wcmd(0x01);         //清除LCD的显示内容
                    delayms(10);
                    i=0  ;
                    lcd_pos(3);         // 设置显示位置
                    while(receiving[i] != '\0')
                    {
                        lcd_wdat(receiving[i]); // 显示字符时间
                        i++;
                    }
                    delaym(1000);
                    lcd_wcmd(0x01);         //清除LCD的显示内容
                    delaym(10);                 
                    X = 0;
                    //第三页开始==================================================================
                    DHT11_main(i);// 显示字符DHT11 温度 湿度 信息
                    delaym(3000);
                    i = 0;
                    lcd_wcmd(0x01);         
                    delaym(1);
                    //第四页开始==================================================================
                    lcd_pos(0);         // 设置显示位置
                    while(LCD_161[i] != '\0'){
                        lcd_wdat(LCD_161[i]);   // 显示字符禾灮信息
                        i++;
                    }
                    delayms(1);
                    i=0  ;
                    lcd_pos_2(0);           // 设置显示位置
                    while(LCD_162[i] != '\0'){
                        lcd_wdat(LCD_162[i]);   // 显示字符禾灮信息
                        i++;
                    }   
                    //结束==================================================================
                    delayms(5000);
                    delayms(1);                         
                }                   
            }           
        }
    }

    //--------------------------------------------------------------------
    //串口中断程序
    void ser_int (void) interrupt 4 using 1
    {

        unsigned char tmp;
        if(RI)
        {
            RI=0;
            tmp=SBUF;
            switch(tmp)
            {
                case '$':
                    cmd_number=0;       //命令类型清空
                    mode=1;             //接收命令模式
                    byte_count=0;       //接收位数清空
                    flag_data=1;
                    flag_rec=1;     //数据标志位置一
                    break;
                case ',':
                    seg_count++;        //逗号计数加1
                    byte_count=0;
                    break;
                case '*':
                    switch(cmd_number)
                    {
                        case 1:
                            buf_full|=0x01;
                            break;
                        case 2:
                            buf_full|=0x02;
                            break;
                        case 3:
                            buf_full|=0x04;
                            break;
                    }
                    mode=0;
                    break;
                default:
                    if(mode==1) //命令种类判断
                    {
                        cmd[byte_count]=tmp;            //接收字符放入类型缓存
                        if(byte_count>=4)
                        {               //如果类型数据接收完毕,判断类型
                            if(cmd[0]=='G')
                            {
                                if(cmd[1]=='N')
                                {
                                    if(cmd[2]=='G')
                                    {
                                        if(cmd[3]=='G')
                                        {
                                            if(cmd[4]=='A')
                                            {
                                                cmd_number=1;      //data type
                                                mode=2;
                                                seg_count=0;
                                                byte_count=0;
                                            }
                                        }
                                        else if(cmd[3]=='S')
                                        {
                                            if(cmd[4]=='V')
                                            {
                                                cmd_number=2;
                                                mode=2;
                                                seg_count=0;
                                                byte_count=0;
                                            }
                                        }
                                    }

                        switch (cmd_number)
                        {
                            case 1:             //类型1数据接收。GNGGA————北斗与GPS组合数据   
                                switch(seg_count)
                                {
                                    case 2:     //纬度处理
                                        if(byte_count<9)
                                        {
                                            WD[byte_count]=tmp;
                                        }
                                        break;
                                    case 3:     //纬度方向处理
                                        if(byte_count<1)
                                        {
                                            WD_a=tmp;
                                        }
                                        break;
                                    case 4:     //经度处理
                                        if(byte_count<10)
                                        {
                                            JD[byte_count]=tmp;
                                        }
                                        break;
                                    case 5:     //经度方向处理
                                        if(byte_count<1)
                                        {
                                            JD_a=tmp;
                                        }
                                        break;
                                    case 6:     //定位判断
                                        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;                          
                    }
                    byte_count++;       //接收数位加1
                    break;
            }
        }       
    }

相关测试结果:

测试视频地址:点击进入


    感谢一直关注着禾灮成长进步的朋友们。你们的信任、支持和鼓励,鞭策着我们一路走到了今天。

    感谢所有的合作伙伴,我们相互促进,共同见证了彼此的成长。

    感谢所有曾经在禾灮彼此倚靠、相互鼓励、携手同心、砥砺同行的兄弟姐妹。这里承载了我们的青春与热血。

                禾灮,感谢有你。

    未来,我们将一如既往,砥砺前行。

                                        禾灮·小楊
                                       2018.08.10

猜你喜欢

转载自blog.csdn.net/HeGuang68207/article/details/81813946