Jannie Hamman
Joined: 16 Sep 2003 Posts: 6 Location: South Africa
|
GPS based RTCC |
Posted: Thu Jul 28, 2011 3:08 am |
|
|
Attached herewith code for GPS based RTCC. Hope you enjoy...
Code: |
/*
PIC Garmin GPS 25LVS - 18F4520
with local time zone correction
BR set to 9600bps and not standard 4800bps
Should work with any GPS module
(c)2008 All rights reserved by Jannie Hamman
20/9/2008 - V1.0 - Original base program
22/7/2011 - V1.1 - Added days of the week calculation
Tested with UBlox module - see comment
*/
#include <18F4520.h>
#device adc=10
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES XT //Crystal osc <= 4mhz for PCM/PCH , 3mhz to 10 mhz for PCD
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOBROWNOUT //No brownout reset
#FUSES BORV20 //Brownout reset at 2.0V
#FUSES NOPUT //No Power Up Timer
#FUSES NOCPD //No EE protection
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT //Program memory not write protected
#FUSES NOWRTD //Data EEPROM not write protected
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES FCMEN //Fail-safe clock monitor enabled
#FUSES PBADEN //PORTB pins are configured as analog input channels on RESET
#FUSES NOWRTC //configuration not registers write protected
#FUSES NOWRTB //Boot block not write protected
#FUSES NOEBTR //Memory not protected from table reads
#FUSES NOEBTRB //Boot block not protected from table reads
#FUSES NOCPB //No Boot Block code protection
#FUSES LPT1OSC //Timer1 configured for low-power operation
#FUSES MCLR //Master Clear pin enabled
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,errors)
#use i2c(master,fast,sda=PIN_C4,scl=PIN_C3)
#include "stdlib.h"
#priority rda
//Varaiables for GPS
long len; //Ring buffer length
int i; //Token counter
char chin; //RS232 received character
char istr[300]; //Received string in buffer
char tstr[100]; //Test/temp string for string functions
char lon[15]; //Final lon
char lat[15]; //Final lat
char lond[5]; //Long's hemisphere
char latd[5]; //Lat's hemispere
char deg[10]; //Coarse over ground
char time[10]; //UTC time
char date[12]; //UTC date
char ele[10]; //Elevation above sea level
char knots[10]; //Speed over ground
char stats[5]; //GPS status
char cmd0[20]; //Used temp for strtok function
char *index; //ditto
char toks[]=","; //, token for strtok
char dowstr[15]; //Day of week
float kmph; // km/h=knots*1.852
char tmp[3]; //Temp string for atoi ect.
int hr; //Time hour
int nn; //Time minutes
int ss; //Time seconds
int yy; //Date year
int mm; //Date month
int dd; //Date day
int dow; //Date day of week 0=Sun .. 6=Sat
int maxdd; //Maksimum days for given month
int xx[]={0,3,2,5,0,3,5,1,4,6,2,4}; //Table for calculating dow
int16 flags; //Some flags used
#bit incmd = flags.0
#bit lfcr = flags.1
#bit gotit = flags.2
//Get date and time to local format
//Only positive offset implemented!
//Modify for negative timezones
void tmdtlocal(){
tmp[0]=time[0];
tmp[1]=time[1];
tmp[2]=0;
hr=atoi(tmp);
tmp[0]=time[2];
tmp[1]=time[3];
tmp[2]=0;
nn=atoi(tmp);
tmp[0]=time[4];
tmp[1]=time[5];
tmp[2]=0;
ss=atoi(tmp);
tmp[0]=date[0];
tmp[1]=date[1];
tmp[2]=0;
dd=atoi(tmp);
tmp[0]=date[2];
tmp[1]=date[3];
tmp[2]=0;
mm=atoi(tmp);
tmp[0]=date[4];
tmp[1]=date[5];
tmp[2]=0;
yy=atoi(tmp);
hr+=2; //Add local timezone for South Africa
if(hr>23){
hr-=24;
dd++; //Add 1 day
maxdd=0; //Check if new month
switch (mm){
case 1: maxdd=31; break;
case 2: maxdd=28; break;
case 3: maxdd=31; break;
case 4: maxdd=30; break;
case 5: maxdd=31; break;
case 6: maxdd=30; break;
case 7: maxdd=31; break;
case 8: maxdd=31; break;
case 9: maxdd=30; break;
case 10: maxdd=31; break;
case 11: maxdd=30; break;
case 12: maxdd=31; break;
default: maxdd=0; break; //For Murthy!!!
}
if(((yy%4)==0)&&(mm==2))maxdd=29; //Leapyear Feb 29 days
if(dd>maxdd){ //1st day of next month
dd=1;
mm++;
}
if(mm>12){ //if December, increment year
mm=1;
yy++;
}
}
//Get time in string format hh:nn:ss
time[0]=(hr/10)+0x30;
time[1]=(hr%10)+0x30;
time[2]=':';
time[3]=(nn/10)+0x30;
time[4]=(nn%10)+0x30;
time[5]=':';
time[6]=(ss/10)+0x30;
time[7]=(ss%10)+0x30;
time[8]=0;
//Get date in string format 20yy/mm/dd
date[0]='2';
date[1]='0';
date[2]=(yy/10)+0x30;
date[3]=(yy%10)+0x30;
date[4]='/';
date[5]=(mm/10)+0x30;
date[6]=(mm%10)+0x30;
date[7]='/';
date[8]=(dd/10)+0x30;
date[9]=(dd%10)+0x30;
date[10]=0;
//Get the day of the week
yy-=mm<3;
dow=(yy+yy/4-yy/100+yy/400+xx[mm-1]+dd)%7;
switch (dow){
case 0: strcpy(dowstr,"Sunday"); break;
case 1: strcpy(dowstr,"Monday"); break;
case 2: strcpy(dowstr,"Tuesday"); break;
case 3: strcpy(dowstr,"Wednesday"); break;
case 4: strcpy(dowstr,"Thursday"); break;
case 5: strcpy(dowstr,"Friday"); break;
case 6: strcpy(dowstr,"Saturday"); break;
default: strcpy(dowstr,"Unknown day"); break; //Not possible, but you never know!
}
}
//Clear the buffer
void clr_buf(){
long i;
len=0;
for(i=0;i<=299;i++)istr[i]='\0';
lfcr=false;
enable_interrupts(int_rda);
}
//RS RDA interrupt ring buffer
#int_RDA
void rsint(){
chin=getc();
if(!incmd){
if((chin=='\r')||(chin=='\n')){chin='*';lfcr=true;}
if((chin>=' ')&&(chin<='~')){
istr[len]=toupper(chin);
len++;
if(len>299){len=0;lfcr=true;istr[299]=0;}
}
}
}
#int_RTCC
void RTCC_isr(void)
{
}
#int_TIMER1
void TIMER1_isr(void)
{
}
#int_TIMER2
void TIMER2_isr(void)
{
}
void main()
{
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_CLOCK_INTERNAL|ADC_TAD_MUL_8);
setup_psp(PSP_DISABLED);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_16); //1sec
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1); //262mS
setup_timer_2(T2_DIV_BY_16,31,2); //1mS
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
enable_interrupts(INT_RTCC);
enable_interrupts(INT_TIMER1);
enable_interrupts(INT_TIMER2);
enable_interrupts(INT_EXT);
setup_oscillator(OSC_NORMAL);
clr_buf();
rs232_errors=0;
flags=0;
printf("$PGRMO,0,2\r\n"); //All NMEA sentences off
printf("$PGRMO,GPRMC,1\r\n"); //RMC activated
printf("$PGRMO,GPGGA,1\r\n"); //GGA activated - have elevation
enable_interrupts(GLOBAL);
while(true){
//Wait for gps response messages
if(lfcr){
delay_ms(200); //Wait for all messages
incmd=true; //Do not receive anymore messages
istr[len+1]='\0'; //Terminate received string with null character
disable_interrupts(int_rda);
strcpy(tstr,"$GPRMC");
index=strstr(istr,tstr);
if(index!=0)
{
strcpy(tstr,index);
i=0;
index=strtok(tstr,toks);
strcpy(cmd0,index);
while(index!=NULL){
i++;
index=strtok(NULL,toks);
if(i==1)strcpy(time,index);
if(i==2)strcpy(stats,index);
if(i==3)strcpy(lat,index);
if(i==4)strcpy(latd,index);
if(i==5)strcpy(lon,index);
if(i==6)strcpy(lond,index);
if(i==7)strcpy(knots,index);
if(i==8)strcpy(deg,index);
if(i==9)strcpy(date,index);
}
strcpy(tstr,"A");
if(strcmp(stats,tstr)==0)gotit=true;
else gotit=false;
kmph=atof(knots)*1.852;
tmdtlocal();
}
strcpy(tstr,"$GPGGA");
index=strstr(istr,tstr);
if(index!=0)
{
strcpy(tstr,index);
i=0;
index=strtok(tstr,toks);
strcpy(cmd0,index);
while(index!=NULL){
i++;
index=strtok(NULL,toks);
if(i==9)strcpy(ele,index);
}
}
incmd=false;
clr_buf();
} //if lfcr
//Do the output thing
if(gotit){
//***Here everthing is ready and current
//***I've used an LCD here, but you can do whatever you want!
}
else{
//***Here GPS is still scanning for satellites
//***My GPS module have a RTC, so that is the only thing that is current
}
}
} |
|
|