eGospodarka.pl
eGospodarka.pl poleca

eGospodarka.plGrupypl.misc.elektronikaPrzykładowe ramki DCF77 › Re: Przykładowe ramki DCF77
  • Path: news-archive.icm.edu.pl!news.icm.edu.pl!news.chmurka.net!.POSTED.213.192.88.68!
    not-for-mail
    From: Piotr Gałka <p...@c...pl>
    Newsgroups: pl.misc.elektronika
    Subject: Re: Przykładowe ramki DCF77
    Date: Thu, 9 May 2019 10:48:58 +0200
    Organization: news.chmurka.net
    Message-ID: <qb0phl$mg$1$PiotrGalka@news.chmurka.net>
    References: <5cd3c2fd$0$527$65785112@news.neostrada.pl>
    NNTP-Posting-Host: 213.192.88.68
    Mime-Version: 1.0
    Content-Type: text/plain; charset=utf-8; format=flowed
    Content-Transfer-Encoding: 8bit
    Injection-Date: Thu, 9 May 2019 08:48:53 +0000 (UTC)
    Injection-Info: news.chmurka.net; posting-account="PiotrGalka";
    posting-host="213.192.88.68"; logging-data="720";
    mail-complaints-to="abuse-news.(at).chmurka.net"
    User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:60.0) Gecko/20100101
    Thunderbird/60.6.1
    Content-Language: pl
    In-Reply-To: <5cd3c2fd$0$527$65785112@news.neostrada.pl>
    Xref: news-archive.icm.edu.pl pl.misc.elektronika:742956
    [ ukryj nagłówki ]

    W dniu 2019-05-09 o 08:04, Atlantis pisze:

    > Pracuję obecnie nad własną biblioteką do obsługi modułów DCF77
    > (częściowo opierając się na kodzie Arduino). Niby działa, jednak od
    > czasu do czasu pojawiają się problemu i dekodowany czas różni się od
    > poprawnego.

    Może Ci się przyda.
    Dawno, dawno temu (lata 95..97) zrobiłem odbiornik DCF podłączony pod
    COM komputera (zasilanie też z COM). Odbiornik wystawiał sygnał z DCF na
    którejś z linii RS232 i z tej linii go czytałem.
    Trochę się naszukałem w starych plikach, ale znalazłem. Poniżej źródła.
    Zauważyłem, że odwołuję się do doneinfo.h. Poszukałem co to takiego -
    jakaś forma linijki pokazującej postęp procesu - nie ma związku z samym DCF.
    Nie chce mi się wczytywać w szczegóły. Na pierwszy rzut oka widzę, że:
    - RS232 obsługuję po adresach - tak się robiło pod DOS
    - do odmierzania czasu używam wysyłania w koło czegoś po RS232

    Przy ^C^V program pocztowy pozawijał niektóre linijki.

    ============================= plik DCF77.H ============================
    // dcf77.h
    // DCF77 class - odbior sygnalu DCF77 przez port RS232

    #ifndef __DCF77_H
    #define __DCF77_H

    #ifndef __DONEINFO_H
    #include "doneinfo.h"
    #endif

    typedef unsigned char BYTE;
    typedef unsigned short WORD;
    typedef unsigned long DWORD;

    class DCF77
    {
    DWORD blo; // bufory na zbierane bity
    WORD bhi;
    int addr; // adres portu


    enum {DLL=0, // Divisor Latch Low byte
    DLH = 1, // Divisor Latch High byte
    IER = 1, // Interrupt Enable Register - zezw. na przerwania
    IIR = 2, // Interrupt Identification Register
    LCR = 3, // Line Control Register - tryb transmisji
    MCR = 4, // Modem Control Register - set innych linii
    LSR = 5, // Line Status Register - stan transmisji
    MSR = 6}; // Modem Status Register - stan innych linii

    int parity(WORD w); // sprawdzenie parzystosci slowa

    public:
    DCF77(int com); // konstruktor

    int read(DoneInfo *d=0); // odbior DCF77 ret:n imp (<0-bledy)
    int gettime(struct time *t); // odczytany czas ret:0-ok,1-err
    int getdate(struct date* d); // odczytana data ret:0-ok,1-err
    };

    #endif // __DCF77_H


    ============================ plik DCF77.CPP ============================
    // dcf77.cpp
    // DCF77 class - odbior sygnalu DCF77 przez port RS232

    #include <dos.h>
    #include <conio.h>

    #include "dcf77.h"

    DCF77::DCF77(int com):blo(0),bhi(0)
    {
    static int adrt[4]={0x3F8,0x2F8,0x3E8,0x2E8}; // adresy COM-ow

    int div=48; // predkosc 2400
    int lcr=3; // format 8N1
    int mcr=1; // DTR=1
    addr=adrt[com];

    outportb(addr+LCR,0x80); // Divisor Latch Access
    outportb(addr,div&0xFF); // Divisor Latch low byte
    outportb(addr+DLH,div>>8); // high byte
    outportb(addr+LCR,lcr); // Line Control Register
    outportb(addr+MCR,mcr); // Modem Control Register
    outportb(addr+IER,0); // Interrupt Enable Register
    inportb(addr); // wyczyszczenie bufora
    outportb(addr,0); // zapelnienie bufora nadawczego
    outportb(addr,0);
    }

    int DCF77::parity(WORD w)
    {
    w^=w>>8;w^=w>>4;w^=w>>2;w^=w>>1;
    return w&1;
    }

    // zwraca:
    // nb = liczba odebranych impulsow, powinno byc co najmniej 39 impulsow
    // -1 = brak impulsow przez 5 sekund
    // -2 = nie podlaczony odbiornik - szum zamiast impulsow
    // -3 = brak konca
    // -4 = klawisz

    int DCF77::read(DoneInfo *d) // odbior DCF77
    {
    int b,b0=0x10,b1=0x10; // 0x10 -> dodatnie zbocze bedzie prawdziwe
    int valid=0; // na poczatku pracy
    int dn=0; // licznik petli w sekundzie DCF77
    int lock=0; // blokowanie analizy linii wejsciowej
    int down=0; // bylo ujemne zbocze
    int nb=0; // licznik odebranych bitow
    int ns=0; // licznik zmian stanu w czasie blokowania

    // w jednej sekundzie miesci sie 240 nadan 2400B:8N1
    static const
    lockT=234, // blokada dla calego okresu (0.975s)
    lockt=18, // blokada dla impulsu (0.075s)
    lim2s=420, // czas dla znacznika konca (1.75s)
    lim01=31, // prog rozroznienia 0/1 (0.13s)
    lim5s=1200; // czas dla braku impulsow (5s)

    bhi=0; // zeruje bufory wynikowe
    blo=0;
    if(d)d->limit(60); // po 59 impulsie czeka jeszcze 2s
    while(1){
    if(inportb(addr+LSR)&0x20){
    outportb(addr,0); // teraz mamy troche czasu bez naruszania dn
    if(down){ // bylo ujemne zbocze - przetwarzanie i info
    blo>>=1;
    if(bhi&1L)blo|=0x80000000L; // przeniesienie bitu
    bhi>>=1;
    if(dn>lim01)bhi|=0x8000; // wpisanie aktualnego bitu
    nb++; // liczba odebranych bitow
    if(d)d->done(nb); // to moze zajac czas (dlatego down)
    down=0; // obsluzone
    }
    dn++; // licznik wyslanych przez RS232 bajtow w impulsie DCF
    if(dn>lim5s)return -1; // brak impulsow
    if(nb>60)return -3; // za duzo impulsow
    if(kbhit()){getch();return -4;} // nacisniety klawisz
    }

    b=inportb(addr+MSR)&0x10; // sprawdzenie linii wejsciowej
    if(dn>lock){ // tylko gdy nie ma blokady
    if(b!=b0){ // zmiana stanu
    b0=b; // nowy stan
    if(valid){ // juz bylo pierwsze dodatnie zbocze
    if(b){ // dodatnie zbocze
    if(dn>lim2s)return nb; // koniec minuty (dn>1.75s)
    lock=lockt; // blokada do 0.075s
    }
    else{ // ujemne zbocze
    down=1; // flaga ujemnego zbocza
    lock=lockT; // blokada do 0.975 s
    }
    }
    if(b){valid=1;dn=0;}// juz bylo dodatnie zbocze i licznik od 0
    b1=b;
    ns=0;
    }
    }
    if(b!=b1){ // nieoczekiwana zmiana stanu
    b1=b;
    if(++ns>9)return -2; // szum - nie podlaczony odbiornik
    }
    }
    }

    int DCF77::gettime(struct time *t) // odczytany czas ret:0-ok,1-err
    {
    int h,l;

    if((blo&0x200)==0 || // nie ma bitu startu
    parity(WORD((blo>>10)&0xFF)) || // parzystosc minut
    parity(WORD((blo>>18)&0x7F)) )return 1; // parzystosc godzin

    h=int((blo>>14)&7);l=int((blo>>10)&0xF);t->ti_min=h*
    10+l;
    if(h>5 || l>9)return 1; // zle wartosci dla minut

    h=int((blo>>22)&3);l=int((blo>>18)&0xF);t->ti_hour=h
    *10+l;
    if(h>2 || l>9 || t->ti_hour>23)return 1; // zle wartosci dla godzin
    t->ti_sec=0;
    t->ti_hund=0;
    return 0;
    }

    int DCF77::getdate(struct date* d) // odczytana data ret:0-ok,1-err
    {
    int h,l,y;

    if((blo&0x200)==0 || // nie ma bitu startu
    parity(WORD(blo>>25))^parity(bhi) )return 1;// parzystosc daty

    h=int((blo>>29)&3);l=int((blo>>25)&0xF);d->da_day=h*
    10+l;
    if(l>9 || d->da_day>31)return 1; // zle wartosci dnia

    h=(bhi>>6)&1;l=(bhi>>2)&0xF;d->da_mon=h*10+l;
    if(l>9 || d->da_mon>12)return 1; // zle wartosci miesiaca

    h=(bhi>>11)&0xF;l=(bhi>>7)&0xF;y=h*10+l;
    if(h>9 || l>9)return 1;
    d->da_year=(y<98)?2000+y:1900+y; // prawidlowo do 2097 roku
    return 0;
    }

Podziel się

Poleć ten post znajomemu poleć

Wydrukuj ten post drukuj


Następne wpisy z tego wątku

Najnowsze wątki z tej grupy


Najnowsze wątki

Szukaj w grupach

Eksperci egospodarka.pl

1 1 1

Wpisz nazwę miasta, dla którego chcesz znaleźć jednostkę ZUS.

Wzory dokumentów

Bezpłatne wzory dokumentów i formularzy.
Wyszukaj i pobierz za darmo: