Device = 16F628A Config HS_OSC, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF ;Interne RC-oscillator ALL_DIGITAL TRUE XTAL = 16 ;Gebruik een kristal van 16MHz ;Normale aliases (constanten) Symbol Blokje = 255 ;Maximaal 255: 255 is de ASCII code voor een blokje op de LCD tijdsbalk Symbol LCD_Char = 16 ;Minimaal 16: Aantal karakters per regel (afhankelijk van het gebruikte LCD type) Symbol MaxVindTijd = 65 ;Minimaal 65: (Sec) Tijd om seconde 00 te vinden Symbol OpStartTijd = 45000 ;Maximaal 65535: (mSec) 45 seconden opstart tijd voor de DCF77 module na power-on Symbol PulsLengte = 740 ;Minimaal 500! Maximaal 750: (mSec) Symbol PulsLengteX = PulsLengte / 10 ;Logische aliases (constanten) Symbol AAN = 0 ;Omgekeerd ON Symbol FALSE = 0 Symbol offf = 0 Symbol onn = 1 Symbol TRUE = 1 Symbol UIT = 1 ;Omgekeerd OFF ;Poort aliases Symbol SecondePuls = PORTA.1 ;Iedere seconde een puls van 0,5 seconde Symbol DCF_Signaal = PORTB.0 ;Ingang voor de DCF77 module (ontvanger) signaal (bv. Conrad BN641138) ; 76543210 TRISA = %11100000 TRISB = %11111111 PORTB_PULLUPS On ;Pull-up voor DCF77 ontvanger en Test toets Declare LCD_TYPE ALPHA Declare LCD_INTERFACE = 4 Declare LCD_ENPIN = PORTA.3 Declare LCD_RSPIN = PORTB.3 Declare LCD_DTPIN = PORTB.4 Declare LCD_LINES = 2 ;WORD Dim SignaalCheck As Word Dim Teller As Word ;BYTE Dim AlgemeneTeller As Byte Dim BitAantal As Byte Dim CursorPos As Byte ;Cursor x-positie op de LCD Dim Dag As Byte Dim Jaar As Byte Dim Maand As Byte Dim Minuut As Byte Dim MinuutDCF As Byte ;Bevat de DCF minuut, is er een pariteitserror, dan wordt Minuut NIET gelijk gemaakt met MinuutDCF, maar alleen met 1 verhoogd Dim OntvangByte As Byte Dim Seconde As Byte Dim Uur As Byte Dim UurDCF As Byte ;Bevat het DCF uur, is er een pariteitserror, dan wordt Uur NIET gelijk gemaakt met UurDCF Dim UurLCD As Byte ;Normaal gelijk aan Uur, alleen bij AM/PM notatie wijkt hij 's middags af Dim WeekDag As Byte Dim BD1 As Byte ;Byte Dummy 1 ;BIT Dim Initialiseren As Bit ;TRUE bij initialiseren Dim OntvangBit As Bit Dim PariteitsBit As Bit Dim PariteitsError As Bit Dim Signaal As Bit ;TRUE als er een signaal is (gevonden) Dim ID1 As Bit ;Bit Dummy 1 Dim Dummy As Bit PORTA = 0 PORTB = 0 Clear Dummy = 0 DelayMS 200 ;LCD stabilisering Cls Print "DCF16NLD V-2" ;Versie nummer DelayMS 2000 Cls Print "Signaal zoeken" Initialiseren = TRUE GoTo HoofdLus ;Spring over de subroutines ;SUBROUTINES OntvangBitAantal: ;Vul het ontvangstbyte met het opgegeven aantal bits in BCD mode Clear OntvangByte For BD1 = 0 To BitAantal - 1 GoSub OntvangEenBit If OntvangBit = 1 Then SetBit OntvangByte, BD1 Next OntvangByte = ((OntvangByte >> 4) * 10) + (OntvangByte & 15) ;BCD (Binary-Coded Decimal) naar byte conversie Return OntvangEenBit: ;Ontvang een bit en bewaar dit in OntvangBit Clear Teller While DCF_Signaal = AAN DelayMS 1 Inc Teller If Teller > 3000 Then ErrorOntvangst ;Tegen een eventuele 'hang up' Wend DelayMS 155 ;135 - 175msec OntvangBit = DCF_Signaal If Initialiseren = TRUE Then CursorPos = (Seconde * LCD_Char) / 58 ;Bereken waar de cursor moet staan (afhankelijk van de wachttijd en LCD type) Print At 2, CursorPos, Blokje ;Maak tijdsbalk actueel Else Print At 1, CursorPos, DEC2 Seconde ;Zet de seconden op het LCD PariteitsBit = PariteitsBit + OntvangBit ;Bit, dus 0+0=0 / 0+1=1 / 1+1=0 / 1+0=1 EndIf Inc Seconde ;Omdat we toch elke seconde in deze routine zijn, gebruiken we het ook om de seconden te tellen SecondePuls = onn ;Uitgangssignaal seconde puls DelayMS 500 SecondePuls = offf DelayMS PulsLengte - 500 Return ;HOOFDPROGRAMMA HoofdLus: Clear AlgemeneTeller Seconde = 00 ;Start met de eerste seconde Signaal = FALSE While Signaal = FALSE ;Wacht tot het DCF signaal hoog is Clear Teller While DCF_Signaal = UIT Inc Teller DelayMS 1 If Teller > OpStartTijd Then ErrorOntvangst ;Opstart tijd voor de DCF77 ontvanger bij power-on Wend Clear Teller While DCF_Signaal = AAN ;Meet de tijd tussen de pulsen Inc Teller DelayMS 10 If Initialiseren = FALSE Then Select Case Teller Case 85 - PulsLengteX ;85 = (1000mSec - 155mSec) / 10 Print At 1, CursorPos, "59";xx:xx:59, zet de niet uitgezonden seconde '59' op het LCD Case 25 SecondePuls = onn Case 75 SecondePuls = offf Case 250 GoTo ErrorOntvangst;Signaal is niet binnen de tijd van niveau veranderd EndSelect Else If Teller > (OpStartTijd / 10) Then ErrorOntvangst ;Opstart tijd voor de DCF77 ontvanger bij power-on EndIf Wend If AlgemeneTeller >= MaxVindTijd Then ErrorOntvangst ;Als er meer dan 'MaxVindTijd' seconden zijn geteld dan hebben we een probleem Inc AlgemeneTeller If Teller > 100 Then Signaal = TRUE ;We tellen per 10mSec, dus we hebben minstens 100x10mSec nodig om het begin te vinden If Initialiseren = TRUE Then CursorPos = (AlgemeneTeller * LCD_Char) / MaxVindTijd ;Bereken waar de cursor moet staan (afhankelijk van de wachttijd en LCD type) Print At 1, 1, "Signaal gevonden" Print At 2, CursorPos , Blokje ;Zet blokjes op het LCD tijdens wachten op het init signaal EndIf Wend If Initialiseren = TRUE Then Cls Print "Initialiseren..." Print At 2, 1, Rep "_" \ LCD_Char ;Teken een dunne lijn die aangeeft hoe lang de tijdsbalk wordt Else CursorPos = LCD_Char - 9 ;X-positie van tijd op het LCD Cursor 1, CursorPos If PariteitsError = TRUE Then ;Tijd onbetrouwbaar, de PIC zorgt nu zelf voor actualisering van de tijd If Minuut < 59 Then Inc Minuut Else Minuut = 00 ;\ If Uur < 23 Then ;-Tijd wordt gelijk gezet, ondanks pariteitserror Inc Uur ;/ Else Uur = 00 ;De datum verhogen heeft geen zin, die wordt bij een error nl. niet gewijzigd EndIf EndIf Else ;Geen error, dus gewoon de DCF tijd neerzetten Minuut = MinuutDCF Uur = UurDCF ;Het uur wordt alleen geactualiseerd als er geen pariteitserror is EndIf UurLCD = Uur Print " " ;Wis deel van 12 uurs notatie (AM/PM) uit bij omschakeling naar 24 uurs notatie If UurLCD < 10 Then Print " " ;Wis de eerste nul (08:00:00 --> 8:00:00) (Nul onderdrukking) Print Dec UurLCD, ":", DEC2 Minuut, ":00" ;Zet elke minuut de actuele tijd op het LCD CursorPos = LCD_Char - 1 ;Cursor positie alvast instellen voor de seconden EndIf If Signaal = TRUE Then ;Startbit succesvol ontvangen, start met het vullen van data GoSub OntvangEenBit ;0: Bit 0 (gereserveerd (DCF77 protocol) Verder: ;Als de gong klinkt, wordt bit 0 genegeerd, na de gong, wordt hier verder gegaan For BD1 = 1 To 14 ;1...14: deze bits zijn gereserveerd (info zie www.picbasic.nl --> DCF77 info) GoSub OntvangEenBit Next Clear PariteitsBit ;Als PariteitsError is geset, dan is PariteitsBit ook verminkt (geweest), even resetten Clear PariteitsError ;Reset PariteitsError (Deze 2 resets op deze plek laten staan ivm. pariteitserror tijdens initialiseren) GoSub OntvangEenBit ;15: Welke zend antenne is gebruikt? ; IF OntvangBit = 0 THEN... ;Signaal is verzonden door de standaard antenne, dit bit wordt niet gebruikt in dit programma ; IF OntvangBit = 1 THEN... ;Signaal is verzonden door een reserve antenne, dit bit wordt niet gebruikt in dit programma GoSub OntvangEenBit ;16: Omschakeling naar zomer/winter volgend uur? ; IF OntvangBit = 1 THEN... ;Dit bit wordt niet gebruikt in dit programma GoSub OntvangEenBit ;17: Zomer- of wintertijd? If OntvangBit = 1 Then ' Zomertijd = TRUE ;Zomer Else ' Zomertijd = FALSE ;Winter EndIf For BD1 = 18 To 19 ;18...19: Deze bits worden niet gebruikt (Time Zone bit 2 en schrikkel-seconde bit) GoSub OntvangEenBit Next GoSub OntvangEenBit ;20: Startbit, normaal altijd 1, dit bit wordt niet gebruikt in dit programma ; IF OntvangBit = 0 THEN... ;Dit bit wordt niet gebruikt in dit programma BitAantal = 7 ;21...27: Ontvang minuut (7 bits) GoSub OntvangBitAantal MinuutDCF = OntvangByte ;Wordt eerst in MinuutDCF opgeslagen, als blijkt dat er geen pariteitserror is, dan wordt het aan Minuut gegeven, bij een error niet GoSub OntvangEenBit ;28: Pariteitsbit 1, minuten If PariteitsBit = onn Then PariteitsError = TRUE BitAantal = 6 ;29...34: Ontvang uur (6 bits) GoSub OntvangBitAantal UurDCF = OntvangByte ;Wordt eerst in UurDCF opgeslagen, als blijkt dat er geen pariteitserror is, dan wordt het aan Uur gegeven, bij een error niet GoSub OntvangEenBit ;35: Pariteitsbit 2, uren If PariteitsBit = onn Then PariteitsError = TRUE BitAantal = 6 ;36...41: Ontvang dag (6 bits) GoSub OntvangBitAantal Dag = OntvangByte BitAantal = 3 ;42...44: Ontvang weekdag (3 bits) GoSub OntvangBitAantal WeekDag = OntvangByte BitAantal = 5 ;45...49: Ontvang maand (5 bits) GoSub OntvangBitAantal Maand = OntvangByte BitAantal = 8 ;50...57: Ontvang jaar (8 bits) GoSub OntvangBitAantal Jaar = OntvangByte GoSub OntvangEenBit ;58: Pariteitsbit 3, datum If PariteitsBit = onn Then PariteitsError = TRUE If Initialiseren = TRUE Then If PariteitsError = FALSE Then ;Als er GEEN pariteitserror is, dan zijn we... Initialiseren = FALSE ;...klaar met initialiseren (Dus opnieuw initialiseren als er WEL een pariteitserror tijdens initialiseren was EndIf Cls EndIf If PariteitsError = FALSE Then ;Alleen datum actualiseren als er geen error in de ontvangst is ; PRINT AT 1, 1, REP " " \ 9 ;Wis de dag op het LCD (Alleen nodig bij volledige naam van de dag) Print At 2, 1, Rep " " \ LCD_Char ;Wis de hele tweede lijn Cursor 1, 1 Select Case WeekDag Case 1: Print "Ma" Case 2: Print "Di" Case 3: Print "Wo" Case 4: Print "Do" Case 5: Print "Vr" Case 6: Print "Za" Case 7: Print "Zo" EndSelect Print At 2, 1, Dec Dag, " " Select Case Maand Case 1: Print "januari" Case 2: Print "februari" Case 3: Print "maart" Case 4: Print "april" Case 5: Print "mei" Case 6: Print "juni" Case 7: Print "juli" Case 8: Print "augustus" Case 9: Print "september" Case 10: Print "oktober" Case 11: Print "november" Case 12: Print "december" End Select If Maand = 9 Then Print " '", DEC2 Jaar ;September (9 karakters) past anders niet op 16 karakters LCD Else Print " 20", DEC2 Jaar EndIf EndIf Else ;Else 'Signaal' = FALSE, geen signaal gevonden GoTo ErrorOntvangst EndIf GoTo HoofdLus GongSignaal: DelayMS 155 If Minuut = 00 Or Dummy = AAN Then ;Gong1 = onn ;Op de hele uren (en met test) volgt een 3-tonig signaal SecondePuls = onn DelayMS 500 SecondePuls = offf DelayMS 330 ;985 - 500 - 155 Inc Seconde EndIf GoTo Verder ;Ga verder met het lezen van de DCF77 bits vanaf bit 1 (We slaan de DCF77 bit 0 over) ErrorOntvangst: Cls Print "Geen signaal" ;Startbit niet gevonden of geen signaal? Repeat Clear ;Wis alle RAM ID1 = DCF_Signaal While DCF_Signaal = ID1 ;Wacht op signaal verandering Inc SignaalCheck DelayMS 1 Wend ID1 = ID1 ^ 1 While DCF_Signaal = ID1 ;Wacht op signaal verandering Inc SignaalCheck DelayMS 1 Wend Until SignaalCheck < 990 Initialiseren = TRUE ;Na een error moet er weer worden geinitialiseerd GoTo HoofdLus