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