DCF77 Driver

Post your requests and ideas on the future development of mikroPascal PRO for AVR.
Post Reply
Author
Message
corado
Posts: 399
Joined: 28 Mar 2009 11:03

DCF77 Driver

#1 Post by corado » 15 Oct 2009 19:11

Why not a DCF 77 Lib ?


DCF77 is in Europe the same as WWV. Transmitting Time/Date via VLF (77.7 kc).

A Driver for DCF77 ist a good Idea

User avatar
anikolic
mikroElektronika team
Posts: 1775
Joined: 17 Aug 2009 16:51
Location: Belgrade
Contact:

#2 Post by anikolic » 16 Oct 2009 15:30

Hi,
I have informed our developers of your suggestions. Thank you for your support.

Best regards,
Aleksandar
Web Department Manager

corado
Posts: 399
Joined: 28 Mar 2009 11:03

#3 Post by corado » 16 Oct 2009 15:47

Thanks, this is a good thing, because the DCF Signal is used for many Thinks.
Boardcomputer for my Elecetric car, Computer to control HEater, Weather Stations and so on

noordschanser
Posts: 6
Joined: 27 Sep 2010 14:04

Re: DCF77 Driver

#4 Post by noordschanser » 27 Sep 2010 15:04

DCF77 decode example pascal code AVR

Code: Select all

Version:0.9 StartHTML:0000000105 EndHTML:0000140107 StartFragment:0000001460 EndFragment:0000140091 
program timen;

{atemga 128
dcf77 conrad print aangesloten op interupt ingang E4 en E5 brug one pull-up needed
 port C LED ON
 C_0 = time pul 1sec by atmega 128 16bit clock
 C_1 = alarm bit = compare time
 C_2 = DCF77 puls, short= 0 long = 1

    }
{ Declarations section }
    type  tijd = record
   dag,
   uur,
    minuut,
    seconde: byte;
    txt: array[20] of char;
end;
 // wekker
type  wekker = record
    status: byte;
    alarm :tijd;
    huidige:tijd;
{   on_off : sbit at status.B0;
    aktief (teller loopt) b1.;
    alarm : sbit at status.B2;
    stil/setup  : sbit at status.B3;
    wijziging in sec .b4
    wijziging in min = b5
    wijz. uur =b6
    zijz. dag =b7
    }
  end;



var
  time : wekker ;
 tel,seconde,minuut,uur,dag,knop : byte;
   pulsduur:word;
   intercept, error:byte;
   dcf77dataold:  array[0..59] of boolean;
   dcf77data:  array[0..59] of boolean;
   dcf77tijd:tijd;
   newdata:byte;
   bitnummer: byte;
   
   
   
   // Led lampjes, external connections
var on_led     : sbit at PORTC0_bit;
var pieper     : sbit at PORTC1_bit;
var on_led_clk     : sbit at PORTC2_bit;




procedure setup_16_bit_timer();

const
  Fio : dword = 1;    //counter sec=01ec : freq=1/T=1/1= 1hertz

  // mimimaal is 1hz

var
  prescaler: word;  //1=2^0, 8=2^3, 32=2^5, 64=2^6, 128, 256, or 1024 afhankelijk uP
  deler:dword;
  clk,deler_ber :dword;
  clk_io :dword;

 begin
 //bereken prescaler HZ
    clk := (1000*Clock_kHz());  //haal clock freq op uit microproccessor
    deler_ber :=  clk  div Fio; // deel uP clock door gewente IO Frequentie = deler waarde
    deler:= (deler_ber  div 65535)+1; //in HZ 65535 $FFFF =grootste vermenigvuldiger OCR1A (H+L)
    if deler<=1024 then prescaler:= 1024;
    if deler<=256 then prescaler:= 256;
    if deler<=64 then prescaler:= 64;
    if deler<=8 then prescaler:= 8;
    if deler<=1 then prescaler:= 1;
 // set prescaler automatisch
           case prescaler of
     1:begin
        TCCR1B.cs10:= 1;
        TCCR1B.CS11:= 0;
        TCCR1B.CS12:= 0;
        end;
     8:begin
        TCCR1B.cs10:= 0;
        TCCR1B.CS11:= 1;
        TCCR1B.CS12:= 0;
        end;
     64:begin
        TCCR1B.cs10:= 1;
        TCCR1B.CS11:= 1;
        TCCR1B.CS12:= 0;
        end;
     256:begin
        TCCR1B.cs10:= 0;
        TCCR1B.CS11:= 0;
        TCCR1B.CS12:= 1;
        end;
    1024:begin
        TCCR1B.cs10:= 1;
        TCCR1B.CS11:= 0;
        TCCR1B.CS12:= 1;
        end;
  end; //case prescaler

//Timer/Counter Control Register – TCCR1
     TCCR1A.wgm10 :=0;
     TCCR1A.wgm11 :=0;
     TCCR1B.wgm12 :=1;  // (normal mode)  mode 4 CTC compare ocr1a
     TCCR1B.WGM13 :=0;

// restand uit teller topv TCNT2    mag niet groter zijn dan  65535 $FFFF
//set OCR compare waarde
     clk_io := deler_ber div prescaler;
     if (clk_io>0)  then clk_io:=clk_io-1;
     OCR1AH:= HI(clk_io);
     OCR1AL:= LO(clk_io);

 //set outpout  CTC
     TCCR1A.COM1A1:= 1; // OC1A/OC1B on compare match
     TCCR1A.COM1A0:=0;
     TCCR1A.COM1B1:= 1;
     TCCR1A.COM1B0:=0;
 //set interupt
     TIMSK.OCIE1A:=1; // Timer/Counter1, Output Compare A Match Interrupt Enable


  end; // timer 16 bit setup

  procedure Timer1comparematch(); org $0018 ;    //atmega 128 $0018,  atmega8 $0006 TIMER1 COMPA Timer/Counter1 Compare Match A
  var tel :byte;
  begin
    // if time.status and %00000010 = %00000010 then
   //   begin //wekker aan
           //  if time.status and %00010000 = %00010000 then portA0_bit:= not portA0_bit;// update display
            if time.huidige.seconde<59 then begin
                 inc(time.huidige.seconde);
                  time.status :=time.status or  %00010000; // zet wijzigings b4=sec op 1
         end else begin
          time.huidige.seconde:=0;
          if  time.huidige.minuut<59 then begin
                      inc(time.huidige.minuut);
                      time.status :=time.status or  %00100000; // zet wijzigings b5=min op 1
           end else begin
                      time.huidige.minuut:=0;
                      time.huidige.seconde:=0;
                 if  time.huidige.uur<24 then begin
                      inc(time.huidige.uur);
                       time.status :=time.status or  %01100000; // zet wijzigings b6=uur en b5=min op 1
                 end else begin
                              time.huidige.uur:=0;
                        end;
                end; //minuut
          end;
          if   (time.huidige.seconde = time.alarm.seconde) and
               (time.huidige.minuut = time.alarm.minuut) and
               (time.huidige.uur = time.alarm.uur)
                         then  time.status := time.status or  %11100100; // set alarm b2

  //  end; //wekker aan


  end;  // einde comp interupt


procedure setuppulsduurmeting();

// timer 0
//De pulsen zijn ofwel 100 ms ofwel 200 ms in lengte, waarbij de lange pulsen een binaire één voorstellen, en de korte een nul.
// 10msec =1/10=0,1kH=100hz
const
  Fio : dword = 100;    //counter sec=01ec : freq=1/T=1/1= 1hertz



var
  prescaler: word;  //1=2^0, 8=2^3, 32=2^5, 64=2^6, 128, 256, or 1024 afhankelijk uP
  deler:dword;
  clk,deler_ber :dword;
  clk_io :dword;

 begin
 //bereken prescaler HZ
    clk := (1000*Clock_kHz());  //haal clock freq op uit microproccessor
    deler_ber :=  clk  div Fio; // deel uP clock door gewente IO Frequentie = deler waarde
    deler:= (deler_ber  div 255)+1; //in HZ 255 $FF =grootste vermenigvuldiger OCR0
    if deler<=1024 then prescaler:= 1024;
    if deler<=256 then prescaler:= 256;
    if deler<=64 then prescaler:= 64;
    if deler<=8 then prescaler:= 8;
    if deler<=1 then prescaler:= 1;
 // set prescaler automatisch
           case prescaler of
     1:begin
        TCCR0.cs00:= 1;
        TCCR0.CS01:= 0;
        TCCR0.CS02:= 0;
        end;
     8:begin
        TCCR0.cs00:= 0;
        TCCR0.CS01:= 1;
        TCCR0.CS02:= 0;
        end;
     64:begin
        TCCR0.cs00:= 1;
        TCCR0.CS01:= 1;
        TCCR0.CS02:= 0;
        end;
     256:begin
        TCCR0.cs00:= 0;
        TCCR0.CS01:= 0;
        TCCR0.CS02:= 1;
        end;
    1024:begin
        TCCR0.cs00:= 1;
        TCCR0.CS01:= 0;
        TCCR0.CS02:= 1;
        end;
  end; //case prescaler
  
  // atmega 128
  TCCR0.WGM00:=0;
  TCCR0.WGM01:=0;

//   interupt op  8mzh/(1024*255)=7812hz => 0,0327  sec  => 32ms
   TIMSK.TOIE0:=1; // set interupt overflow bit
  end; // timer 0, 8 bit setup

  procedure telpulsduur(); org $0020 ;  //atmega128 $0020, atmeg 8 0x009 TIMER0 OVF Timer/Counter0 Overflow

  begin
     inc(pulsduur);
  end;

  procedure setupintercept_puls();

  begin
    //atmega 128
    // pin PE4
     //Interrupt 4 Sense Control heeft togle
    EICRB.ISC40  :=0 ;// Any logical change on INT1 generates an interrupt request.
    EICRB.ISC41 := 1;  //10  The falling edge between two samples of INTn generates an interrupt
   // EIMSK :=%00010000;

    //pin pE5
    EICRB.ISC50  :=1 ;    //  1 1 The rising edge of INTn generates asynchronously an interrupt request
    EICRB.ISC51  :=1 ;
    // set interupt bit03 en bit04
     EIMSK :=%00110000;
   end;
   
   procedure interceptpuls(); org $000A; //atmega128 $000A INT4 External Interrupt Request 4 , atmega8 0x001 INT0 External Interrupt Request 0

   var pulslengte:word;

     begin

          on_led_clk :=  0;
          pulslengte:= pulsduur; //   duur/32ms
           pulsduur:=0;
 //De pulsen zijn ofwel 100 ms ofwel 200 ms in lengte, waarbij de lange pulsen een binaire één voorstellen, en de korte een nul.
           if (pulslengte>10) and (pulslengte <40 ) // puls <120ms
                   then begin
                            intercept:=0 ;
                            dcf77data[bitnummer]:=0;
                            inc( bitnummer);
                        //    UART1_Write_Text('L');
                        end;
               if pulslengte >40 //and pulslengte<8 // puls >120ms <240ms
                   then  begin
                            intercept:=1 ;
                            dcf77data[bitnummer]:=1;
                            inc( bitnummer);
                          //  UART1_Write_Text('H');
                        end;

                  //    UART1_Write(pulslengte);
                {if pulslengte >8 and pulslengte<17 // puls >240ms <544ms
                   then  intercept=1 ;}

          if bitnummer>60 then bitnummer:=0;

     end;
     
   procedure interceptrisingedge(); org $000C; //atmega128 $$000C INT5 External Interrupt Request 4 , atmega8 0x001 INT1 External Interrupt Request 

   var pulslengte:word;

     begin
                      on_led_clk :=  1;
                   pulslengte:=pulsduur;
                 // UART1_Write_Text('L');
                  // UART1_Write(pulslengte);
                   if pulslengte>230 then begin
                       // nieuwe reeks
                       dcf77dataold:= dcf77data;
                       newdata:=1;
                       bitnummer:=0;
                       
                        UART1_Write_Text('nieuw');
                        UART1_Write($0D);
                   end;
                   pulsduur:=0; // start met tellen
        end;
   
   procedure decodedcf77();
       var crc,teller:byte;
    txt: string[4];
    var getal, dagvdweek,maand,jaar:byte;
  begin
      error:=0;
      dcf77tijd.seconde:=0;
          { 0= M Minuutmarkering
1-14  gereserveerd
15 R 1 als reserve-zendantenne in gebruik is
16 A1 aankondiging omschakeling zomer/wintertijd
17-18 Z1, Z2 01 tijdens wintertijd, 10 tijdens zomertijd
19 A2 aankondiging schrikkelseconde
20 S Start van tijdsbericht, altijd 1
21-24  eenheden minuten
25-27  tientallen minuten
28 P1 controlesom van bit 21-27
29-32  eenheden uren
33-34  tientallen uren
35 P2 controlesom bit 29-34
36-39  eenheden datum
40-41  tientallen datum
42-44  dag van de week
45-48  eenheden maand
49  tiental maand
50-53  eenheden jaartal (00..99)
54-57  tientallen jaartal (00..99)
58 P3 controlesom bit 36-57
(59) - ontbrekende impuls; markeert einde van een minuut}
     if  dcf77dataold[15]=1 then begin
                                         UART1_Write_Text('reserve zender');
                                          UART1_Write($0D);
     end;
     if  dcf77dataold[16]=1 then begin
                               UART1_Write_Text('aankondiging omschakeling zomer/wintertijd');
                               UART1_Write($0D);
     end;
     if  (dcf77dataold[17]=1) and  (dcf77dataold[18]=0) then begin
                 UART1_Write_Text('Zomertijd');
                 UART1_Write($0D);
     end;
     if  (dcf77dataold[17]=0) and  (dcf77dataold[18]=1) then begin
                UART1_Write_Text('wintertijd');
                 UART1_Write($0D);
     end;
     if  dcf77dataold[19]=1 then begin
                UART1_Write_Text('aankondiging schrikkelseconde');
                 UART1_Write($0D);
     end;
     if  dcf77dataold[20]=1 then begin
                  UART1_Write_Text('de tijd is:');
                   UART1_Write($0D);
                   end else error:=1;
         getal:=0;
         getal:= dcf77dataold[24] ;
         getal:= getal shl 1;
         getal:=getal+dcf77dataold[23] ;
         getal:= getal shl 1;
         getal:=getal+dcf77dataold[22] ;
         getal:= getal shl 1;
         getal:=getal+dcf77dataold[21];
         if dcf77dataold[25] then getal := getal +10 ;
         if dcf77dataold[26] then getal := getal +20 ;
         if dcf77dataold[27] then getal := getal +40 ;
         crc:=0;
         for teller:=21 to 27 do crc:=crc+ dcf77dataold[teller];
         crc:=crc and %00000001;
         if crc<>dcf77dataold[28] then begin
                               error:=error+2; // set 2e error bit;
                               dcf77tijd.minuut:=0;
         end   else dcf77tijd.minuut:= getal;
         UART1_Write_Text('minuut:') ;
         ByteToStr(getal,txt);
         UART1_Write_Text(txt) ;
         UART1_Write($0D);
         getal:=0;
         getal:=0;
         getal:= dcf77dataold[32] ;
         getal:= getal shl 1;
         getal:=getal+dcf77dataold[31] ;
         getal:= getal shl 1;
         getal:=getal+dcf77dataold[30] ;
         getal:= getal shl 1;
         getal:=getal+dcf77dataold[29];
         if dcf77dataold[33] then getal := getal +10 ;
         if dcf77dataold[34] then getal := getal +20 ;
         crc:=0;
         for teller:=29 to 34 do crc:=crc+ dcf77dataold[teller];
         crc:=crc and %00000001;
         if crc<>dcf77dataold[35] then begin
                               error:=error+4 ;// set 2e error bit;
                               dcf77tijd.uur:=0;
         end   else dcf77tijd.uur:= getal;
         UART1_Write_Text('uur:') ;
         ByteToStr(getal,txt);
         UART1_Write_Text(txt);
         UART1_Write($0D);
         ///dag
           getal:=0;
           getal:= dcf77dataold[39] ;
           getal:= getal shl 1;
           getal:=getal+dcf77dataold[38] ;
           getal:= getal shl 1;
           getal:=getal+dcf77dataold[37] ;
           getal:= getal shl 1;
           getal:=getal+dcf77dataold[36];
           if dcf77dataold[40] then getal := getal +10 ;
           if dcf77dataold[41] then getal := getal +20 ;
           dcf77tijd.dag:= getal;
           UART1_Write_Text('dag:') ;
           ByteToStr(getal,txt);
           UART1_Write_Text(txt) ;
           UART1_Write($0D);
   // dagvdweek
           getal:=0;
           getal:=getal+dcf77dataold[44] ;
           getal:= getal shl 1;
           getal:=getal+dcf77dataold[43] ;
           getal:= getal shl 1;
           getal:=getal+dcf77dataold[42];
           dagvdweek:=getal;
           case dagvdweek of
                   1:  UART1_Write_Text(' maandag') ;
                   2:  UART1_Write_Text(' dinsdag') ;
                   3:  UART1_Write_Text(' woensdag') ;
                   4:  UART1_Write_Text(' donderdag') ;
                   5:  UART1_Write_Text(' vrijdag') ;
                   6:  UART1_Write_Text(' zaterdag') ;
                   7:  UART1_Write_Text(' zondag') ;
           end;
          UART1_Write($0D);
  //maand
           
         getal:=0;
         getal:= dcf77dataold[48] ;
         getal:= getal shl 1;
         getal:=getal+dcf77dataold[47] ;
         getal:= getal shl 1;
         getal:=getal+dcf77dataold[46] ;
         getal:= getal shl 1;
         getal:=getal+dcf77dataold[45];
         if dcf77dataold[49] then getal := getal +10 ;
         maand:= getal;
        UART1_Write_Text('maand:') ;
        ByteToStr(getal,txt);
        UART1_Write_Text(txt) ;
        UART1_Write($0D);
// jaar
         getal:=0;
         getal:= dcf77dataold[53] ;
         getal:= getal shl 1;
         getal:=getal+dcf77dataold[52] ;
         getal:= getal shl 1;
         getal:=getal+dcf77dataold[51] ;
         getal:= getal shl 1;
         getal:=getal+dcf77dataold[50];
         if dcf77dataold[54] then getal := getal +10 ;
         if dcf77dataold[55] then getal := getal +20 ;
         if dcf77dataold[56] then getal := getal +40 ;
         if dcf77dataold[57] then getal := getal +80 ;
         crc:=0;
         for teller:=36 to 57 do crc:=crc+ dcf77dataold[teller];
         crc:=crc and %00000001;
         if crc<>dcf77dataold[58] then begin
                               error:=error+8; // set 4e error bit;
                               jaar:=0;
        end   else jaar:= getal;
        UART1_Write_Text('jaar:') ;
        ByteToStr(getal,txt);
        UART1_Write_Text(txt) ;
        UART1_Write($0D);
        UART1_Write_Text('error') ;
        ByteToStr(error,txt);
        UART1_Write_Text(txt) ;
        UART1_Write($0D);
     end;// decode
   

 procedure uart_tijd();

  var error, receive, teller, teken : byte;
  var output : array[3] of char ;

 begin

    //  UART
   UART1_Write_Text('tijd:');
   ByteToStr( time.huidige.uur,output );
   UART1_Write_Text(output);
   UART1_Write(58);
   ByteToStr( time.huidige.minuut,output );
   UART1_Write_Text(output);
   UART1_Write(58);

   ByteToStr( time.huidige.seconde,output );
   UART1_Write_Text(output);
   UART1_Write(58);

  end;
   



begin
   // Initialize Software UART communication on pins Rx, Tx, at 9600 bps
   UART1_Init(9600);
   delay_ms(100);         // Wait for UART module to stabilize
   UART1_Write_Text('setup');
   UART1_Write($0D);
   DDRC.B3 :=0;  // uart aan
   DDRC.b0 :=1;   //set register C bit0  als uitgangen
   DDRC.b1 :=1;   //set register C bit 1 als uitgangen
   DDRC.b2 :=1;   //set register C bit 2 als uitgangen
    //atmega 128
   DDRE.B4 := 0;  // input dcf77 puls uit conrad print
   DDRE.B5:= 0;  // input dcf77 puls uit conrad print
   pulsduur:=0;
   bitnummer:=0;
   setup_16_bit_timer();           { Main program }
   UART1_Write_Text('setup timer done');
   UART1_Write($0D);
   setuppulsduurmeting();
   UART1_Write_Text('setup pulsduur done');
   UART1_Write($0D);
   setupintercept_puls();
   UART1_Write_Text('setup puls ingang done');
   UART1_Write($0D);
   UART1_Write_Text('set interupt aan');
   UART1_Write($0D);
   SREG_I_bit := 1;               // Interrupt enable

   UART1_Write_Text('start');
   UART1_Write($0D);
   dcf77tijd.minuut:=00;
   dcf77tijd.uur :=10;
   dcf77tijd.dag := 1;
 // wait mim 2 minuten
      error:=1;
      repeat
          if newdata then begin  // dcf77dataold ont leden
            decodedcf77();
            newdata:=0;
          end; //if newdata
      until (error=0);
      time.huidige.seconde :=0;
      time.huidige.minuut :=dcf77tijd.minuut;
      time.huidige.uur :=dcf77tijd.uur;
      time.huidige.dag :=dcf77tijd.dag;
      UART1_Write_Text('tijd opgehaald');
      uart_tijd();
 while true do begin
       if time.status and %00010000 = %00010000 then on_led:= not on_led ;// update display

  //    if time.status and %00010000 = %00010000 then portA:= not portA;// update display
      if time.status and %00000100= %00000100 then begin
      // alarm
         pieper:=1;

       end else pieper:=0; // alarm
        time.status := time.status and  %00001111;


     //  UART1_Write(pulsduur);
     if  newdata then begin  // dcf77dataold ont leden
        decodedcf77();
        uart_tijd();
        newdata:=0;
      end; //if newdata
    end;
end.



User avatar
slavisa.zlatanovic
mikroElektronika team
Posts: 1321
Joined: 07 Apr 2009 09:39

Re: DCF77 Driver

#5 Post by slavisa.zlatanovic » 28 Sep 2010 14:49

Hi!

Thanks for sharing your code!

P.S.
There is the User Projects section at this forum.
Please, send your project to this address: marko@mikroe.com and we'll put it in the User Projects page.
Best regards
Slavisa

Post Reply

Return to “mikroPascal PRO for AVR Wish List”