?? gps_display_release.c
字號(hào):
/*
; 使用AVR單片機(jī)解析出GPSRM數(shù)據(jù)段的信息,提取時(shí)間、經(jīng)緯度、指示出南北半球及東西經(jīng)、日期、以及當(dāng)前數(shù)據(jù)是否有效的標(biāo)識(shí)位,
; 并將這些信息顯示在1602液晶屏上。
;
; 網(wǎng)站: http://www.ruixuedz.cn
;email: unaided@tom.com
; 作者: 老蔣
*/
#include <AVR_PQ1A.h> //包含自定義常量頭文件
#include <avr/interrupt.h>
uchar buf[500]; //串口接受數(shù)據(jù)緩沖區(qū)
uint readCount=0; //串口解析數(shù)據(jù)計(jì)數(shù)
uint writeCount=0; //串口接受數(shù)據(jù)計(jì)數(shù)
uchar Time[6]; //gps時(shí)間
uchar Date[6]; //gps日期
uchar Status; //gps有效性
uchar Latitude[9]; //gps緯度
uchar NSIndicator; //gps南北半球標(biāo)識(shí)位
uchar Longitude[10];//gps經(jīng)度
uchar EWIndicator; //gps東西經(jīng)標(biāo)識(shí)位
uchar Speed[4]; //gps速度
/*******************************************
函數(shù)名稱: Uart_init
功 能: 異步串口初始化
參 數(shù): baud--設(shè)置的波特率
返回值 : 無
********************************************/
void Uart_init(uint baud)
{
baud=MCLK/16/baud-1; //波特率最大為65K
UCSRB=0x00;
UCSRA=0x00; //控制寄存器清零
UCSRC=(1<<URSEL)|(0<<UPM0)|(3<<UCSZ0); //選擇UCSRC,異步模式,禁止校驗(yàn),1位停止位,8位數(shù)據(jù)位
UBRRL=baud;
UBRRH=baud>>8; //設(shè)置波特率
UCSRB=(1<<TXEN)|(1<<RXEN)|(1<<RXCIE); //接收、發(fā)送使能,接收中斷使能
sei(); //全局中斷開放
DDRD|=0X02; //配置TX為輸出(很重要)
}
/*******************************************
函數(shù)名稱: Uart_sendB
功 能: 異步串口發(fā)送一個(gè)字節(jié)
參 數(shù): sendB--發(fā)送的字節(jié)數(shù)據(jù)
返回值 : 無
********************************************/
void Uart_sendB(uchar sendB)
{
while(!(UCSRA&(1<<UDRE))); //等待發(fā)送緩沖區(qū)為空
UDR=sendB; //發(fā)送數(shù)據(jù)
while(!(UCSRA&(1<<TXC))); //等待發(fā)送完畢
UCSRA|=1<<TXC; //清除發(fā)送完畢狀態(tài)位
}
/*******************************************
函數(shù)名稱: Uart_sentstr
功 能: 異步串口發(fā)送一個(gè)字符串
參 數(shù): sendpt--發(fā)送的數(shù)組指針
返回值 : 無
********************************************/
void Uart_sentstr(uchar *sendpt)
{
while(*sendpt) //字符串未結(jié)束則繼續(xù)發(fā)送
{
Uart_sendB(*sendpt++);
}
}
/*******************************************
函數(shù)名稱: Uart_RX
功 能: 異步串口接收
參 數(shù): 無
返回值 : 無
********************************************/
ISR(USART_RXC_vect)
{
UCSRB&=~BIT(RXCIE); //關(guān)閉接收中斷
buf[writeCount]=UDR; //將接收到的數(shù)據(jù)存入全局?jǐn)?shù)組
++writeCount;
if(writeCount > 499)
writeCount = 0;
UCSRB|=BIT(RXCIE); //使能接收中斷
}
/*******************************************
函數(shù)名稱: Read_byte
功 能: 從接受緩沖區(qū)中讀取一個(gè)字節(jié)
參 數(shù): 無
返回值 : temp--讀取到的數(shù)據(jù)
********************************************/
uchar Read_byte(void)
{
uchar temp;
while(readCount == writeCount)
{
Delayms(10);
}
temp = buf[readCount];
++readCount;
if(readCount > 499)
readCount = 0;
return temp;
}
/*******************************************
函數(shù)名稱: LCD1602_portini
功 能: 初始化1602液晶用到的IO口
參 數(shù): 無
返回值 : 無
********************************************/
void LCD1602_portini(void)
{
LCDa_CTRL_DDR |= BIT(LCDa_RS)|BIT(LCDa_RW)|BIT(LCDa_E);//配置控制管腳為輸出
LCDa_DATA_DDR |= 0xFF;//配置數(shù)據(jù)管腳為輸出
}
/*******************************************
函數(shù)名稱: LCD1602_readbyte
功 能: 從1602液晶讀出一個(gè)字節(jié)數(shù)據(jù)或者指令
參 數(shù): DatCmd--為iDat時(shí)是數(shù)據(jù),為iCmd時(shí)是指令
返回值 : dByte--讀回的數(shù)據(jù)或者指令
********************************************/
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; //數(shù)據(jù)總線定義為輸入
dByte=LCDa_DI; //讀數(shù)據(jù)或者指令
Delayms(1); //時(shí)序調(diào)整
LCDa_CLR_E;
LCDa_DATA_DDR|=0xff; //數(shù)據(jù)總線還原為輸出
return dByte;
}
/*******************************************
函數(shù)名稱: LCD1602_sendbyte
功 能: 向1602液晶寫入一個(gè)字節(jié)數(shù)據(jù)或者指令
參 數(shù): DatCmd--為iDat時(shí)是數(shù)據(jù),為iCmd時(shí)是指令
dByte--為寫入1602的數(shù)據(jù)或者指令
返回值 : 無
********************************************/
void LCD1602_sendbyte(uchar DatCmd, uchar dByte)
{
if (DatCmd == iCmd) //指令操作
LCDa_CLR_RS;
else
LCDa_SET_RS; //數(shù)據(jù)操作
LCDa_CLR_RW; //寫操作操作
LCDa_SET_E;
LCDa_DO = dByte; //寫入數(shù)據(jù)
Delayms(1);
LCDa_CLR_E;
}
/*******************************************
函數(shù)名稱: LCD1602_sendstr
功 能: 向1602液晶寫入一個(gè)字符串
參 數(shù): ptString--字符串指針
返回值 : 無
********************************************/
void LCD1602_sendstr(uchar *ptString)
{
while((*ptString)!='\0') //字符串未結(jié)束就一直寫
{
LCD1602_sendbyte(iDat, *ptString++);
}
}
/*******************************************
函數(shù)名稱: LCD1602_clear
功 能: 1602液晶清屏
參 數(shù): 無
返回值 : 無
********************************************/
void LCD1602_clear(void)
{
LCD1602_sendbyte(iCmd,LCDa_CLS);//寫入清屏指令
Delayms(40);// 清屏指令寫入后,2ms 的延時(shí)是很必要的!!!
}
/*******************************************
函數(shù)名稱: LCD1602_readBF
功 能: 1602液晶清屏
參 數(shù): 無
返回值 : busy--為1時(shí)是忙狀態(tài),為0時(shí)可以接收指令
********************************************/
uchar LCD1602_readBF(void)
{
uchar busy;
busy=LCD1602_readbyte(iCmd); //讀回BF標(biāo)志(忙標(biāo)志)和地址
if(busy&0x80) //如果忙返回正在忙的狀態(tài)
busy=1;
else //如果不忙,可以寫入
busy=0;
return busy;
}
/*******************************************
函數(shù)名稱: LCD1602_gotoXY
功 能: 移動(dòng)到指定位置
參 數(shù): 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;
}
}
/*******************************************
函數(shù)名稱: LCD1602_initial
功 能: 1602液晶初始化
參 數(shù): 無
返回值 : 無
********************************************/
void LCD1602_initial(void)
{
Delayms(100); //上電后等待內(nèi)部復(fù)位
LCD1602_portini(); //端口初始化
LCD1602_sendbyte(iCmd, LCDa_FUNCTION); //功能、模式設(shè)定,具體的設(shè)定功能可以看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); //輸入模式設(shè)定
}
/*******************************************
函數(shù)名稱: clear_gprmc
功 能: 清空gprmc顯示緩沖區(qū)
參 數(shù): 無
返回值 : 無
********************************************/
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';
}
/*******************************************
函數(shù)名稱: Parse_gprmc
功 能: 解析GPRMC字段
參 數(shù): 無
返回值 : 無
********************************************/
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();
}
}
}
/*******************************************
函數(shù)名稱: Display_gprmc
功 能: 顯示GPRMC字段信息
參 數(shù): 無
返回值 : 無
********************************************/
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);
}
/*******************************************
函數(shù)名稱: Read_gprmc
功 能: 讀取GPRMC字段
參 數(shù): 無
返回值 : 無
********************************************/
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();
}
}
}
}
}
/*******************************************
函數(shù)名稱: main
功 能:
參 數(shù): 無
返回值 : 無
********************************************/
int main(void)
{
Board_init( ); //初始化開發(fā)板
Uart_init(9600); //初始化串口,設(shè)置波特率
LCD1602_initial();
while(LCD1602_readBF());
LCD1602_gotoXY(1,0);
LCD1602_sendstr("AVR_PQ1A BOARD");
while(1)
{
Read_gprmc();
}
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -