📄 main.txt
字号:
/*************************************
GPS解码程序
作者:BG4UVR
最后更新:
2007.03.30
1.5版
1、改为使用12864点阵屏显示
***************************************/
//包含头文件
#include <avr/io.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include "ks0108.h"
#define TIME_AREA 8
//GPS数据存储数组
unsigned char JD[10]={"00000.0000"}; //经度
unsigned char JD_a='*'; //经度方向
unsigned char WD[9]={"0000.0000"}; //纬度
unsigned char WD_a='*'; //纬度方向
unsigned char time[6]={"000000"}; //时间
unsigned char date[6]={"000000"}; //日期
unsigned char speed[5]; //速度
unsigned char high[6]; //高度
unsigned char angle[5]; //方位角
unsigned char use_sat[2]={"00"}; //使用的卫星数
unsigned char total_sat[2]={"00"}; //天空中总卫星数
//串口中断需要的变量
unsigned char seg_count; //逗号计数器
unsigned char dot_count; //小数点计数器
unsigned char byte_count; //位数计数器
unsigned char cmd_number; //命令类型
unsigned char mode; //0:结束模式,1:命令模式,2:数据模式
volatile unsigned char buf_full; //1:整句接收完成,相应数据有效。0:缓存数据无效。
unsigned char cmd[5]; //命令类型存储数组
//显示需要的变量
unsigned char dsp_count; //刷新次数计数器
unsigned char time_count;
volatile unsigned char high_num,a_num,s_num;
void init_set(void);
void sys_init(void);
unsigned char week(unsigned char year, unsigned char mon, unsigned char day);
int main(void)
{
unsigned char i;
unsigned char Bhour=0,Bday=0,Bmonth=0;
unsigned int Byear=0;
sys_init();
while(1){
if(buf_full==0) //无GPS信号时
{
dsp_count++;
_delay_ms(10);
if(dsp_count>=200){
CLEAN_SCREEN(); //清屏
STR_58_DISP(0,0,PSTR("No GPS CONNECT.."),0);
while(buf_full==0);
CLEAN_SCREEN();
dsp_count=0;
}
}
else{ //有GPS信号时
if(buf_full|0x01){ //GGA语句
ASCII_58_DISP(0,0,JD_a,0); //显示经度
for(i=0;i<3;i++){
ASCII_58_DISP(0,(i+1)*6,JD[i],0);
}
ASCII_58_DISP(0,24,'.',0);
for(i=3;i<10;i++){
ASCII_58_DISP(0,(i+2)*6,JD[i],0);
}
ASCII_58_DISP(1,0,WD_a,0); //显示纬度
for(i=0;i<2;i++){
ASCII_58_DISP(1,(i+2)*6,WD[i],0);
}
ASCII_58_DISP(1,24,'.',0);
for(i=2;i<9;i++){
ASCII_58_DISP(1,(i+3)*6,WD[i],0);
}
ASCII_58_DISP(2,96,use_sat[0],0); //显示接收卫星数
ASCII_58_DISP(2,102,use_sat[1],0);
ASCII_58_DISP(2,108,'/',0);
STR_58_DISP(2,0,PSTR("HI:"),0);
if(high_num<6) //高度显示
{
for(i=0;i<(6-high_num);i++)
{
ASCII_58_DISP(2,(3+i)*6,0x20,0);
}
}
for(i=0;i<high_num;i++)
{
ASCII_58_DISP(2,(9-high_num+i)*6,high[i],0);
}
STR_58_DISP(2,54,PSTR("m U/T:"),0);
buf_full&=~0x01;
dsp_count=0;
}
if(buf_full|0x02){ //GSV语句
ASCII_58_DISP(2,114,total_sat[0],0);
ASCII_58_DISP(2,120,total_sat[1],0);
buf_full&=~0x02;
dsp_count=0;
}
if(buf_full|0x04)
{
STR_58_DISP(0,78,PSTR("AG:"),0);//方位角显示
if(a_num<5)
{
for(i=0;i<(5-a_num);i++)
{
ASCII_58_DISP(0,(16+i)*6,0x20,0);
}
}
for(i=0;i<a_num;i++)
{
ASCII_58_DISP(0,(21-a_num+i)*6,angle[i],0);
}
STR_58_DISP(1,78,PSTR("SP:"),0); //速度显示
if(s_num<5)
{
for(i=0;i<(5-s_num);i++)
{
ASCII_58_DISP(1,(16+i)*6,0x20,0);
}
}
for(i=0;i<s_num;i++)
{
ASCII_58_DISP(1,(21-s_num+i)*6,speed[i],0);
}
buf_full&=~0x04;
dsp_count=0;
}
if(buf_full|0x08){
if(Bhour!=((time[0]-0x30)*10+time[1]-0x30)+TIME_AREA){
Bhour=((time[0]-0x30)*10+time[1]-0x30)+TIME_AREA; //北京时间转换
Bday=(date[0]-0x30)*10+date[1]-0x30;
Bmonth=(date[2]-0x30)*10+date[3]-0x30;
Byear=(date[4]-0x30)*10+date[5]-0x30+2000;
if(Bhour>=24){ //如果小时数大于24
Bhour-=24; //小时数减24
Bday++; //日期数加1
switch(Bday){ //判断日期
case 29: //普通年的2月份
if((!((Byear%400==0)||((Byear%4==0)&&(Byear%100!=0)))&&(Bmonth==2))){
Bday=1;
Bmonth++;
}
break;
case 30: //如果是闰年的2月
if(((Byear%400==0)||((Byear%4==0)&&(Byear%100!=0)))&&(Bmonth==2)){
Bday=1;
Bmonth++;
}
break;
case 31:
if((Bmonth==4)||(Bmonth==6)||(Bmonth==9)||(Bmonth==11)){
Bday=1;
Bmonth++;
}
break;
case 32:
Bday=1;
Bmonth++;
if(Bmonth>=13){
Byear++;
Bmonth=1;
}
break;
}
}
}
ASCII_58_DISP(3,0,'2',0);
ASCII_58_DISP(3,6,'0',0);
ASCII_58_DISP(3,12,(Byear%100)/10+0x30,0);
ASCII_58_DISP(3,18,Byear%10+0x30,0);
ASCII_58_DISP(3,24,'/',0);
ASCII_58_DISP(3,30,Bmonth/10+0x30,0);
ASCII_58_DISP(3,36,Bmonth%10+0x30,0);
ASCII_58_DISP(3,42,'/',0);
ASCII_58_DISP(3,48,Bday/10+0x30,0);
ASCII_58_DISP(3,54,Bday%10+0x30,0);
switch(week(Byear%100,Bmonth,Bday)){
case 0:
STR_58_DISP(3,120,PSTR("7"),0);
break;
case 1:
STR_58_DISP(3,120,PSTR("1"),0);
break;
case 2:
STR_58_DISP(3,120,PSTR("2"),0);
break;
case 3:
STR_58_DISP(3,120,PSTR("3"),0);
break;
case 4:
STR_58_DISP(3,120,PSTR("4"),0);
break;
case 5:
STR_58_DISP(3,120,PSTR("5"),0);
break;
case 6:
STR_58_DISP(3,120,PSTR("6"),0);
break;
}
if(Bhour/10!=0)
{
ASCII_58_DISP(3,66,Bhour/10+0x30,0);
NUM1632_DISP(4,0,Bhour/10,0);
}
else
{
ASCII_58_DISP(3,66,0x20,0);
NUM1632_DISP(4,0,11,0);
}
ASCII_58_DISP(3,72,Bhour%10+0x30,0);
ASCII_58_DISP(3,78,':',0);
ASCII_58_DISP(3,84,time[2],0);
ASCII_58_DISP(3,90,time[3],0);
ASCII_58_DISP(3,96,':',0);
ASCII_58_DISP(3,102,time[4],0);
ASCII_58_DISP(3,108,time[5],0);
NUM1632_DISP(4,1,Bhour%10,0);
NUM1632_DISP(4,2,10,0);
NUM1632_DISP(4,3,time[2]-0x30,0);
NUM1632_DISP(4,4,time[3]-0x30,0);
NUM1632_DISP(4,5,10,0);
NUM1632_DISP(4,6,time[4]-0x30,0);
NUM1632_DISP(4,7,time[5]-0x30,0);
buf_full&=~0x08;
dsp_count=0;
}
}
}
}
//计算星期
unsigned char week(unsigned char year, unsigned char mon, unsigned char day)
{
const prog_uchar Weekdays[] = {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5};
// 31 28 31 30 31 30 31 31 30 31 30
return (6-1 + (year>>2) + year + Weekdays[mon-1] + day + (((year & 3) || mon > 2)? 1 : 0)) % 7;
//完整的计算星期的公式:
//(year>>2) - (year / 100) + (year/400) + year +
// Weekdays[mon-1] + day + ((!isLeap(year) || mon > 2)? 1 : 0)) % 7;
}
//USART 初始化
void init_USART(void)
{
UCSRC = (1<<URSEL) | 0x06; //异步,8位数据,无奇偶校验,一个停止位,无倍速
UBRRL= (F_CPU/9600/16-1)%256; //UBRR= (F_CPU/(BAUDRATE*16))-1;
UBRRH= (F_CPU/9600/16-1)/256;
UCSRA = 0x00; //使能接收中断,使能接收,使能发送
UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);
sei(); //总中断允许
}
//系统初始化
void sys_init()
{
LCD_RESET(); //初始化LCD
CLEAN_SCREEN();
init_USART(); //初始化串口
}
//串口接收中断
SIGNAL(SIG_UART_RECV) //串口接收中断服务程序
{
unsigned char tmp;
tmp=UDR;
switch(tmp){
case '$':
cmd_number=0; //命令类型清空
mode=1; //接收命令模式
byte_count=0; //接收位数清空
break;
case ',':
seg_count++; //逗号计数加1
byte_count=0;
break;
case '*':
switch(cmd_number){
case 1:
buf_full|=0x01;
break;
case 2:
buf_full|=0x02;
break;
case 3:
buf_full|=0x04;
break;
case 4:
buf_full|=0x08;
break;
}
mode=0;
break;
default:
if(mode==1){
//命令种类判断
cmd[byte_count]=tmp; //接收字符放入类型缓存
if(byte_count>=4){ //如果类型数据接收完毕,判断类型
if(cmd[0]=='G'){
if(cmd[1]=='P'){
if(cmd[2]=='G'){
if(cmd[3]=='G'){
if(cmd[4]=='A'){
cmd_number=1;
mode=2;
seg_count=0;
byte_count=0;
high_num=0;
}
}
else if(cmd[3]=='S'){
if(cmd[4]=='V'){
cmd_number=2;
mode=2;
seg_count=0;
byte_count=0;
}
}
}
else if(cmd[2]=='R'){
if(cmd[3]=='M'){
if(cmd[4]=='C'){
cmd_number=3;
mode=2;
seg_count=0;
byte_count=0;
a_num=0;
s_num=0;
}
}
}
else if(cmd[2]=='Z'){
if(cmd[3]=='D'){
if(cmd[4]=='A'){
cmd_number=4;
mode=2;
seg_count=0;
byte_count=0;
}
}
}
}
}
}
}
else if(mode==2){
//接收数据处理
switch (cmd_number){
case 1: //类型1数据接收。GPGGA
switch(seg_count){
case 2: //纬度处理
if(byte_count<9){
WD[byte_count]=tmp;
}
break;
case 3: //纬度方向处理
if(byte_count<1){
WD_a=tmp;
}
break;
case 4: //经度处理
if(byte_count<10){
JD[byte_count]=tmp;
}
break;
case 5: //经度方向处理
if(byte_count<1){
JD_a=tmp;
}
break;
case 7: //定位使用的卫星数
if(byte_count<2){
use_sat[byte_count]=tmp;
}
break;
case 9: //高度处理
if(byte_count<6){
high[byte_count]=tmp;
high_num++;
}
break;
}
break;
case 2: //类型2数据接收。GPGSV
switch(seg_count){
case 3: //天空中的卫星总数
if(byte_count<2){
total_sat[byte_count]=tmp;
}
break;
}
break;
case 3: //类型3数据接收。GPRMC
switch(seg_count){
case 7: //速度处理
if(byte_count<5){
speed[byte_count]=tmp;
s_num++;
}
break;
case 8: //方位角处理
if(byte_count<5){
angle[byte_count]=tmp;
a_num++;
}
break;
}
break;
case 4: //类型4数据接收。GPZDA
switch(seg_count){
case 1:
if(byte_count<6){ //时间处理
time[byte_count]=tmp;
}
break;
case 2:
if(byte_count<2){
date[byte_count]=tmp;
}
break;
case 3:
if(byte_count<2){
date[byte_count+2]=tmp;
}
break;
case 4:
if((byte_count<4)&&(byte_count>1)){
date[byte_count+2]=tmp;
}
break;
}
break;
}
}
byte_count++; //接收数位加1
break;
}
}
/*
$GPGGA,024518.00,3153.7225,N,12111.9951,E,1,04,1.48,-00009,M,007,M,,*4C
$GPGLL,3153.7225,N,12111.9951,E,024518.00,A,A*63
$GPVTG,000.0,T,004.7,M,000.0,N,000.0,K,A*20
$GPGSA,A,2,04,08,17,20,,,,,,,,,1.48,1.48,0.03*08
$GPGSV,2,1,08,04,15,231,38,08,29,218,42,11,49,043,,19,09,082,*76
$GPGSV,2,2,08,27,14,198,29,28,71,316,,17,32,300,36,20,45,124,43*70
$GPRMC,024518.00,A,3153.7225,N,12111.9951,E,000.0,000.0,280107,04.7,W,A*12
$GPZDA,024519.45,28,01,2007,,*62
*/
/*
012345678901234567890
E121.22.2231 AG:112.1
N 23.23.2341 SP:234.1
HI:12345.5m U/T:03/12
2007/12/13 23:23:53 7
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -