{===============================================================}
{ }
{ Program Uhr mit externem batteriegepufferten RTC und DCF; }
{ LCD- und RTC-DCF-Funktionen }
{ }
{ }
{ Bearbeitungsbeginn: 12.02.2007 }
{ Bearbeitungsstand: 31.03.2008 }
{ Hardware-Aenderung ab 01.04.2008 Version 2 }
{ Bearbeitungsstand: 25.04.2008 }
{ Bearbeiter: Stefan Taborek }
{ }
{ Dieses Modul kann jederzeit ueber TWI-Bus abgefragt werden }
{ Wird das Kommandobyte 15 gesendet, so antwortet dieser Slave }
{ mit der aktuellen Zeit und Datum. }
{ Der avrco-Compiler muss mit dem Optimizer gestartet werden! }
{ }
{===============================================================}
program RTC_DCF_Uhr;
{ $BOOTRST $00C00} {Reset Jump to $00C00}
{$NOSHADOW}
{ $W+ Warnings} {Warnings off}
Device = mega8, VCC=4.9;
(*
Define_Fuses {fuer MEGA8 8MHZ mit internem Quarz}
LockBits0 = [];
// FuseBits0 = [CKSEL0, CKSEL1, CKSEL3, SUT1];
// FuseBits1 = [SPIEN];
ProgMode = SPI;
*)
Import SysTick, TickTimer, SerPort , TWInet;
From System Import LongWord, {Float,} Pipes, Processes;
Define
ProcClock = 8000000; {Hertz}
SysTick = 10; {msec}
Scheduler = iData;
StackSize = $0064, iData;
FrameSize = $0080, iData;
SerPort = 9600, parnone, Stop2, Databit8;
RxBuffer = 8, iData;
TxBuffer = 8, iData;
TWInetMode = Slave;
TWInode = 07;
TWIpresc = TWI_BR100; {Bitrate}
TWIframe = 36, iData; {buffer/packet size}
TWIframeBC = 4; {Broadcast Frame size}
TickTimer = Timer1;
Implementation
{$IDATA}
{--------------------------------------------------------------}
{ Type Declarations }
type
TRTCDaten=array[0..7] of byte; //alle Datenregister + Reserve
// Daten[0] := // Sekunde
// Daten[1] := // Minute
// Daten[2] := // Stunde
// Daten[3] := // Tag
// Daten[4] := // Monat
// Daten[5] := // Jahr
// Daten[6] := // Wochentag
// Daten[7] := //
TTelefonNr = string[22];
// Der folgende Daten-Rekord enthaelt alle Daten einer Weckzeit,
TRAMDATENRec = Record
cmd : byte;
state : byte;
time : TRTCDaten; // {se}, mi, hr, dd, mm, jj, wd, rr
str_ : TTelefonNr;
snr : byte;
prs : byte;
end;
TBCD = array[0..7] of byte;
TPipeStr = TTelefonNr;
{--------------------------------------------------------------}
{ Const Declarations }
const
MasterNode : byte = $02; // 2
RTC_DCFNode : byte = TWInode; // $07;
TxRxFrameSize : byte = sizeOf(TRAMDATENRec);
//Index 0 im folgenden Array ist fuer Telegramm-Fehler noetig:
dwArr:array[0..7] of string[2]=( SO , MO , DI , MI , DO , FR , SA , 00 );
{--------------------------------------------------------------}
{$EEPROM}
Structconst
eInt : word = 1;
ls1:string = #12+#1+#4;
ls2:string = -- Telefon-Wecker -- ; //!!!
ls3:string = #2+#44 + Stefan Taborek ;
ls4:string = #2+#69 + 2008 ;
eByte : byte = $AA;
eCheck : word = CalcCheckSum (@ls1, @eByte);
{--------------------------------------------------------------}
{ Var Declarations }
{$IDATA}
var
NetTimeOut : SysTimer8;
Timer1 : SysTimer8, UpCount; //8Bit fuer Pulsmessung
S_RTC : Semaphore;
Int_DCF_lo : boolean;
Zeit_Anzeigen : boolean;
min_voll : boolean;
RTC_Sec : byte;
RTC_Int_Sec : boolean;
RTC_Contr_CS1[@PortD,5] : bit;
RTC_DataOutPort[@PortC] : byte;
RTC_DataInPort[@PinC] : byte;
RTC_AdrPort[@PortB] : byte;
LED_A[@PortD,7] : bit;
RTC_Daten : TRTCDaten; // array[0..7] of byte
{--------------------------------------------------------------}
NetTxRec[@TWITXBUFF] : TRAMDATENRec;
NetRxRec[@TWIRXBUFF] : TRAMDATENRec;
lb, hb, arr_ptr : byte;
DCF_Inp[@PinD,2] : bit;
LCD_Pipe : Pipe[4] of TPipeStr;
Sec_Str : String[4];
L_Str : String[24];
LCD_Str_Info : string[14];
LCD_Str_Sig : string[14];
Zeit_Str : TPipeStr;
{--------------------------------------------------------------}
tel : array[0..60]of byte;
DCF_Daten : TRTCDaten;
DCF_true : boolean;
part8 : TBCD;
anz_bit_sec : byte;
anz_bitfehler : byte;
anz_telflanken : byte;
anz_telflanken_alt : byte;
err_pr : byte;
Tbit_Ptr : byte;
wLo,wLoHi : integer;
PeSumme : integer;
qlo : integer;
qHi : integer;
qcnt : integer;
wcnt : word;
{--------------------------------------------------------------}
{ Interrupt-Routinen }
{ $NoSave}
{--------------------------I-----------------------------------}
Interrupt Int0; //Ausgeloest von DCF ueber PinD2 H->L or L->H
{--------------------------------------------------------------}
begin
//------------------ Telegramm-Empfang -------------------
if (DCF_Inp= false)then // Achtung hier Logikwechsel!!!!
wLo := Integer(GetSysTimer(Timer1)); // Dauer der Low-Periode
// LED1 := true;
else
wLoHi := Integer(GetSysTimer(Timer1)); // Dauer der Lo + Hi-Periode
ResetSysTimer(Timer1); //
Int_DCF_lo := true; // Start des Process
// LED1 := false;
endif;
end;
{$NoSave}
{--------------------------I-----------------------------------}
Interrupt Int1; //Ausgeloest vom ext. RTC ueer PinD3
{--------------------------------------------------------------}
begin
IncSema(S_RTC);
end;
{-------------------functions procedures-----------------------}
{--------------------------------------------------------------}
procedure InitPorts;
{--------------------------------------------------------------}
begin
LED_A := false;
//------------- Port B -------------
DDRB := %00111111; // Adress-Port (2Bit + 4Bit) Ausgabe
RTC_AdrPort := %00110000; // PortB: Bit4, Bit5 auf High setzen !!!!
//
//------------- Port C -------------
DDRC := %00001111; //Daten-Port (4Bit) zuerst Ausgabe
//
//------------ Port D --------------
PortD := %00001100; // fuer PIN2 und PIN3 PullUp-Resistor aktivieren
DDRD := %11000000; // Bit0
// // Bit1
// Bit2 < Int0 DCF interrupt
// Bit3 < Int1 RTC Sekundeninterrupt
// Bit4
// Bit5
// Bit6 > CS1 am RTC
// Bit7 > LED
//---Externer Interrupt Int0 (D2) und Int1 (D3):
GICR := GICR or %11000000; // Int0 und Int1 sind erlaubt
MCUCR := MCUCR or %00001001; // Int0 bei jeder Flanke
// Int1 loest bei fall. Flanke aus
// Int0 kommt von DCF-In
// Int1 kommt von RTC
end InitPorts;
{--------------------------------------------------------------}
procedure InitVar;
{--------------------------------------------------------------}
begin
anz_bitfehler := 0;
anz_telflanken := 0; // Zaehler fuer ungueltige Bits
DCF_true := false;
PeSumme := 0;
qcnt := 0;
wcnt := 0; // sperrt den evtl. fruehzeitigen RTC-Int
end;
{--------------------------------------------------------------}
procedure InitLCD;
{--------------------------------------------------------------}
begin
Write(SerOut, #12+#1+#4); // Clear; Cursor Home, Hide
L_Str := ls2;
Write(SerOut, L_Str);
Write(SerOut, ls3);
Write(SerOut, ls4);
mdelay(3900);
Write(SerOut, #12+#1+#4); // Clear; Cursor Home
end;
{--------------------------------------------------------------}
function RTC_Read(adr:byte):byte;
{--------------------------------------------------------------}
var dat1 : byte;
// Bit4 : RD Lo-aktiv
// Bit5 : WR Lo-aktiv
// Achtung Reihenfolge der Befehle nicht veraendern!
// Achtung nichts veraendern!
// CS1 wird hier eingesetzt, weil damit auch der Standby-Modus
// des RTC gesteuert wird, dh. CS1 ist bei Netzausfall immer Lo
begin
RTC_Contr_CS1 := true; // CS1 auf Hi setzen
adr := adr or %00110000; // Bit4, Bit5 auf High setzen
RTC_AdrPort := adr; // PortB: adr out unbed. noetig!
excl(adr, 4); // PortB Bit4 (RD) auf Low setzen
RTC_AdrPort := adr; // PortB gibt RD (+ Adresse) aus
DDRC:= %0000; // Daten-Port (4Bit) Lesen
dat1 := RTC_DataInPort and $0F;
RTC_Contr_CS1 := false; // CS1 auf Lo setzen -> Holdbit=0
return(dat1);
end;
{--------------------------------------------------------------}
procedure RTC_Write(adr, daten:byte);
{--------------------------------------------------------------}
// Bit4 : RD Lo-aktiv
// Bit5 : WR Lo-aktiv
// Achtung Reihenfolge der Befehle nicht veraendern!
// Achtung nichts veraendern!
// CS1 wird hier eingesetzt, weil damit auch der Standby-Modus
// des RTC gesteuert wird, dh. CS1 ist bei Netzausfall immer Lo
begin
RTC_Contr_CS1 := true; // CS1 auf Hi setzen
adr := adr or %00110000; // Bit4, Bit5 auf High setzen
RTC_AdrPort := adr; // PortB: adr out unbed noetig
excl(adr, 5); // PortB Bit5 (WR) auf Low setzen
DDRC:= %1111; // Daten-Port (4Bit) Schreiben
RTC_DataOutPort := daten and $0F; // PortC
RTC_AdrPort := adr; // PortB gibt WR (+ Adresse) aus
RTC_Contr_CS1 := false; // CS1 auf Lo setzen -> Holdbit=0
end;
{--------------------------------------------------------------}
function RTC_BusyBit:boolean;
{--------------------------------------------------------------}
var busybit : boolean;
regD, cnt1: byte;
begin
busybit := true;
cnt1 := 5;
Repeat
RTC_Write($0D, %00000001); // Reg_D Hold-Bit setzen (Bit0)
regD := RTC_Read($0D); // Reg_D zuruecklesen
if not bit(regD, 1) then // Busy-Bit = 0 ? (Bit1)
busybit := false;
else
RTC_Write($0D, %00000000); // Reg_D schr Hold-Bit=0
mdelay(1); // wait laut Datenblatt = 0,19ms
endif;
dec(cnt1);
until (not busybit) or (cnt1 =0);
RTC_Write($0D, %00000000); // Reg_D schr Hold-Bit = 0
return(busybit);
end;
{--------------------------------------------------------------}
procedure Set_RTC_Time;
{--------------------------------------------------------------}
var b,i8 : byte;
begin
arr_ptr := 0;
//
if RTC_BusyBit=false then // Busy-Bit=1 entspricht readonly
for i8 := 0 to 11 by 2 do //
b := RTC_Daten[arr_ptr];
lb := (b mod 10);
hb := (b div 10);
inc(arr_ptr);
//
RTC_Write(i8, lb);
if i8=4 then hb := hb or %100; endif; // Bit2 fuer 24h-Betr.
RTC_Write(i8+1, hb);
endfor;
RTC_Write(12, RTC_Daten[6]); // Wochentag
endif;
//
RTC_Write($0F, %00000101); // Reg_F schreiben Reset-Bit = 1
RTC_Write($0F, %00000100); // Reg_F schreiben Reset-Bit = 0
RTC_Write($0D, %00000000); // Reg_D schreiben Hold-Bit = 0
RTC_Write($0D, %00000000); // Reg_D schreiben Hold-Bit = 0
end;
{--------------------------------------------------------------}
procedure Get_RTC_Time;
{--------------------------------------------------------------}
var h,i9 : byte;
begin
// das RTC_Daten-Array in der selben Reihenfolge
arr_ptr := 0;
//
if RTC_BusyBit=false then
for i9 := 0 to 11 by 2 do // ohne WD !!!!
lb := RTC_Read(i9);
hb := RTC_Read(i9+1);
if (i9 = 4) then hb := hb and %0011; endif; //24h
h := hb*10 + lb;
//
RTC_Daten[arr_ptr] := h;
inc(arr_ptr);
endfor;
RTC_Daten[6] := RTC_Read(12) and %0111; //WD 12
else
endif;
RTC_Sec := RTC_Daten[0]; // Anfangssekunde einstellen !
//
RTC_Write($0D, %00000000); // Reg_D schreiben Hold-Bit = 0 2 mal
RTC_Write($0D, %00000000); // Reg_D schreiben Hold-Bit = 0 !!!!
end;
{--------------------------------------------------------------}
procedure RTC_ZeitStellen(dcfsync : boolean);
{--------------------------------------------------------------}
var i0: byte;
begin
// nur aufrufen, wenn DCF-Daten gerade eingetroffen sind!!
// dh. Net_Puffer.dat ist aktuell !
// oder mit Parameter false
if RTC_BusyBit=false then // Busy-Bit=1 entspricht readonly
if dcfsync then
RTC_Daten := DCF_Daten;
else{----------------------}
// Testwerte einsetzen bei Erstinitialisierung
for i0 := 7 downto 1 do
RTC_Daten[i0-1] := (7-i0)*i0-(11 mod i0) ; //
endfor;
// Sekunde 0
// Minute 5
// Stunde 8
// Tag 9
// Monat 11
// Jahr 10
// Wochentag 2 Dienstag
endif;
//
Set_RTC_Time; // alle 12 Register von 0 bis C
endif;
mdelay(2);
RTC_Write($0D, %00000000); // Reg_D schreiben Hold-Bit = 0 !!
end;
{--------------------------------------------------------------}
procedure WriteTimeToLCD(zle : byte);
{--------------------------------------------------------------}
var
i : byte;
begin
// zle bezieht sich auf das Display 4x20;
// zle=1 entspricht Zeile 1
// Das Ausgabeformat benoetigt genau 20 Zeichen:
// hr:mi:se WD dd.mm.jj
//
dec(zle);
zle := (zle * 20) + 1; //fortlaufende Cursorposition
//
Zeit_Str := #2+char(zle);
for i := 2 downto 0 do
Zeit_Str := Zeit_Str + ByteToStr(RTC_Daten[i]:2: 0 );
case i of
1..2: Zeit_Str := Zeit_Str + : ; |
0: Zeit_Str := Zeit_Str + + dwArr[RTC_Daten[6]] + ; |
endCase;
endfor;
for i := 3 to 5 do
Zeit_Str := Zeit_Str + ByteToStr(RTC_Daten[i]:2: 0 );
if i < 5 then Zeit_Str := Zeit_Str + . ; endif;
endfor;
PipeSend(LCD_Pipe, Zeit_Str);
end;
{--------------------------------------------------------------}
procedure RTC_Initialisieren;
{--------------------------------------------------------------}
var RTCRegD, RTCRegE : byte;
begin
// nur bei Prozessor-Reset oder Neustart:
RTCRegE := RTC_Read($0E); // Reg_E !!!!!!!!!!!!!!
RTCRegE := RTC_Read($0E); // Reg_E 2mal
RTCRegD := RTC_Read($0D); // Reg_D
if (not bit(RTCRegD, 0)) and // HoldBit Bit= 0 ?
(RTCRegE = %00000110) then // E-Register ok? xxxx
Get_RTC_Time; // alle Zeit-Daten
else
// da der RTC nicht korrekt initialisiert ist:
RTC_Write($0F, (%00000100 or %00000011)); //Reg_F
mdelay(3);
RTC_Write($0E, %00000110); // Reg_E sec-Periode Interrupt
RTC_Write($0D, %00000001); // Reg_D Hold setzen
RTC_Write($0F, %00000100); // Reg_F
//
RTC_ZeitStellen(false); // Parameter false --> nur Testwerte
endif;
RTC_Write($0D, %00000000); // Reg_D schreiben Hold-Bit = 0 !!
end;
//*************************DCF***********************************
{--------------------------------------------------------------}
procedure Part8_clear;
{--------------------------------------------------------------}
var i4 : byte;
begin
for i4 := 0 to 7 do
part8[i4] :=0;
endfor;
end;
{--------------------------------------------------------------}
function ParityTest(t_a, t_e:byte): byte;
{--------------------------------------------------------------}
var h5, i5 :byte;
begin
// das Paritaetsbit ergaenzt immer auf eine gerade Anzahl Bits
h5 := 0;
for i5 := t_a to t_e do
if tel[i5] = 1 then
inc(h5);
endif;
endfor;
return((h5) mod 2);
end;
{--------------------------------------------------------------}
function DCF_Wert_decodieren(bcdw:TBCD ):byte;
{--------------------------------------------------------------}
// to decimal
var h2, i2, w2 : byte;
begin
// die Codierung der DCF-Werte erfolgt nicht im ueblichen
// Nibble-Code
w2 := 0;
h2 := 1;
for i2 := 0 to 7 do
if (i2 = 4) then h2 := 10; endif; // 10er-Werte beginnen
if bcdw[i2] = 1 then w2 := w2 + h2; endif;
h2 := h2 * 2;
endfor;
//
return(w2);
end;
{--------------------------------------------------------------}
function DCF_Telegramm_decodieren : boolean;
{--------------------------------------------------------------}
var b, h7, i7 : byte;
begin
// Hier wird das Telegramm erst geprueft und ausgewertet,
// nachdem das Bit 58 gesendet wurde.
err_pr := 0; // fuer Pruefbitfehler
// als Pruefbitfehler werden auch Fehler an Bit0 und
// Bit20 gezaehlt
// die maximale Pruefbitfehlerzahl ist demnach 5
for i7 := 0 to 59 do
b := byte(tel[i7]);
case i7 of
0 : if (b > 0) then //dieses Bit ist immer 0
inc(err_pr);
endif;
|
20 : if (b <> 1) then // Startbit immer 1
inc(err_pr);
endif;
Part8_clear;
h7:= 0; // Vorbereitung fuer Min
|
21..27 : Part8[h7] := byte(b);
inc(h7);
|
28 : h7 := DCF_Wert_decodieren(part8); // Minute
if h7 > 59 then
inc(err_pr);
h7 := 0;
endif;
DCF_Daten[1] := h7;
err_pr := err_pr + ParityTest(21, 28);
Part8_clear; // Vorbereitung fuer Std
h7 := 0;
|
29..34 : Part8[h7] := b;
inc(h7);
|
35 : h7 := DCF_Wert_decodieren(part8); // Stunde
if h7 > 23 then
inc(err_pr);
h7 := 1;
endif;
DCF_Daten[2] := h7;
err_pr := err_pr + ParityTest(29, 35);
Part8_clear;
h7 := 0; // Vorbereitung fuer Tag
|
36..41 : part8[h7] := b;
inc(h7);
|
42 : h7 := DCF_Wert_decodieren(part8); // Tag
if not (h7 in [1..31]) then
inc(err_pr);
h7 := 1;
endif;
DCF_Daten[3] := h7;
Part8_clear;
part8[0] := b; // 1.Bit fuer Wochentag
h7 := 1;
|
43..44 : part8[h7]:= b;
inc(h7);
|
45 : h7 := DCF_Wert_decodieren(part8); // Wochentag 1..7
if not (h7 in [1..7]) then
inc(err_pr);
h7 := 1;
endif;
if h7 = 7 then h7 := 0; endif; // Anpassg an RTC
DCF_Daten[6] := h7;
Part8_clear;
part8[0] := b; // 1.Bit fuer Monat
h7 := 1;
|
46..49 : part8[h7] := byte(tel[i7]);
inc(h7);
|
50 : h7 := DCF_Wert_decodieren(part8); // Monat
if not (h7 in [1..12]) then
inc(err_pr);
h7 := 1;
endif;
DCF_Daten[4] := h7;
Part8_clear;
part8[0] := b; // 1.Bit fuer Jahr
h7 := 1;
|
51..57 : Part8[h7]:= b;
inc(h7);
|
58 : h7 := DCF_Wert_decodieren(part8); // Jahr
if not (h7 in [8..25]) then
inc(err_pr);
h7 := 0;
endif;
DCF_Daten[5] := h7;
err_pr := err_pr + ParityTest(36, 58);
|
endcase;
endfor;
//
return((Tbit_Ptr > 57)and(err_pr = 0));
end;
//=========================Prozesse======================
{--------------------------------------------------------------}
process WriteLCD(40, 32: iData, 3);
{--------------------------------------------------------------}
{ Frame- and Stack-Size habe ich ausgemessen }
begin
WaitPipe(LCD_Pipe);
PipeRecv(LCD_Pipe, L_Str);
Write(SerOut, L_Str);
mdelay(15);
end;
{==============================================================}
Process RxMasterFrame(40, 40 : iData, 4);
{==============================================================}
begin
// Telegramm von Master eingetroffen:
WaitSema(TWIrxSEMA);
NetTxRec.cmd:= 254;
if NetRxRec.cmd = 15 then
if NetRxRec.str_ <> then
PipeSend(LCD_Pipe, NetRxRec.str_);
endif;
NetTxRec.time := RTC_Daten; // Daten in Byteformat
NetTxRec.str_ := Zeit_Str;
NetTxRec.cmd := 115; // Quittungsbyte
endif;
mdelay(5);
TWItxFrame(MasterNode, TxRxFrameSize); // an Master senden
TWIRXCLEAR; // This is mandatory !!!
end;
{==============================================================}
process RTC_Sekunde(28,34 : iData, 3);
{==============================================================}
{ Frame- and Stack-Size habe ich ausgemessen }
begin
waitSema(S_RTC);
repeat until wcnt = 1; // Start des Main_Proc
//
//------------------------
// Interruptbit des RTC muss hier noch quittiert werden:
RTC_Write($0D, %00000000); // Reg_D schreiben Int-Bit = 0
//------------------------
//
inc(RTC_Sec);
if (RTC_Sec > 59)or(min_voll) then
min_voll := false;
Get_RTC_Time; // auch RTC_Sec := 0;
Zeit_Anzeigen := true;
else
// Ausgabe der Sekunde auf dem LCD:
Sec_Str := #2+#7 + ByteToStr(RTC_Sec:2: 0 );
PipeSend(LCD_Pipe, Sec_Str);
//
endif;
//
//=============
LED_A := true;
mdelay(65); // Blinkdauer
LED_A := false;
//=============
//
// ------ DCF-Signalueberwachung --------
//----Signalqualitaet berechnen:
…..........
//
LCD_Str_Sig := #2+#61 + Sig: +ByteToStr(Byte(qhi):3: )+ % ;
if (anz_bitfehler) > 0 then
LCD_Str_Sig := #2+#61 + Sig ?? ;
endif;
//
if anz_telflanken_alt < anz_telflanken then
anz_telflanken_alt := anz_telflanken;
anz_bit_sec := 0;
else
inc(anz_bit_sec);
if (anz_bit_sec > 3) then
LCD_Str_Sig := #2+#61 + Sig: aus ;
if DCF_true then
DCF_true := false;
Int_DCF_lo := true; // Anzeige aktualisieren
endif;
endif;
endif;
PipeSend(LCD_Pipe, LCD_Str_Sig);
// --------------------------------------
end;
{--------------------------------------------------------------}
{ Main Program }
{$IDATA}
{--------------------------------------------------------------}
begin
InitPorts;
InitVar;
//--------------------------------------
EnableInts;
//--------------------------------------
mdelay(600); // vor InitLCD muessen ca 600ms Stabilisierungszeit liegen!!
InitLCD; // nicht vor EnableInts;
//
Start_Processes;
TWIrxClear; //erst nach Start_Processes !
//
//--------------------------------------
RTC_Initialisieren; //
RTC_Sec := RTC_Daten[0]; // Anfangssekunde einstellen !
WriteTimeToLCD(1); // zeile 1
//--------------------------------------
wcnt := 1; // !!! Siehe RTC-Prozess (fuer Fehlstart)
//============================================================
loop
repeat
if Zeit_Anzeigen then
Zeit_Anzeigen := false;
WriteTimeToLCD(1); // kompletten Zeitstring ausgeben
endif;
until (Int_DCF_lo); // siehe Interrupt Int0;
//
Int_DCF_lo := false;
(*-----------------------------------------------------------
Start nur bei Flankenwechsel nach Low
es folgt die Auswertung der vohergehenden Sekunde
Messung erfolgte in der ISR
- ----------------------- ---------------------
| | | | |
| | | | |
------ -------- ----
0 1
|<-----------1sec---------->|<-----------1sec---------->|
| Lo | | Lo | Hi |
100ms 200ms
^ ^ ^
--neue Sekunde beginnt: alte Sek auswerten wird
gespeichert *)
//
if wLo in [09..12] then
tel[Tbit_Ptr] := 0;
endif;
if wLo in [19..22] then
tel[Tbit_Ptr] := 1;
endif;
//
LCD_Str_Info := #2+#70+ DCF ;
if (wLoHi > 190) and (wLoHi < 215) then // Minutenwechsel
if DCF_Telegramm_decodieren = true then //
RTC_ZeitStellen(true);
Zeit_Anzeigen := true;
LCD_Str_Info := LCD_Str_Info + Zt: OK ;
DCF_true := true; // ein mal nach Signalausfall
else
LCD_Str_Info := LCD_Str_Info + Zt: Err ;
endif;
//------------------
Tbit_Ptr := 0; // hier erfolgt exakter Reset
// RTC_Sec := 0;
anz_bitfehler := 0;
anz_telflanken_alt := 0;
anz_telflanken := 1;
mdelay(10); // um nicht zu zeitig zu sein!
min_voll := true;
//
else //------------------------------
if ((wLoHi > 90) and (wLoHi < 115)) then // vorige Sek
else
tel[Tbit_Ptr] := 255; //unbestimmt
if (anz_bitfehler < 255) then
inc(anz_bitfehler);
endif;
endif;
//------------------
inc(Tbit_Ptr); // Bit-Pointer
if (Tbit_Ptr > 59) then // Sicherheit fuer array
Tbit_Ptr := 0;
endif;
//------------------
//
if (DCF_true)and(Tbit_Ptr > 4) then
LCD_Str_Info := LCD_Str_Info + Empf OK ;
else
LCD_Str_Info := LCD_Str_Info + Empf ?? ;
endif;
//
endif;
PipeSend (LCD_Pipe, LCD_Str_Info);
//-----------------------------------------
inc(anz_telflanken); //jede Lo-Telegrammflanke zaehlen
endloop;
end RTC_DCF_Uhr.
Quelltext des Programms
Blockschaltbild
Details