Nachdem mein "alter" Code nicht auf einem Pollin - ATmega32 - Board lief, habe ich diesen nun neu geschrieben ...
.. hier was fertiges inkl. Demoprogramm, Uhrzeit wird über Com1 ausgegeben.

Zur Info, hab noch Fehlerzähler implementiert ... und die Sekunden sind nun auch möglich. Uhrzeit dann fehlerfrei wenn Fehler == 0 && valid

Der Code ist absichtlich nicht auf Größe optimiert, verwendet also immer noch keine Bitfelder ... C für Beginners ist schon schwer genug, so bleibts lesbarer.

Viel Spaß beim Testen,
Vajk

Demo.c
Code:
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define __STDIO_FDEVOPEN_COMPAT_12 // fuer uart_putchar
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

#include "basdef_h.h"

//-------------------------------------------------------
// Source-Modues
#include "dcf77_h.h"

//-------------------------------------------------------
// prototypes
static void avr_init(void);

// avrdude -P /dev/ttyS0 -p m32 -c ponyser -U f:w:demo2.hex:i -F
// ^^ avrdude-sequenz für Pollin Board, das über die serielle 
//       via avrdude programmiert wird, unter SIDUX / DEBIAN
// Quelle: http://www.mobile-roboter.org/content/view/13/43/


#define USEUART


//-------------------------------------------------------

byte flag_INT1           = 0;
byte old_std             = 0;
byte old_min             = 0;
byte old_sec             = 0;
byte old_fehlcnt         = 0;
byte old_rxdatafehl      = 0;

#ifdef USEUART

// Gibt printf-daten auf die UART0 aus 9600 8 N1
// fdevopen(uart_putchar, NULL, 0); // 4 debugging -> use printf :-)
//-------------------------------------------------------
int uart_putchar(char c)
{
  // if(c == '\n') uart_putchar('\r'); Zeilenvorschunb und Wagenrücklauf 

  loop_until_bit_is_set(UCSRA, UDRE);
  
  UDR = c;

  return 0;
}
#endif

//-------------------------------------------------------
int main(void)
{
	avr_init();
	
   #ifdef USEUART
   fdevopen(uart_putchar, NULL, 0); // 4 debugging -> use printf :-)
   printf("\nProgrammstart");
   #endif

	for(;;)
	{
		dcf_auswertung();
		
      if(old_showdcf77sig != showdcf77sig)
		{
			old_showdcf77sig = showdcf77sig;
			
			if(showdcf77sig)
				PORTD |= (1 << PD5); // Licht an
			else
				PORTD &=~(1 << PD5); // Licht aus
		}
		
		if(DCF_time.valid) // sind die DCF - Daten überhaupt plausibel
		{	
			if(DCF_time.valid_min && DCF_time.valid_std) // Stunden und Minuteninformation auch
			{
				// dann darf auch ausgewertet werden
				// DCF_time.MESZ laß ich erstmal ausßen vor

            // nur einmal ausgeben ...
            if((DCF_time.std != old_std) || (DCF_time.min != old_min) || (DCF_time.sec != old_sec))
            {
               old_std = DCF_time.std;
               old_min = DCF_time.min;
               old_sec = DCF_time.sec;

               #ifdef USEUART
               printf("\n%02d:%02d:%02d %s", (int)DCF_time.std,
                                             (int)DCF_time.min,
                                             (int)DCF_time.sec,
                                             DCF_time.MESZ ? "MESZ" : "MEZ");

               if(DCF_time.valid_datum)
               {
                  printf("   %02d.%02d.%04d", (int)DCF_time.tag, (int)DCF_time.mon, DCF_time.year);
               }

               // wota Mo=1 .. So=7 nicht berücksichtigt

               if(DCF_time.fehlcnt || DCF_time.rxdatafehl)
                  printf("  Fehlbits: %02d / %02d", (int)DCF_time.fehlcnt, (int)DCF_time.rxdatafehl);
               #endif

               if((DCF_time.std >= 9) && (DCF_time.std <= 22))
                  PORTD |= (1 << PD6); // Licht an
               else
                  PORTD &=~(1 << PD6); // Licht aus
            }
         }
      }
      #ifdef USEUART
      else
      {
         if(DCF_time.fehlcnt || DCF_time.rxdatafehl)
         {
            if((DCF_time.fehlcnt != old_fehlcnt) || (DCF_time.rxdatafehl != old_rxdatafehl))
            {
               old_fehlcnt    = DCF_time.fehlcnt;
               old_rxdatafehl = DCF_time.rxdatafehl;

               printf("\nFehlbits: %02d / %02d", (int)DCF_time.fehlcnt, (int)DCF_time.rxdatafehl);
            }
         }
      }
      #endif


      if(flag_INT1 == 1)
      {
         flag_INT1 = 2; // durch diese "technik" ist beliebig lang Zeit, auf den Tastendruck zu reagieren
                        // ein einfaches ++ würde im Interrupt selbst stehen

         #ifdef USEUART
         printf("\n----- Taste2 ----- "); 

         // serielle Ausgabe dauert ja etwas .. 6 Byte = 48 Bit + 6 Bit = 5,6 ms bei 9600 BitspSec

         #endif               // außerdem ist die ser.Datenübertragung nicht synchron

         flag_INT1 = 0;
      }
	}

	return(0); // wird nie erreicht, da endlos for-schleife, aber weglassen führt zu compilerfehler
}

//-------------------------------------------------------
static void avr_init(void)
{
	// Gedächtnisstütze :-) of 4 copy & paste
	// DDRp [A,B,..]	= Datenrichtungsregister Bit gesetzt = Ausgang, sonst Eingang
	// PORTp			= Datenregister Ausgänge setzen, wenn als Eingang definiert, dann int. Pullup mit 1 aktiviert
	// PINp				= Eingangsadresse - Abfrage der Eingänge
	// Einzelne Bits mit (1 << x) mit x = [0..7]
	// Port an mit PORTp |= (1 << x)
	// Port aus mit PORTp &=~ (1 << x)

	// first: alles als Eing�ge 
	DDRA  = 0;	DDRB  = 0;	DDRC  = 0;	DDRD  = 0;

	DDRB  |= (1 << PB0) | (1 << PB1); // PB0,1 als Ausgänge
	DDRD  |= (1 << PD5) | (1 << PD6);

	// Interrupts mega128: S. 87 mega32: S. 66

	// INT0 = PD2
   //       DCF-INT0      Taster2 INT1
	MCUCR = (1 << ISC00) | (1 << ISC11); // INT0 - DCF77, both edges
	GICR  = (1 << INT0)  | (1 << INT1);  // INT0 aktivieren

	// Timer mega32: S. 80
	// 8Bit - Timer bei 16 MHz
	// für DCF overflowerkennung alle ~2,1ms
	// 16 Mhz  -> 2ms ist /1024 / 32
	// also CTC0 und Teiler durch 1024
	// TCCR0 = (1 << WGM01) | (1 << CS00) | (1 << CS02);
	// OCR0  = 32; 
   // TIMSK   |= (1 << OCIE0); // OutputCompareMatchInterrupt Enable    TOIE0); // Timer Interrupt -> 8 Bit -> Overflow bei 256 
   // oder via Timer 2
   // 1 / 16 Mhz * 256 * 128 = 2,048 ms
   TCCR2  = (1 << CS22) | (1 << CS20);
   TIMSK |= (1 << TOIE2);

   dcf_Init();

   // serielle Kommunikation aktiveren
   #ifdef USEUART
   // UCSRB  |= (1 << RXEN) | (1 << RXCIE);  // TXEN=TX an, RXEN=RX an, RXCIE=RXcomplete Int, TXCIE=TXdto.
   UCSRB  |= (1 << TXEN); // | (1 << TXCIE);     // TXEN=TX an, RXEN=RX an, RXCIE=RXcomplete Int, TXCIE=TXdto.
   UCSRC  |= (1 << USBS) | (3 << UCSZ0);  // asyncron 8N1
   UBRRH   = 0;
   #define USART_BAUD_RATE      9600
   #define USART_BAUD_SELECT  (F_CPU/(USART_BAUD_RATE*16l)-1)
   UBRRL = (unsigned char) USART_BAUD_SELECT;
   // UBRRL  = 51; // 103 fr 9600  || 51 fr 19200 || 25 fr 38400
   //                  16 fr 57,6k || 12 fr 76,8k ||  8 fr 115,2k - alles bezogen auf 16 MHz
   #endif

   sei(); // enable interrupts -> Global enable interrupt
}

//-------------------------------------------------------
// // grmpf SIGNAL(SIG_OVERFLOW0) // derzeit mit Teiler 128 -> alle ~2,1ms
// SIGNAL(SIG_OUTPUT_COMPARE0)// Compare T=255 und Vort.256 -> alle 4,08 ms
SIGNAL(SIG_OVERFLOW2)
{
   uint8_t tmp_sreg = SREG;
	cli(); // Interrupts aus

	dcf_timer_alle2ms048();
	
	SREG = tmp_sreg; // besser als sei(); -> Interrupts an
}

//-------------------------------------------------------
SIGNAL(SIG_INTERRUPT0) // Impuls via DCF77
{
	uint8_t tmp_sreg = SREG;
	cli(); // Interrupts aus
		
	dcf_interrupt();

	SREG = tmp_sreg; // besser als sei(); -> Interrupts an
}

//-------------------------------------------------------
SIGNAL(SIG_INTERRUPT1) // Taster 2
{
   if(!flag_INT1) // wenn semaphore noch nicht gesetzt
      flag_INT1 = 1; // na dann setzen
}
dcf77.h
Code:
#ifndef _dcf77_h_
#define _dcf77_h_

#define INPORT_INT PIND
#define PIN_INT    PD2

typedef struct
{
   byte valid;
   byte MESZ;
   byte sec;
   byte min;
   byte valid_min;
   byte std;
   byte valid_std;
   byte tag;
   byte wota;
   byte mon;
   int  year;
   byte valid_datum;
   byte fehlcnt;
   byte rxdatafehl;
}DCF_TIME;
   
#ifdef __dcf77_h_intern_

byte     dcf77modulaktiv	= 0;
byte     showsigdcf77aktiv	= 0;
byte     old_showdcf77sig	= 255;
byte     showdcf77sig		= 0;


DCF_TIME DCF_time;
long     lval_dcf_store;

void     dcf_Init(void);
void     dcf_timer_alle2ms048(void);
void     dcf_interrupt(void);
void     dcf_auswertung(void);

#else

extern byte	    dcf77modulaktiv;
extern byte	    showsigdcf77aktiv;

extern byte		 showdcf77sig;
extern byte	    old_showdcf77sig;

extern DCF_TIME DCF_time;
extern long     lval_dcf_store;
extern void		 dcf_Init(void);
extern void		 dcf_timer_alle2ms048(void);
extern void		 dcf_interrupt(void);
extern void		 dcf_auswertung(void);

#endif
#endif
dcf77.c
Code:
#include <inttypes.h>
#include <avr/io.h>
//#include <avr/signal.h>
//#include <avr/interrupt.h>
//#include <avr/delay.h>
#include <stdio.h> // fr printf
//#include <stdlib.h>
#include <string.h>
//-------------------------------------------------------

#include "basdef_h.h"

#define __dcf77_h_intern_
#include "dcf77_h.h"

byte bitbuffer[60];
byte bitauswertung[60];

int  flag_auswertung     = -1; // auswertung läuft erst ab 0
int  bitposition         = 0;
int  zeitzaehler         = 0;
byte signalrx            = 0;
byte datavalue           = 0;
byte rxdatafehl          = 0;
byte store_rxdatafehl    = 0;

void dcf_Init(void)
{
   lval_dcf_store = 0;
   memset(&DCF_time, 0, sizeof(DCF_TIME));
}

void dcf_timer_alle2ms048(void) // alle 2.048ms
{
   zeitzaehler++;

   // zaehlwert zw. 50ms und 100 ms bei 2.048ms = 24 .. 48 --- gewaehlt 0x020 = ~  65ms
   // zaehlwert zw.100ms und 200 ms bei 2.048ms = 48 .. 96 --- gewaehlt 0x040 = ~ 131ms
   // zaehlwert > 200ms             bei 2.048ms =     > 96 --- gewaehlt 0x064 = ~ 205ms
   // zaehlwert ~ 1060ms            bei 2.048ms =      520 --- gewaehlt 0x208 = ~1065ms

   byte SigVal =  INPORT_INT & (1 << PIN_INT); // INT - Port
   if(zeitzaehler == 0x20) // also Abtastaung mitten im 0-Bit
   {
      if(SigVal) // hier muß immer ein Signal sein 1..58 sec-Datenzeitbereich
      {
         signalrx  = 1;
         datavalue = 1; // Logisch 0
      }
      else
         rxdatafehl++;
   }
   if(zeitzaehler == 0x40) // also Abtastung mitten im 1-Bit-Datenzeitbereich
   {
      if(SigVal && signalrx)
         datavalue = 2; // Logisch 1
   }
   if(zeitzaehler == 0x64) // also Abtastung nach dem Datenzeitbereich
   {
      if(!SigVal && signalrx && datavalue) // kein Signal mehr, empfang und dataval
      {
         if(bitposition < 59)
         {
            bitbuffer[bitposition] = datavalue;
            bitposition++;
            datavalue              = 0;
            signalrx               = 0;
            DCF_time.sec++;
            DCF_time.sec = (DCF_time.sec < 60) ? DCF_time.sec : 60; // 60 nicht valid
         }
      }
   }
   if(zeitzaehler == 0x208) // wird nur erreicht, wenn 59 sec = leerübermittlung oder empfangsstörung
   {
      if(!SigVal) // kein Signal
      {
         store_rxdatafehl = rxdatafehl;         // Empfangsfehlerzaehler
         memcpy(bitauswertung, bitbuffer, 60);  // Datenbereich uebertragen
         flag_auswertung  = 1;                  // Zeitsequenz empfangen - Auswertung freigeben
      }

      // Neustart des Puffer
      memset(bitbuffer, 0, 60); // alle Felder ohne Empfangsinformation
      bitposition    = 0;
      DCF_time.sec   = 0;
      rxdatafehl     = 0;
   }
   // 8.4 sec kein Signal ... groesser muß der zaehler nicht werden, 0 abba auch nicht
   zeitzaehler = (zeitzaehler > 0x1000) ? 0x1000 : zeitzaehler;
}

void dcf_interrupt(void) // via Interrupt beide Flanken
{
   byte SigVal =  INPORT_INT & (1 << PIN_INT); // INT - Port
   if(SigVal) // also Beginn eines Datenbits
      zeitzaehler = 0;

   // für die Anzeige des DCF77-Signals
   showdcf77sig = SigVal; // !showdcf77sig;
}




void dcf_auswertung()
{
	if(flag_auswertung > 0)
	{
      int p, sum;
		memset(&DCF_time, 0, sizeof(DCF_TIME));
			
      DCF_time.rxdatafehl = store_rxdatafehl;
		DCF_time.valid      = 1;
      DCF_time.fehlcnt    = 0;

		for(p = 20; p < 59; p++)
		{
			if(bitauswertung[p] == 0)
            DCF_time.fehlcnt++;
      }

		if(DCF_time.valid && (bitauswertung[20] != 2)) // Startbit der Zeitinformation = immer Logisch 1 
			DCF_time.valid = 0; // Startbit fehlt

		if(DCF_time.valid)
		{
			DCF_time.MESZ =	((bitauswertung[17] == 1) && (bitauswertung[18] == 0));
			
			// 21-27: 7 Bits  Minute 1,2,4,8,10,20,40
			DCF_time.min  =	(bitauswertung[21] == 2) *  1 +
							(bitauswertung[22] == 2) *  2 +
							(bitauswertung[23] == 2) *  4 +
							(bitauswertung[24] == 2) *  8 +
							(bitauswertung[25] == 2) * 10 +
							(bitauswertung[26] == 2) * 20 +
							(bitauswertung[27] == 2) * 40;
			// 28:    1 Bit   Paritiy Minute - Bit 21-27
			sum = 0;
			for(p = 21; p <= 28; p++)
				sum += (bitauswertung[p] == 2);
			DCF_time.valid_min = !(sum % 2);
         if(DCF_time.min > 59)
            DCF_time.valid_min = 0;

			// 29-34: 6 Bits  Stunde 1,2,4,8,10,20
			DCF_time.std  =	(bitauswertung[29] == 2) *  1 +
							(bitauswertung[30] == 2) *  2 +
							(bitauswertung[31] == 2) *  4 +
							(bitauswertung[32] == 2) *  8 +
							(bitauswertung[33] == 2) * 10 +
							(bitauswertung[34] == 2) * 20;
			// 35:    1 Bit   Parity Stunde - Bit 29-34
			sum = 0;
			for(p = 29; p <= 35; p++)
				sum += (bitauswertung[p] == 2);
			DCF_time.valid_std = !(sum % 2);
         if(DCF_time.std > 23)
			   DCF_time.valid_std = 0;

			// 36-41: 6 Bits  Tag 1,2,4,8,10,20
			DCF_time.tag  =	(bitauswertung[36] == 2) *  1 +
							(bitauswertung[37] == 2) *  2 +
							(bitauswertung[38] == 2) *  4 +
							(bitauswertung[39] == 2) *  8 +
							(bitauswertung[40] == 2) * 10 +
							(bitauswertung[41] == 2) * 20;
				
			// 42-44: 3 Bits  Wochentag 1,2,4 - 1=Mo .. 7=So
			DCF_time.wota  =(bitauswertung[42] == 2) *  1 +
							(bitauswertung[43] == 2) *  2 +
							(bitauswertung[44] == 2) *  4;
							
			// 45-49: 5 Bits  Monat 1,2,4,8,10
			DCF_time.mon  =	(bitauswertung[45] == 2) *  1 +
							(bitauswertung[46] == 2) *  2 +
							(bitauswertung[47] == 2) *  4 +
							(bitauswertung[48] == 2) *  8 +
							(bitauswertung[49] == 2) * 10;
							
			// 50-57: 8 Bits  Jahr 2005+ 1,2,4,8,10,20,40,80
			DCF_time.year  =	(bitauswertung[50] == 2) *  1 +
							(bitauswertung[51] == 2) *  2 +
							(bitauswertung[52] == 2) *  4 +
							(bitauswertung[53] == 2) *  8 +
							(bitauswertung[54] == 2) * 10 +
							(bitauswertung[55] == 2) * 20 +
							(bitauswertung[56] == 2) * 40 +
							(bitauswertung[57] == 2) * 80 + 2000;
			// 58:    Paritiy Datum - Bit 35-57
			sum = 0;
			for(p = 36; p <= 58; p++)
				sum += (bitauswertung[p] == 2);
			DCF_time.valid_datum = !(sum % 2);
         if((DCF_time.tag  > 31) || (DCF_time.tag == 0) || 
            (DCF_time.wota >  7) ||
            (DCF_time.mon  > 12) || (DCF_time.mon == 0))
         {
            DCF_time.valid_datum = 0;
         }

         /*
			printf("\n%02d:%02d (%d/%d) - %02d.%02d.%04d (%d)", (int)DCF_time.std, (int)DCF_time.min, (int)DCF_time.valid_std,
                                                             (int)DCF_time.valid_min, (int)DCF_time.tag, (int)DCF_time.mon,
                                                             (int)DCF_time.year,      (int)DCF_time.valid_datum);
			23:44 (1/1) - 03.02.2006 (1)
			*/
		}
		/*
		else
		{
			printf("\n#");
			for(int i = 0; i < 60; i++)
			{
				switch(bitauswertung[i])
				{
					case 1 : printf("0"); break;
					case 2 : printf("1"); break;
					default: printf("_"); break;
				}
			}
			printf("#");
		}
		*/
		
		flag_auswertung = 0;
	}
}