⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gps_display_release.c

📁 使用AVR单片机解析出GPSRM数据段的信息
💻 C
字号:
/*
; 使用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); //选择UCSRC,异步模式,禁止校验,1位停止位,8位数据位
   UBRRL=baud; 					     	  
   UBRRH=baud>>8; 						  //设置波特率
   UCSRB=(1<<TXEN)|(1<<RXEN)|(1<<RXCIE);  //接收、发送使能,接收中断使能
   sei();							  //全局中断开放
   DDRD|=0X02;							  //配置TX为输出(很重要)
}

/*******************************************
函数名称: Uart_sendB
功    能: 异步串口发送一个字节
参    数: sendB--发送的字节数据
返回值  : 无
********************************************/
void Uart_sendB(uchar sendB)
{
 while(!(UCSRA&(1<<UDRE)));		 //等待发送缓冲区为空
 UDR=sendB;						 //发送数据
 while(!(UCSRA&(1<<TXC)));		 //等待发送完毕
 UCSRA|=1<<TXC;					 //清除发送完毕状态位
}

/*******************************************
函数名称: Uart_sentstr
功    能: 异步串口发送一个字符串
参    数: sendpt--发送的数组指针
返回值  : 无
********************************************/
void Uart_sentstr(uchar *sendpt)		
{
    while(*sendpt)				//字符串未结束则继续发送
	{
	 Uart_sendB(*sendpt++);
	}
}

/*******************************************
函数名称: Uart_RX
功    能: 异步串口接收
参    数: 无
返回值  : 无
********************************************/
ISR(USART_RXC_vect)
{
 UCSRB&=~BIT(RXCIE);					//关闭接收中断 
 buf[writeCount]=UDR;						//将接收到的数据存入全局数组
 ++writeCount;
 if(writeCount > 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();
 }
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -