/* ; 使用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