Page 1 of 1
DCF77 Driver
Posted: 15 Oct 2009 19:11
by corado
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
Posted: 16 Oct 2009 15:30
by anikolic
Hi,
I have informed our developers of your suggestions. Thank you for your support.
Best regards,
Aleksandar
Posted: 16 Oct 2009 15:47
by corado
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
Re: DCF77 Driver
Posted: 27 Sep 2010 15:04
by noordschanser
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.
Re: DCF77 Driver
Posted: 28 Sep 2010 14:49
by slavisa.zlatanovic
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.