Przykładowe ramki DCF77

Szukam, ale jakoś znaleźć nie mogę... Potrzebuję przykładów poprawnych ramek DCF77, wraz z informacją na temat tego, jaki czas jest w nich zakodowany. Chodzi mi po prostu o ciąg bitów. 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. Chciałem teraz zrobić krok w tył i sprawdzić poprawność działania poszczególnych funkcji, kompilując je na PC, karmiąc spreparowanymi danymi i obserwując wynik.

Niby protokół jest opisany, jednak chcę mieć pewność, że i podczas preparowania ramki nie popełnię błędu...

Reply to
Atlantis
Loading thread data ...

To pewnie dla ciebie oczywistość, ale podczas transmisji mogą występować błędy... Zaufanie do pojedynczej ramki powinno być mocno ograniczone, a czas ustawiony tylko wówczas, kiedy ciąg kilku ramek konsekwentnie wskazuje bardzo zbliżony czas.

Mateusz

Reply to
Mateusz Viste

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

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; }

Reply to
Piotr Gałka

W dniu 2019-05-09 o 10:48, Piotr Gałka pisze:

Ciekawe. Przed wysłaniem były pozawijane. Jak po wysłaniu zajrzałem to nie są pozawijane.

Nigdy nie zadałem sobie trudu rozejrzenia się w ustawieniach Thunderbirda. P.G.

Reply to
Piotr Gałka

Tak. Biblioteka na której się opieram zawiera kilka "sanity checks". Problem polega na tym, że błędy nie są wynikiem problemy nie są efektem przekłamania w transmisji, ale jakiegoś błędu w kodzie. Przez to są one powtarzalne i występują w kolejnych ramkach, prowadząc do zaakceptowania błędnego czasu. Próbuję ustalić w którym miejscu się tak dzieje. A ponieważ zmęczyło mnie debugowanie na "żywym" układzie, w środku nocy, gdy propagacja się podnosi, chcę to zrobić w sposób opisany powyżej. ;)

Reply to
Atlantis

tutaj masz cos co generuje DCF na GPIO (razem z szumem)

formatting link

W tym repo masz bardzo duzo informacji jak walczyc z zakłóceniami:

formatting link

Reply to
Cezar

tutaj mozesz zobaczyć ramki na żywo, bit po bicie:

formatting link

Reply to
Cezar

Dzięki. Właśnie tego potrzebowałem. ;)

Reply to
Atlantis

W dniu 2019-05-09 o 10:53, Piotr Gałka pisze:

Już dawno to zauważyłem. To widocznie standardowe zachowanie thunderbirda.

Reply to
robot

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.