CPU z kwarcem do transmisji szeregowej a odliczanie 1ms

Jun 30, 2005 35 Replies

Kwestia wielkosci arytmetyki tylko :-) Spojrz na linuxa - masz mikroadjustacje zegara w jadrze i akceptuje wszystkie kwarce :-)

J.

Hm - z powodu tego /8 masz czestotliwosc 5400 Hz. To daje jitter ~0.1ms

Zauwaz ze mozesz podzielic obie liczby przez 100. A nawet przez 200. Przy zalozeniu ze kwarc zawsze podasz z dwoma zerami na koncu, to w zasadzie zawsze mozesz podzielic

troche pozwala .. a C++ to ponoc nawet duzo :-)

Nie musi byc taki. Z jednej strony chcesz wielokrotnosc

153600 [16*9600 - czy szybciej]. Z drugiej - wielokrotnosc 1000 [8000 ?]. LCM wychodzi 768kHz .. i dowolna wielokrotnosc tego bedzie dobra. W szczegolnosci: 7680000 8448000 9216000 9984000 10752000 11520000

hm .. chyba zadnych takich nie robia :-(. Z drugiej strony .. chyba 10MHz by sie ladnie nadawal, dla RS te 0.2% roznicy nie ma zadnego znaczenia :-)

J.

J.

Tja, zaraz na Army wejdziemy z tą arytmetyką ;)

sword

No to na pewno nie z tego powodu masz błędy, to ile bajtów jest do wysłania nie ma przecież znaczenia bo synchronicacja jest do każdego. Teoretycznie to odchyłka może sięgać 10%, tylko wtedy to raczej dostaniesz frame error. Przyczyny takich przekłamań szukałbym raczej w innym miejscu (np. pcb).

sword

U¿ytkownik "Sebastian Bialy" snipped-for-privacy@poczta.onet.pl> napisa³ w wiadomo¶ci news:da31em$b2k$ snipped-for-privacy@nemesis.news.tpi.pl...

akceptacji.

RS232 synchronizuje siê do ka¿dego bitu startu, a nie do ca³ego bloku. Dok³adno¶æ musi wytrzymaæ tylko 10 bitów. Odchy³ka czêstotliwo¶ci 2% da b³±d odczytu ostatniego bitu 20% (zamiast w ¶rodku bitu (50%) to w 30% lub 70% jego czasu). Trzeba wiedzieæ, co siê dzieje ze zboczami w transmisji (eye diagram) i mo¿na praktycznie unikn±æ jakichkolwiek b³êdów.

P.G.

Nie, raczej nie. Odbiornikiem jest fabryczny konwerter RS232->RS485. Ponieważ nie miałem w domu kwarcu 11.0592 musiałem wstawić 10. Prawidłowo obliczyłem (z resztą jest w dokumantacji do CPU) parametry. Ilośc błędów CRC modbus wzrosła do niepokojącego poziomu. Program różnił się wyłacznie współczynnikiem podziału UART.

Zmiana nastepnego dnia kwarcu na 11.0592 spowodowała powrót do normalnej pracy (jeden/dwa CRC na godzinę).

Może powodem jest _dośc odległa_ magistrala (około 300m).

Nic nie szkodzi, chodzi o stabilnośc długofalową (rzedu parudziesięciu sekund).

Mogę, niestety muszę to znaleźć w sposób, który zwalnia programistę wykorzystaującego ten moduł od myślenia (bo tak się składa, że to ja będe :P).

Żartuje :)

No nic, potestuje teraz na moim konwerterze czy faktycznie kwarce "nie-rs" nie będa robic różnicy. Niestety na fabrycznym konwerterze sypie błędami CRC przy kwarcu 10MHz :(

Jesli to zawsze bedzie 1000Hz, i kwarc w miare z zakresu 5-15MHz, to mozesz przez 100 dzielic od razu. Niech sobie programista wpisuje ile chce na koncu, po podzialeniu i tak wyyjdzie dobrze. A kwarc .. przy 50ppm i tak mamy +/-500Hz :-)

A predkosc masz 9600 i zadnych preskalerow ? bo niestety

10M/9600/16=65.1, i na zaden inny podzial 65 nie ma tu juz miejsca ..

J.

Sprawa jest prosta.

Masz zegar 11059000 Hz. Wliczając że przerwanie jest co 256 cyknięć to okres przerwań wynosi w przybliżeniu 23149 ns. Potrzebujesz odmierzać

1ms = 1000000 ps.

deklarujesz co najmniej 24-bitowy licznik. Za każdym tyknięciem przerwania dodajesz mu 23149 i sprawdzasz, czy przekroczono 1000000. Jeśli tak to robisz co trzeba co te 1ms i od zawartości licznika odejmujesz 1000000. Reszta która zostanie powoduje że w następnej rundce pamiętana jest poprawka na to że to 1ms jest całkowicie niesychroniczne z czymkolwiek w procku.

TP.

Dokładnie tak mam teraz, szukam jednak czegos prostszego i uniwersalnego jednocześnie. coraz bardziej jednak utwierdzam się w przekonaniu, że pewnie prościej (i uniwersalniej jednoczęsnie) się nie da.

Oczywiście 1ms = 1000000 ns.

TP.

I w³a¶nie po to mikrokontrolerom jest potrzebne C++ (a nie do jakiego¶ tam programowania obiektowego):

template <unsigned long m, unsigned long n> struct gcd {

enum { val = gcd<n, (m % n)>::val }; };

template <unsigned long m> struct gcd<m, 0U> {

enum { val = m }; };

template <unsigned long m, unsigned long n> struct lcm {

enum { val = (m*n)/gcd<m,n>::val }; };

test:

std::cout << gcd<20,24>::val << " " << lcm<20,24>::val << std::endl;

4 120

Pozdrawiam Piotr Wyderski

template <typename T> struct property {

enum { is_unsigned_short = 0 }; };

template <> struct property<unsigned short> {

enum { is_unsigned_short = 1 }; };

test:

std::cout << property<int>::is_unsigned_short << " " << property<unsigned short>::is_unsigned_short << std::endl;

0 1

:-) To tylko drobna próbka. Teraz rozumiesz, czemu cierpiê pisz±c w VHDL? ;-)

Z nieznajomo¶ci C? ;-> Makroekspansja nie dzia³a rekurencyjnie, wiêc preprocesorem niczego nie zwojujesz. Potrzebujesz szablonów, a wiêc C++. One s± z kolei trochê "za silne" -- da siê w nich zakodowaæ maszynê Turinga, a wiêc i DOWOLNY program. W poprzednim li¶cie zapisa³em alg. Euklidesa.

Standardowy C++ pozwala. Co prawda jego twórcy tego nie przewidzieli, ale oni w ogóle ma³o przewidzieli. ;-D

Pozdrawiam Piotr Wyderski

:-)))

Ano ni ma, Panocku. :-)

Pozdrawiam Piotr Wyderski

No bez przesady -- wystarczy dopisaæ dwa krzy¿yki do tego C i rzecz stanie siê implementowalna na poziomie jêzyka, bez potrzeby u¿ywania dodatkowych narzêdzi.

Pozdrawiam Piotr Wyderski

A nie 11059 MHz? Czyli 11059000 kHz?

A nie 43199.21875 kHz? Czyli 43199218.75 Hz?

Musisz dzielić przez 43199.21875000000000000000, co nie jest optymalne.

Ja bym zrobił tak:

  1. Punkt wejścia do przerwania.
  2. Zwiększ licznik1 (8 bitowy).
  3. Jeśli licznik1 się nie przepełnił, to koniec.
  4. Zwiększ licznik2 (8 bitowy).
  5. Jeśli licznik2 nie osiągnął 168 to koniec.
  6. Wyzeruj licznik2.
  7. Wywołaj swoją procedurę.
  8. Koniec.

Procedura będzie wywoływana 43199218.75/(256*168) razy na sekundę, czyli 1004.44612048921130952380 Hz. Może być?

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required