/*
; 使用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)
gps 信号解析与显示,用于在单片机开发实例解析,可以用于工程
3星 · 超过75%的资源 需积分: 10 4 浏览量
2008-12-19
15:45:47
上传
评论 3
收藏 13KB RAR 举报
niepc0000
- 粉丝: 0
- 资源: 3
最新资源
- Screenshot_20240427_031602.jpg
- 网页PDF_2024年04月26日 23-46-14_QQ浏览器网页保存_QQ浏览器转格式(6).docx
- 直接插入排序,冒泡排序,直接选择排序.zip
- 在排序2的基础上,再次对快排进行优化,其次增加快排非递归,归并排序,归并排序非递归版.zip
- 实现了7种排序算法.三种复杂度排序.三种nlogn复杂度排序(堆排序,归并排序,快速排序)一种线性复杂度的排序.zip
- 冒泡排序 直接选择排序 直接插入排序 随机快速排序 归并排序 堆排序.zip
- 课设-内部排序算法比较 包括冒泡排序、直接插入排序、简单选择排序、快速排序、希尔排序、归并排序和堆排序.zip
- Python排序算法.zip
- C语言实现直接插入排序、希尔排序、选择排序、冒泡排序、堆排序、快速排序、归并排序、计数排序,并带图详解.zip
- 常用工具集参考用于图像等数据处理
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈