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();   
  •  }   
  • }   
  •    
  • posted @ 2010-07-04 02:35  邵利超  阅读(2775)  评论(0编辑  收藏  举报