DCF77 Signal mit Timer einlesen
Dienstag, 22. Mai 2012
 
 

PIC Mikrocontroller Forum  |  PIC Mikrocontroller  |  CCS Compiler  |  Timer (CCS)  |  DCF77 Signal mit Timer einlesen « vorheriges nächstes »
Seiten: [1] Nach unten Drucken
Autor Thema: DCF77 Signal mit Timer einlesen  (Gelesen 8258 mal)
 
Bernd_Fritz
Newbie
*
Offline Offline

Beiträge: 27


Mein Hobby


Profil anzeigen WWW
« am: Dezember 17, 2006, 20:08:22 »

Hallo,

Weihnachtszeit auch Programmierzeit,
ich möchte mit einem Timer das DCF77 Signal einlesen,
suche Beispiele mit dem CCS Compiler,
mein Prozessor ist der PIC16F690.
Wer kann mir mit Tips weiterhelfen ?

Gruß
Bernd_Fritz
 Augen rollen
Gespeichert

MFG
Bernd Fritz
Ramazuki
Newbie
*
Offline Offline

Beiträge: 37


Profil anzeigen
« Antworten #1 am: Dezember 17, 2006, 21:22:43 »

Salutti !

Also, Hier im Forum hats einen Thread, in welchem ich meinen
Code geklaut und angepasst habe :

http://www.fernando-heitor.de/component/option,com_smf/Itemid,120/topic,83.0/

Stark vereinfacht läuft's dahin hinaus, die Länge der Peaks / Sinks zu messen,
in einen Puffer abzufüllen und zu decodieren.

Dann kommen noch die Paritätabfrage und einen Abgleich mit einer Internen Uhr.

ACHTUNG : SEHR EXPERIMENTELL !!!!!!

Code:

#bit DCF = PortA.0
#bit LED = PortA.1 // Action --> LED PULSE

byte incomming_buffer[incomming_BUFFER_SIZE];


#inline // Zeit + Datum ausgeben
void show_time_dcf();

#inline // Zeit + Datum ausgeben
void show_time_rtc();

// DATA TYPES //////////////////////////////////////////////////////////////////
int1
loop,traeger,changes,falling,rising,gueltig,symbol,empfang,stimmt,syncbit;

int8
Zeiger,Pulse,

dcf_sekunde,dcf_minute,dcf_stunde,dcf_kalendertag,dcf_wochentag,dcf_monat,dcf_jahr,

sekunde,minute,stunde,kalendertag,wochentag,monat,jahr,

counter,zaehler,new,old,wait,dcf_minute_old,alarm,


runmode;
////////////////////////////////////////////////////////////////////////////////

#inline
// Setup  ////////////////////////////////////////////////////////////////////
void Setup() // Alles Rücksetzen + init
{ int i ;
for(i=0;i<=60;++i)incomming_buffer[i]=0; // buffer rücksetzen
dcf_sekunde = 0 ;
dcf_minute = 0 ;
dcf_minute_old = 0 ;
dcf_stunde = 0 ;
dcf_kalendertag = 0 ;
dcf_wochentag = 0 ;
dcf_monat = 0 ;
dcf_jahr = 0 ;

sekunde = 0;
minute = 0 ;
stunde =0 ;
kalendertag =0 ;
wochentag =0;
monat =0 ;
jahr =0;

syncbit = 0;



pulse = 0 ;
traeger = 0 ;
zeiger = 0 ;
gueltig = 0 ;
empfang = 0 ;
stimmt = 0 ;
runmode = 1 ; // START CLOCK
loop =0;
lcd_init();

lcd_gotoxy(1,1);
printf(lcd_putc,"\cDCF Initialized");
delay_ms(500);
lcd_gotoxy(1,1);
printf(lcd_putc,"\c");
show_time_dcf();
show_time_rtc();



}
////////////////////////////////////////////////////////////////////////////////

// show_time  //////////////////////////////////////////////////////////////////
#inline // Zeit + Datum ausgeben
void show_time_dcf()
{

lcd_gotoxy(1,1); // HOME POSI
printf(lcd_putc,"%02u:%02u:%02u|%02u.%02u.%02u", dcf_stunde,dcf_minute,dcf_sekunde,dcf_kalendertag,dcf_monat,dcf_jahr); // ZEIT Ausgeben

dcf_minute_old=dcf_minute ;
}

#inline // Zeit + Datum ausgeben
void show_time_rtc()
{

lcd_gotoxy(1,2); // HOME POSI

printf(lcd_putc,"%02u:%02u:%02u|%02u.%02u.%02u", stunde,minute,sekunde,kalendertag,monat,jahr); // ZEIT Ausgeben

}
////////////////////////////////////////////////////////////////////////////////

// show_sec  ///////////////////////////////////////////////////////////////////
#inline
void show_sec()
{
if((dcf_sekunde==60)&&(gueltig==1))
 {dcf_sekunde = 0 ;
 } // Wenn dcf_sekunde 0 + gueltig Zeit Ausgeben

else{
lcd_gotoxy(7,1);
printf(lcd_putc,"%02u",dcf_sekunde);

lcd_gotoxy(7,2);
printf(lcd_putc,"%02u",sekunde);
}


}

////////////////////////////////////////////////////////////////////////////////

// CLEAR  //////////////////////////////////////////////////////////////////////
void clear() // Alle Zeiten NULL
{
int i=0;
for(i=0;i<=60;++i)incomming_buffer[i]=0;


dcf_minute = 0 ;
dcf_stunde =0 ;
dcf_kalendertag =0 ;
dcf_wochentag =0;
dcf_monat =0 ;
dcf_jahr =0;









}
////////////////////////////////////////////////////////////////////////////////



void sync()
{
sekunde     = dcf_sekunde;
minute      = dcf_minute-1;
stunde      = dcf_stunde;
kalendertag = dcf_kalendertag;
monat       = dcf_monat;
jahr        = dcf_jahr;

}













// Decode DCF77  ///////////////////////////////////////////////////////////////
#inline
void BCD_Time() // BCD-Buffer zu Dezimal
{
if(incomming_buffer[21]) dcf_minute+=1;
if(incomming_buffer[22]) dcf_minute+=2;
if(incomming_buffer[23]) dcf_minute+=4;
if(incomming_buffer[24]) dcf_minute+=8;
if(incomming_buffer[25]) dcf_minute+=10;
if(incomming_buffer[26]) dcf_minute+=20;
if(incomming_buffer[27]) dcf_minute+=40;
// dcf_stunden
if(incomming_buffer[29]) dcf_stunde+=1;
if(incomming_buffer[30]) dcf_stunde+=2;
if(incomming_buffer[31]) dcf_stunde+=4;
if(incomming_buffer[32]) dcf_stunde+=8;
if(incomming_buffer[33]) dcf_stunde+=10;
if(incomming_buffer[34]) dcf_stunde+=20;
// dcf_kalendertag
if(incomming_buffer[36]) dcf_kalendertag+=1;
if(incomming_buffer[37]) dcf_kalendertag+=2;
if(incomming_buffer[38]) dcf_kalendertag+=4;
if(incomming_buffer[39]) dcf_kalendertag+=8;
if(incomming_buffer[40]) dcf_kalendertag+=10;
if(incomming_buffer[41]) dcf_kalendertag+=20;
// dcf_wochentag
if(incomming_buffer[42]) dcf_wochentag+=1 ;
if(incomming_buffer[43]) dcf_wochentag+=2 ;
if(incomming_buffer[44]) dcf_wochentag+=4 ;
// dcf_monat
if(incomming_buffer[45]) dcf_monat+=1 ;
if(incomming_buffer[46]) dcf_monat+=2 ;
if(incomming_buffer[47]) dcf_monat+=4 ;
if(incomming_buffer[48]) dcf_monat+=8 ;
if(incomming_buffer[49]) dcf_monat+=10 ;
// dcf_jahr
if(incomming_buffer[50]) dcf_jahr+=1 ;
if(incomming_buffer[51]) dcf_jahr+=2 ;
if(incomming_buffer[52]) dcf_jahr+=4 ;
if(incomming_buffer[53]) dcf_jahr+=8 ;
if(incomming_buffer[54]) dcf_jahr+=10 ;
if(incomming_buffer[55]) dcf_jahr+=20 ;
if(incomming_buffer[56]) dcf_jahr+=40 ;
if(incomming_buffer[57]) dcf_jahr+=80 ;
}
////////////////////////////////////////////////////////////////////////////////





// Check Buffer  ///////////////////////////////////////////////////////////////
int check_buffer()
{
int par_min = 0;
int i;

for(i=21;i<=27;i++)
 {
  par_min = par_min + incomming_buffer[i];
 }
 if ((!incomming_buffer[0])&(incomming_buffer[20])) // bit0=0 and bit20=1
  {
    if ((!(par_min % 2))&(incomming_buffer[28]))
      {
       return 1;
      }
  }

 else
   {
    return 0;
   }
}
////////////////////////////////////////////////////////////////////////////////


// Timeout  ////////////////////////////////////////////////////////////////////
#inline
void Timeout() // Wenn die lücke kommt und bis 59 gezählt wurde :-)
{ int i;
if (zeiger==59)
{
gueltig=1; // buffer inhalt gueltig
dcf_sekunde = 59;

bcd_time(); // Buffer auswerten
if (syncbit==0) {sync(); syncbit=1;}

show_time_dcf();

clear();
//if(runmode==1)show_sec() ;



//if (check_buffer())
//   {
//    clear(); // alles rücksetzen
//    bcd_time(); // Buffer auswerten
//    show_time();
//   }
// else
//   {
//    lcd_gotoxy(1,1);
//    show_time();
 //   printf(lcd_putc,"/c Bad DCF");
 //   show_bits();
//   }



}
else {gueltig=0;}
Zeiger =0 ;
if(runmode==1&&!stimmt)
 if(gueltig)
  {
 //  lcd_gotoxy(1,1);
 //  printf(lcd_putc,"\2 DCF Auswertung ");

  }
 else
 {
//  lcd_gotoxy(1,1);
//  printf(lcd_putc,"\2 DCF Sync aktiv ");

  };
 }

////////////////////////////////////////////////////////////////////////////////


// Flanken-Erkennung  //////////////////////////////////////////////////////////

#inline // dcf_sekunden ausgeben
void flanken_erkennung()
{
new = DCF ;
changes = old^new ;
falling = changes&~new;
rising = changes&new;
old = new ;
if(changes)
{
if(rising)
{
if(Zeiger==60){Zeiger =0;}
if (wait <= 7)
   {
    incomming_Buffer[zeiger]=0;
//  printf(lcd_putc,"\c");
//    lcd_gotoxy(15,1);
//   printf(lcd_putc,"B%02u:%01u",zeiger,incomming_Buffer[zeiger]);
//   printf(lcd_putc,"\2Wait : %03u",wait);

   }
else
   {
    incomming_Buffer[zeiger]=1 ;
//    printf(lcd_putc,"\c");
//    lcd_gotoxy(15,1);
//    printf(lcd_putc,"B%02u:%01u",zeiger,incomming_Buffer[zeiger]);
//   printf(lcd_putc,"\2Wait : %03u",wait);
    }

++zeiger;
++dcf_sekunde;
show_sec();

led=0;}
else{

 if(runmode==1);
led =1;
}

wait = 0;

set_timer0(0);

}

}



















////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
//  -=Process Zero Drift Real Time Clock Information=-
//
// Most algorithms configure the timer to generate an interrupt every 100ms, and
// then count the number of interrupts. The problem in that approach is that most
// clock frequencies can't be divided by 256 and you don't get an exact 100ms.
// The small errors will add up to an error of several seconds a day.
//
// The algorithm presented here is exact in the long run because it doesn't
// count the number of interrupts but counts the number of clock cycles.
////////////////////////////////////////////////////////////////////////////////

int32 Ticker;

void Initialize_RTC(void)
{
  Ticker = TIMER1_FREQUENCY;                  // initialize clock counter to number of clocks per second
  setup_timer_1( T1_INTERNAL | T1_DIV_BY_1 ); // initialize 16-bit Timer1 to interrupt
                                              // exactly every 65536 clock cycles
                                              // (about 76 times per second)
  enable_interrupts( INT_TIMER1 );            // Start RTC
}
////////////////////////////////////////////////////////////////////////////////

// INTERRUPT TIMER0  ///////////////////////////////////////////////////////////
#int_rtcc // INTERRUPT RTCC ( TIMER 0 )

void TIMER_Flanken() // Timer für messung
{
++wait;

flanken_erkennung();
if (wait >= 78)
 {

 // lcd_gotoxy(1,1);
 // printf(lcd_putc,"\cTimeout  : %02u",wait);
  Timeout();
  wait =0 ;
  dcf_sekunde = 0;
 }

}
////////////////////////////////////////////////////////////////////////////////

// INTERRUPT TIMER1  ///////////////////////////////////////////////////////////
#int_TIMER1
void TIMER1_isr()
{
  Ticker -= 65536;                        // Decrement ticker by clocks per interrupt
  if ( Ticker < 65536 )                   // If second has expired
  {  Ticker += TIMER1_FREQUENCY;          //   Increment ticker by clocks per second
     sekunde++;                                    //   Increment number of seconds
     show_sec();
if (sekunde == 60)
    { minute++; sekunde = 0; //show_time_rtc();
     if(minute == 60)
        {stunde++; minute=0;
         if(stunde == 24)
            {kalendertag++; stunde=0;
             if ( (kalendertag == 30 && monat==2)
                  || (kalendertag == 31 && (monat==4 || monat==6 || monat==9 || monat==11 ))
                  || (kalendertag == 32) )
                     {monat++;kalendertag=0;}
                      if(monat == 13) {kalendertag++; monat=0;}
            }
          }
     }














  }
}

////////////////////////////////////////////////////////////////////////////////


Gespeichert
Ramazuki
Newbie
*
Offline Offline

Beiträge: 37


Profil anzeigen
« Antworten #2 am: Dezember 17, 2006, 21:32:53 »

Hier noch ein kleines Excel-File.. Habs für mich geschrieben,
um die Empfangenen Bits zu überprüfen, und sollte eigentlich
funktionieren. Einfach in den violetten Teil die einzelnen
Bits abfüllen. Falls die Pariräten nicht OK sind, färbt
sich der Hintergrund rot..

* DCF.xls (23 KB - runtergeladen 251 Mal.)
Gespeichert
Bernd_Fritz
Newbie
*
Offline Offline

Beiträge: 27


Mein Hobby


Profil anzeigen WWW
« Antworten #3 am: Dezember 17, 2006, 21:41:36 »

Hallo Ramazuki,

vielen Dank, das versuche ich mal mit einem PIC16F690
hinzubekommen. Eine LCD Anzeige sowie die RS232 Übertragung zum PC-Terminal funktioniert bereits mit diesem PIC.

Gruß Bernd
 L&#228;chelnd
Gespeichert

MFG
Bernd Fritz
Bernd_Fritz
Newbie
*
Offline Offline

Beiträge: 27


Mein Hobby


Profil anzeigen WWW
« Antworten #4 am: Dezember 25, 2006, 11:04:25 »

Hallo,

habe eine Lösung gefunden, die ich hier zur Diskusion stellen möchte. Was mir besonders geholfen hat ist die DCF77.xls von Ramazuki Im Anhang befinden sich mein Quellcode und die Header Files meiner DCF77 Uhr. Die Ausgabe erfogt über ein LCD-Display oder der RS232 Schnittstelle. Was im Programm noch fehlt ist die Paritätserkennung!!  Benutzt wird der Prozessor PIC16F690 und CCS-Compiler.
Code: (css)
/**************************************************************************
 * ---------      Interruptsevice Rutine - Timer1               ----------*
**************************************************************************/
#int_TIMER1
void uberlauf_timer1 (void)           // hier die Timer Überläufe erfassen
{timer1_uberlauf++;}               
/**************************************************************************
 * ---------      Interruptsevice Rutine - Impuls einlesen      ----------*
 **************************************************************************/
#int_ext                                       // Interrupt service Routine
void interrupt (void)
 {
  if (flanke)                                  // wenn gesetzt dann Impuls Ende erkannt
   { setup_timer_1(T1_DISABLED);               // Timer stop
     dcf77_start_bit=timer1_uberlauf;          // den Überlauf hier abspeichern
     timer1_uberlauf=0;                        // lösche für neue Messung
     timer1_H=TMR1H;                        // abspeichern - high Byte Timer
     impuls_ok=1;                              // Merkbit der Impuls liegt an
     restart_wdt();                               // Watchdog zurücksetzen
     ext_int_edge(L_TO_H);                     // Flanke umstellen für (Anfang-Impuls)
     setup_timer_1(T1_INTERNAL|T1_DIV_BY_4);   // Timer wieder aktiv           
     flanke=0; }                               // lösche Merkbit neue Messung     
  else
   { set_timer1(0);                            // lösche Timer * 2µs
     ext_int_edge(H_TO_L);                     // Flanke umstellen für (Ende-Impuls)
     flanke=1; }                               // setze Merkbit zum abspeichern
 }

* DCF77.c (17.09 KB - runtergeladen 514 Mal.)
* DCF77.h (7.92 KB - runtergeladen 304 Mal.)
* LCD4x20.H (9.3 KB - runtergeladen 269 Mal.)
« Letzte Änderung: Januar 01, 2007, 21:59:37 von Bernd_Fritz » Gespeichert

MFG
Bernd Fritz
Bernd_Fritz
Newbie
*
Offline Offline

Beiträge: 27


Mein Hobby


Profil anzeigen WWW
« Antworten #5 am: Dezember 25, 2006, 12:21:05 »

Hallo,

hier noch der Schaltplan und wie die LCD-Anzeige aussieht.

Gruß Bernd



* Schaltplan_DCF77.jpg (68.75 KB, 597x534 - angeschaut 726 Mal.)
Gespeichert

MFG
Bernd Fritz
Bernd
Globaler Moderator
Hero Member
*****
Offline Offline

Beiträge: 3815



Profil anzeigen
« Antworten #6 am: Dezember 25, 2006, 22:13:58 »

Kann es sein, daß Du die Datei DCF77.h vergessen hast? 

Noch ein genereller Hinweis in Bezug auf "multi-statements" Makros:

Zitat
Code:
#define LCD_BLANK() { lcd_send_byte(0,1);delay_ms(2);}

Diese Makro wird in folgender Situation einen Fehler verursachen, der eventuell nicht einfach zu finden ist:

Code:
if (foo)
    LCD_BLANK();
else
    bar();

Nach der Expansion des Makros ergibt sich:

Code:
if (foo)
{                         // Makro
    lcd_send_byte (0, 1); // Makro
    delay_ms (2);         // Makro
}                         // Makro
;                         // <<- "zusätzliches" Semikolon, leeres Statement
else                      // else somit hier syntaktisch falsch --> Compiler-Fehlermeldung
    bar();

Daher sollten derartige Makros immer in eine do-while Schleife "verpackt" werden.

Code:
#define LCD_BLANK() do { lcd_send_byte(0,1);delay_ms(2);} while (0)

Damit funktioniert das Makro immer wie erwartet.


Viele Grüße

Bernd
Gespeichert

Bernd_Fritz
Newbie
*
Offline Offline

Beiträge: 27


Mein Hobby


Profil anzeigen WWW
« Antworten #7 am: Dezember 27, 2006, 08:22:32 »

Hallo Bernd,

die fehlende DCF77.H habe ich oben ergänzt. Die Ausgabe über RS232 ist in der obrigen Version als Kontrollfunktion, kann jedoch jederzeit mit den entsprecheden Ausgabe Variablen vesehen werden.
Das mit dem Macro war mir so noch nicht bekannt.
Zur Zeit versuche ich die Paritäts Prüfung einzufügen. Dies steht aber in einem anderen Thema.
Noch eine Frage was sind ..Code-Tags?

Gruß
Bernd Fritz
Gespeichert

MFG
Bernd Fritz
Bernd
Globaler Moderator
Hero Member
*****
Offline Offline

Beiträge: 3815



Profil anzeigen
« Antworten #8 am: Dezember 27, 2006, 16:49:22 »

Zitat
Noch eine Frage was sind ..Code-Tags?

Die Code-Tags erhalten die Formatierung des von Dir geposteten Quellcodes. Du kannst sie auf mehrere Arten in Deinen Post einfügen:

  • Manuell: Vor den Quellcode [ code ] und am Ende des Quellcodes  [ /code ] eintippen (ohne die Leerzeichen innerhalb der eckigen Klammern)
  • auf das "Rautensymbol oben rechts (über den Smileys) im Eingabefenster klicken
  • das Pulldown-Menü oben links (GeSHi) verwenden und die Programmiersprache auswählen


Viele Grüße

Bernd
Gespeichert

Bernd_Fritz
Newbie
*
Offline Offline

Beiträge: 27


Mein Hobby


Profil anzeigen WWW
« Antworten #9 am: Dezember 28, 2006, 23:45:27 »

Hallo Zusammen,

wenn Bedarf besteht sende ich Euch den Schaltplan im Eagle Format, ein Layout dazu habe ich noch nicht erstellt. Zur Zeit ist alles noch auf dem Microchip Experimentier Bord aufgebaut.

Gruß
Bernd Fritz
Gespeichert

MFG
Bernd Fritz
Bernd_Fritz
Newbie
*
Offline Offline

Beiträge: 27


Mein Hobby


Profil anzeigen WWW
« Antworten #10 am: Dezember 28, 2006, 23:50:15 »

Zitat
Noch eine Frage was sind ..Code-Tags?

Die Code-Tags erhalten die Formatierung des von Dir geposteten Quellcodes. Du kannst sie auf mehrere Arten in Deinen Post einfügen:

  • Manuell: Vor den Quellcode [ code ] und am Ende des Quellcodes  [ /code ] eintippen (ohne die Leerzeichen innerhalb der eckigen Klammern)
  • auf das "Rautensymbol oben rechts (über den Smileys) im Eingabefenster klicken
  • das Pulldown-Menü oben links (GeSHi) verwenden und die Programmiersprache auswählen


Viele Grüße

Bernd
Zitat
Danke für die Hinweise, habe als Neuling nicht darauf geachtet, was es für Möglichkeiten gibt.
Gespeichert

MFG
Bernd Fritz
Bernd_Fritz
Newbie
*
Offline Offline

Beiträge: 27


Mein Hobby


Profil anzeigen WWW
« Antworten #11 am: Januar 01, 2007, 22:29:25 »

Hallo Zusammen,

Das einlesen des DCF77 Signals mit einem Timer funktioniert.
Verwendet wurde der PIC16F690.
Abschließend könnt ihr euch den Schaltplan (Eagle) runterladen.
In der ZIP Datei befinden sich auch die Header Files sowie der CCS-Quell Code meiner DCF77 Uhr. ( die Datei befindet sich jetzt im nächsten Beitrag)

Die Ausgabe erfolgt auf ein LCD-Display oder auf ein PC-Terminal Programm über die RS232 Schnittstelle.

Vielen Dank
Bernd Fritz    Schockiert:
« Letzte Änderung: Januar 25, 2007, 20:52:35 von Bernd_Fritz » Gespeichert

MFG
Bernd Fritz
Bernd_Fritz
Newbie
*
Offline Offline

Beiträge: 27


Mein Hobby


Profil anzeigen WWW
« Antworten #12 am: Januar 21, 2007, 11:33:18 »

Hallo,

in den alten Unterlagen sind noch ein paar Fehler drin. Die Leitungen zur LCD-Anzeige sind falsch angeschlossen, meine Paritätsprüfung stimmte auch nicht und beim Update auf dem CCS-Compiler V4.020 gab es andere Einstellwerte vom Watchdog.
Ein Dankeschön an Euch die mir zu diesem Thema DCF77 mit Timer einlesen geholfen haben.

* Update_DCF77.zip (33.18 KB - runtergeladen 321 Mal.)
Gespeichert

MFG
Bernd Fritz
The Puma
Newbie
*
Offline Offline

Beiträge: 7


Profil anzeigen
« Antworten #13 am: Oktober 01, 2007, 19:13:23 »

Ich mochte denn pic program fur einen PIC18F4620 verwenden.
Geht dass, und wass mus geanderd werden.

Hoffendlich kann mich jemanden weiter helfen

Gespeichert
Seiten: [1] Nach oben Drucken 
« vorheriges nächstes »
Gehe zu:  

Powered by MySQL Powered by PHP Made for Mozilla (Firefox) Made for Internet Explorer
Seite erstellt in 0.044 Sekunden mit 18 Zugriffen.
 
Top! Top!