gps 信号解析与显示

/*  ; 使用AVR单片机解析出GPSRM数据段的信息,提取时间、经纬度、指示出南北半球及东西经、日期、以及当前数据是否有效的标识位,  ; 并将这些信息显示在1602液晶屏上。   ; 网站:  http://www.ruixuedz.cn  ;email: unaided@tom.com  ; 作者:  老蒋  */      #include <AVR_PQ1A.H>       //包含自定义常量头文件    #include <AVR interrupt.h>       uchar buf[500];     //串口接受数据缓冲区    uint readCount=0;   //串口解析数据计数     uint writeCount=0;  //串口接受数据计数    uchar Time[6];      //gps时间    uchar Date[6];      //gps日期    uchar Status;       //gps有效性    uchar Latitude[9];  //gps纬度    uchar NSIndicator;  //gps南北半球标识位    uchar Longitude[10];//gps经度    uchar EWIndicator;  //gps东西经标识位    uchar Speed[4];     //gps速度       /*******************************************  函数名称: Uart_init  功    能: 异步串口初始化  参    数: baud--设置的波特率  返回值  : 无  ********************************************/   void Uart_init(uint baud)                                {       baud=MCLK/16/baud-1;                   //波特率最大为65K       UCSRB=0x00;       UCSRA=0x00;                            //控制寄存器清零       UCSRC=(1<<URSEL)|(0<<UPM0)|(3<<UCSZ0); UBRRH="baud" UBRRL="baud;" 选择UCSRC,异步模式,禁止校验,1位停止位,8位数据位>>8;                          //设置波特率       UCSRB=(1<<TXEN)|(1<<RXEN)|(1<<RXCIE); if(writeCount ++writeCount; 将接收到的数据存入全局数组 buf[writeCount]="UDR;" 关闭接收中断 UCSRB&="~BIT(RXCIE);" { ISR(USART_RXC_vect) ******************************************** 无 : 返回值 数: 参 异步串口接收 能: 功 Uart_RX 函数名称: ******************************************* } Uart_sendB(*sendpt++); 字符串未结束则继续发送 while(*sendpt) *sendpt) Uart_sentstr(uchar void sendpt--发送的数组指针 异步串口发送一个字符串 Uart_sentstr 清除发送完毕状态位 UCSRA|="1<<TXC;" 等待发送完毕 while(!(UCSRA&(1<<TXC))); 发送数据 UDR="sendB;" 等待发送缓冲区为空 while(!(UCSRA&(1<<UDRE))); sendB) Uart_sendB(uchar sendB--发送的字节数据 异步串口发送一个字节 Uart_sendB 配置TX为输出(很重要) DDRD|="0X02;" 全局中断开放 sei(); 接收、发送使能,接收中断使能> 499)       writeCount = 0;    UCSRB|=BIT(RXCIE);                     //使能接收中断    }      /*******************************************  函数名称: Read_byte  功    能: 从接受缓冲区中读取一个字节  参    数: 无  返回值  : temp--读取到的数据  ********************************************/   uchar Read_byte(void)   {       uchar temp;       while(readCount == writeCount)       {           Delayms(10);           }       temp = buf[readCount];       ++readCount;       if(readCount > 499)           readCount = 0;       return temp;       }      /*******************************************  函数名称: LCD1602_portini  功    能: 初始化1602液晶用到的IO口  参    数: 无  返回值  : 无  ********************************************/   void LCD1602_portini(void)   {       LCDa_CTRL_DDR |= BIT(LCDa_RS)|BIT(LCDa_RW)|BIT(LCDa_E);//配置控制管脚为输出        LCDa_DATA_DDR |= 0xFF;//配置数据管脚为输出    }      /*******************************************  函数名称: LCD1602_readbyte  功    能: 从1602液晶读出一个字节数据或者指令  参    数: DatCmd--为iDat时是数据,为iCmd时是指令  返回值  : dByte--读回的数据或者指令  ********************************************/   uchar LCD1602_readbyte(uchar DatCmd)   {       uchar dByte;       if (DatCmd == iCmd)      //指令操作            LCDa_CLR_RS;       else           LCDa_SET_RS;                  LCDa_SET_RW;             //读操作        LCDa_SET_E;       LCDa_DATA_DDR=0x00;      //数据总线定义为输入        dByte=LCDa_DI;           //读数据或者指令        Delayms(1);              //时序调整        LCDa_CLR_E;        LCDa_DATA_DDR|=0xff;     //数据总线还原为输出        return dByte;   }      /*******************************************  函数名称: LCD1602_sendbyte  功    能: 向1602液晶写入一个字节数据或者指令  参    数: DatCmd--为iDat时是数据,为iCmd时是指令            dByte--为写入1602的数据或者指令  返回值  : 无  ********************************************/   void LCD1602_sendbyte(uchar DatCmd, uchar dByte)   {       if (DatCmd == iCmd)     //指令操作            LCDa_CLR_RS;       else           LCDa_SET_RS;        //数据操作                   LCDa_CLR_RW;            //写操作操作        LCDa_SET_E;       LCDa_DO = dByte;        //写入数据        Delayms(1);       LCDa_CLR_E;    }      /*******************************************  函数名称: LCD1602_sendstr  功    能: 向1602液晶写入一个字符串  参    数: ptString--字符串指针  返回值  : 无  ********************************************/   void LCD1602_sendstr(uchar *ptString)   {       while((*ptString)!='\0')         //字符串未结束就一直写        {           LCD1602_sendbyte(iDat, *ptString++);       }   }      /*******************************************  函数名称: LCD1602_clear  功    能: 1602液晶清屏  参    数: 无  返回值  : 无  ********************************************/   void LCD1602_clear(void)   {       LCD1602_sendbyte(iCmd,LCDa_CLS);//写入清屏指令        Delayms(40);// 清屏指令写入后,2ms 的延时是很必要的!!!    }      /*******************************************  函数名称: LCD1602_readBF  功    能: 1602液晶清屏  参    数: 无  返回值  : busy--为1时是忙状态,为0时可以接收指令  ********************************************/   uchar LCD1602_readBF(void)   {            uchar busy;       busy=LCD1602_readbyte(iCmd);        //读回BF标志(忙标志)和地址        if(busy&0x80)                       //如果忙返回正在忙的状态            busy=1;       else                                //如果不忙,可以写入            busy=0;       return busy;   }      /*******************************************  函数名称: LCD1602_gotoXY  功    能: 移动到指定位置  参    数: Row--指定的行            Col--指定的列  返回值  : 无  ********************************************/   void LCD1602_gotoXY(uchar Row, uchar Col)   {          switch (Row)          //选择行        {           case 1:               LCD1602_sendbyte(iCmd, LCDa_L1 + Col); break;   //写入第1行的指定列             case 2:               LCD1602_sendbyte(iCmd, LCDa_L2 + Col); break;   //写入第2行的指定列             default:               break;                      }   }      /*******************************************  函数名称: LCD1602_initial  功    能: 1602液晶初始化  参    数: 无  返回值  : 无  ********************************************/   void LCD1602_initial(void)   {       Delayms(100);               //上电后等待内部复位        LCD1602_portini();          //端口初始化               LCD1602_sendbyte(iCmd, LCDa_FUNCTION);  //功能、模式设定,具体的设定功能可以看C:\icc\include\AVR_PQ1A.H里面的常量定义        while(LCD1602_readBF());                //等待不忙为止        LCD1602_sendbyte(iCmd, LCDa_ON);        //打开显示        while(LCD1602_readBF());                //等待不忙为止        LCD1602_clear();                        //清屏        while(LCD1602_readBF());                //等待不忙为止        LCD1602_sendbyte(iCmd, LCDa_ENTRY);     //输入模式设定            }      /*******************************************  函数名称: clear_gprmc  功    能: 清空gprmc显示缓冲区  参    数: 无  返回值  : 无  ********************************************/   void clear_gprmc(void)   {       uchar i;       for(i=0; i<6; i++)       {           Time[i] = '0';           Date[i] = '0';       }       for(i=0; i<9; i++)       {           Latitude[i] = '0';       }       for(i=0; i<10; i++)       {           Longitude[i] = '0';       }       for(i=0; i<4; i++)       {           Speed[i] = '0';       }              Status = '0';            NSIndicator = '0';       EWIndicator = '0';   }      /*******************************************  函数名称: Parse_gprmc  功    能: 解析GPRMC字段  参    数: 无  返回值  : 无  ********************************************/   void Parse_gprmc(void)   {       uchar i;       uchar temp;       clear_gprmc();       Read_byte();       temp = Read_byte();       if(',' != temp)       {           Time[0] = temp;           for(i=0; i<5; i++)           {               Time[i+1] = Read_byte();           }           Read_byte();           Read_byte();           Read_byte();           Read_byte();       }       Status = Read_byte();       Read_byte();       temp = Read_byte();       if(',' != temp)       {           Latitude[0] = temp;           for(i=0; i<3; i++)           {               Latitude[i+1] = Read_byte();           }           Read_byte();           for(i=0; i<5; i++)           {               Latitude[4+i] = Read_byte();           }           Read_byte();       }       temp = Read_byte();       if(',' != temp)       {           NSIndicator = temp;           Read_byte();       }       temp = Read_byte();       if(',' != temp)       {           Longitude[0] = temp;           for(i=0; i<4; i++)           {               Longitude[i+1] = Read_byte();           }              Read_byte();           for(i=0; i<5; i++)           {               Longitude[5+i] = Read_byte();           }              Read_byte();       }       temp = Read_byte();       if(',' != temp)       {           EWIndicator = temp;           Read_byte();       }       temp = Read_byte();       if(',' != temp)       {           Speed[0] = temp;           Read_byte();           for(i=0; i<3; i++)           {               Speed[1+i] = Read_byte();           }           Read_byte();       }       Read_byte();       temp = Read_byte();       if(',' != temp)       {           Date[0] = temp;           for(i=0; i<5; i++)           {               Date[i+1] = Read_byte();           }          }   }      /*******************************************  函数名称: Display_gprmc  功    能: 显示GPRMC字段信息  参    数: 无  返回值  : 无  ********************************************/   void Display_gprmc(void)   {       uchar high,low,i;       high = Time[0];       low = Time[1];       low = low+8;       if(low > 57)       {           low = low - 10;           high = high + 1;        }       LCD1602_clear();       while(LCD1602_readBF());       LCD1602_gotoXY(1,0);       LCD1602_sendbyte(iDat,high);       LCD1602_sendbyte(iDat,low);       LCD1602_sendbyte(iDat,':');       LCD1602_sendbyte(iDat,Time[2]);       LCD1602_sendbyte(iDat,Time[3]);       LCD1602_sendbyte(iDat,':');       LCD1602_sendbyte(iDat,Time[4]);       LCD1602_sendbyte(iDat,Time[5]);       LCD1602_sendbyte(iDat,' ');       LCD1602_sendbyte(iDat,Status);       while(LCD1602_readBF());       LCD1602_gotoXY(2,0);       LCD1602_sendbyte(iDat,Date[4]);       LCD1602_sendbyte(iDat,Date[5]);       LCD1602_sendbyte(iDat,'.');       LCD1602_sendbyte(iDat,Date[2]);       LCD1602_sendbyte(iDat,Date[3]);       LCD1602_sendbyte(iDat,'.');       LCD1602_sendbyte(iDat,Date[0]);       LCD1602_sendbyte(iDat,Date[1]);       Delayms(50000);       LCD1602_clear();       while(LCD1602_readBF());       LCD1602_gotoXY(1,0);       LCD1602_sendbyte(iDat,Latitude[0]);       LCD1602_sendbyte(iDat,Latitude[1]);       LCD1602_sendbyte(iDat,'.');       for(i=0; i<7; i++)       {           LCD1602_sendbyte(iDat,Latitude[2+i]);       }       LCD1602_sendbyte(iDat,' ');       LCD1602_sendbyte(iDat,NSIndicator);       while(LCD1602_readBF());       LCD1602_gotoXY(2,0);       LCD1602_sendbyte(iDat,Longitude[0]);       LCD1602_sendbyte(iDat,Longitude[1]);       LCD1602_sendbyte(iDat,Longitude[2]);       LCD1602_sendbyte(iDat,'.');        for(i=0; i<7; i++)       {           LCD1602_sendbyte(iDat,Longitude[3+i]);       }          LCD1602_sendbyte(iDat,' ');       LCD1602_sendbyte(iDat,EWIndicator);       Delayms(50000);   }      /*******************************************  函数名称: Read_gprmc  功    能: 读取GPRMC字段  参    数: 无  返回值  : 无  ********************************************/   void Read_gprmc(void)   {       uchar temp = 0;       temp = Read_byte();       if(temp == '$')       {           Read_byte();           Read_byte();           temp = Read_byte();           if(temp == 'R')           {               temp = Read_byte();               if(temp == 'M')               {                   temp = Read_byte();                   if(temp == 'C')                   {                       Parse_gprmc();                       Display_gprmc();                   }               }           }       }   }      /*******************************************  函数名称: main  功    能:   参    数: 无  返回值  : 无  ********************************************/   int main(void)   {    Board_init( );             //初始化开发板     Uart_init(9600);           //初始化串口,设置波特率     LCD1602_initial();     while(LCD1602_readBF());     LCD1602_gotoXY(1,0);     LCD1602_sendstr("AVR_PQ1A BOARD");        while(1)    {       Read_gprmc();    }   }      

转载于:https://www.cnblogs.com/slcfhr/archive/2010/07/04/1770727.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值