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...
Didn't find your answer? Ask the community — no account required.
M
Mateusz Viste
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
P
Piotr Gałka
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];
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>>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; }
P
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.
A
Atlantis
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. ;)
C
Cezar
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
C
Cezar
tutaj mozesz zobaczyć ramki na żywo, bit po bicie:
formatting link
A
Atlantis
Dzięki. Właśnie tego potrzebowałem. ;)
R
robot
W dniu 2019-05-09 o 10:53, Piotr Gałka pisze:
Już dawno to zauważyłem. To widocznie standardowe zachowanie thunderbirda.
Join the Discussion
Have something to add? Share your thoughts — no account required.
Didn't find your answer?
Ask the community — no account required
Report Content
You are reporting this content to the moderators. They will look at it
ASAP.