Przyjęta odpowiedź jfpoilpret jest bardzo dobrze napisana, doskonale poprawna iw 99% przypadków zrobię dokładnie to, co on wyjaśni. Jego rozwiązania mieszczą się w określonych parametrach, więc powinny działać bardzo dobrze. Ale co jest lepszego niż „ bardzo dobrze ”? Doskonałość! W końcu chodzi o wygenerowanie dokładnej wartości. Jak powiedziano, wystarczająco blisko jest dobre w większości przypadków (prawdopodobnie wszystkie), a nawet mając do czynienia z zegarem, gdy 1 sekunda musi wynosić 1 sekundę, nadal musisz cierpieć z powodu niedoskonałości odziedziczonych części.
To, co zasugeruję, nie zawsze jest możliwe. W niektórych przypadkach jest to możliwe, ale przy znacznie większym wysiłku i wysiłku niż w tym przypadku. Czy warto, zależnie od przypadku. Moim celem jest przede wszystkim pokazanie alternatywy dla przyszłych referencji, która jest lepsza w nieco marginalnych przypadkach. Jest to napisane z myślą o początkujących użytkownikach Arduino, którzy nie mają dużego doświadczenia w elektronice.
Dla bardziej zaawansowanych ludzi prawdopodobnie będzie to wyglądać zbyt rozwlekle i głupio. Ale wierzę, że ci sami ludzie prawdopodobnie już to wiedzą i nie potrzebują tej odpowiedzi. Dotyczy to również każdego mikrokontrolera oraz każdego producenta i architektury. Jednak w przypadku innych mikrokontrolerów należy zapoznać się z właściwym arkuszem danych, aby znaleźć odpowiednie rejestry oraz wstępnie skalować nazwy i wartości.
W twoim przypadku potrzebujesz konkretnej częstotliwości, a miłą rzeczą jest to, że dokładnie 56 kHz można osiągnąć bardzo łatwo (nie licząc praktycznych niedoskonałości części). Jest to więc również doskonały przykład.
Generowanie sygnału zależy od timerów i źródła zegara mikrokontrolera, co dobrze wyjaśniono w jfpoilpret. Jego odpowiedź dotyczy problemu tylko jednego punktu widzenia i bawi się licznikami czasu. Ale możesz także bawić się ze źródłem zegara, a nawet lepiej, zarówno w celu uzyskania synergii, jak i niesamowitych wyników. Zmieniając parametry środowiska, w tym przypadku włamując się do systemu i zastępując źródło zegara, możemy poradzić sobie z konkretnym problemem o wiele, wiele łatwiej i łatwiej.
Najpierw przypomnijmy, ze względu na przełączanie stanu pinów, musisz wykonać ISR dwa razy więcej niż częstotliwość sygnału. To 112 000 razy na sekundę. 56 000 i 16 000 000 nie sumuje się tak ładnie, jak już wspomniano. Musimy zmienić częstotliwość sygnału lub częstotliwość taktu. Zajmijmy się na razie niezmienną częstotliwością sygnału i znajdźmy lepszą częstotliwość zegara.
Najłatwiej byłoby wybrać zegar o pewnym rzędzie wielkości większym niż 56 kHz (lub 112 kHz, ale jest praktycznie taki sam), ponieważ dodajesz tylko zera, a matematyka jest najprostsza dla większości ludzi. Niestety wszystko na tym świecie jest z czymś kompromisem. Nie każda wartość będzie działać.
Pierwszy przykład dotyczy zbyt niskiej prędkości generatora taktu.
Jeśli wybierzesz zegar o częstotliwości 56 000 Hz, nie będziesz w stanie nic zrobić, ponieważ będziesz musiał wywoływać ISR w każdym cyklu i nie będziesz mógł zrobić nic innego. Jest to całkowicie bezużyteczne. Jeśli wybierzesz 10-krotnie większą prędkość (560 kHz), będziesz mieć 9 (10 cykli, aby zegar osiągnął maksymalną wartość - jeden cykl, aby wywołać funkcję ISR) cykli mikrokontrolera, aby wykonać twoją pracę i to całkiem możliwe, może to nie wystarczyć. Po prostu często potrzebujesz większej mocy obliczeniowej.
Jeśli z drugiej strony wybierzesz wartość zbyt wielką, ponieważ 56 MHz mikrokontroler po prostu nie może z nią pracować. To jest zbyt szybkie. Tak więc samo wybranie największej wartości w sklepie też jej nie zmniejszy.
Oryginalny Arduino Uno R3 ma zapasowy zegar 16 MHz, więc wszystko wolniejsze, co gwarantuje działanie. Kolejna wartość, która jest o rząd wielkości większa niż 56 i mniejsza niż 16 MHz, wynosi 5,6 MHz. Doprowadzi to do możliwości wywoływania ISR co 50 cykli i stworzy idealną częstotliwość zegara wynoszącą 112 000 Hz. Twój sygnał wyniesie dokładnie 56 kHz. Będziesz miał 49 cykli MCU, aby wykonać swój program między wywołaniami ISR, ale nadal jest to około 1/3 prędkości oryginalnego zegara. Można użyć numeru 112 jako podstawy i użyć zegara 11,2 MHz, co da około 2/3 podstawowego rezonatora 16 MHz. Funkcja ISR będzie wywoływana co 100 cykli i nadal generuje doskonały sygnał 56 kHz.
Istnieją jednak dwa główne problemy z tymi wartościami.
Pierwszy problem poważnie zależy od twoich potrzeb: poświęcasz około 1/3 (przy 11,2 MHz) maksymalnej mocy obliczeniowej, aby uzyskać dokładną częstotliwość sygnału, która wykorzystuje łatwą do znalezienia wartość rejestru (OCR iirc ). Możesz sobie z tym poradzić lub nie.
Drugi problem to trudny showstopper : bardzo łatwo jest znaleźć wartości, ale bardzo często po prostu nie istnieją one jako wyprodukowane źródło zegara. To strona rezonatora Farnella, której po prostu brakuje zarówno 5,6 MHz, jak i 11,2 MHz.
Aby tego uniknąć, możemy przyjrzeć się dostępnym wartościom rezonatora i dowiedzieć się czegoś innego, co można wykorzystać do wygenerowania dokładnie pożądanych wartości. Jeśli podzielimy 56 przez 4, otrzymamy 14 i na szczęście powstanie rezonator 14 MHz. To zapewnia nam znacznie większą prędkość i więcej mocy oraz równie łatwą do znalezienia wartość rejestru. Aby wywołać ISR 112 000 razy na sekundę, musimy wpisać wartość dziesiętną 124 lub szesnastkową 0x7C do rejestru OCR, więc licząc 124 cykle + 1 dla wywołania ISR, otrzymujemy pożądaną idealną wartość.
NB
- ISR - procedura obsługi przerwań (jest to kod wykonywany tylko na wygenerowanych przerwaniach)
- Jak duży może być Twój program, zależy od wielkości pamięci! Nie ma to nic wspólnego z częstotliwością zegara i nie ma związku z częstotliwością wywoływania ISR.
Kiedy mikrokontroler zaczyna się od polecenia programu, licznik jest zwiększany. Jeśli generowane jest przerwanie, wywoływany jest ISR i ta wartość jest przechowywana w specjalnym rejestrze. Po zakończeniu kodu ISR wartość licznika programu jest przywracana z tego specjalnego rejestru, a program kontynuuje działanie od miejsca, w którym został przerwany, jak gdyby nigdy się nie zdarzyło.
Podam wyjątkowo głupi przykład. Jeśli jesteś purystą, ostrzegam: może wystąpić krwawienie z nosa i oka.
Wyobraź sobie, że musisz gdzieś iść. Instrukcje trasy krok po kroku to twój główny program i jego polecenia. Szybkość marszu lub biegu zależy od „prędkości zegara”, ale nie od instrukcji na trasie (30 kroków do przodu, 1 skręt o 90 stopni w lewo, 10 kroków do przodu, 45 stopni w prawo itp.) Zawsze są takie same . Teraz wyobraź sobie, że małe dziecko lub chciwy skorumpowany lokalny polityk od czasu do czasu rozwiązuje twoje buty. To zdarzenie generuje przerwanie. Potem zatrzymujesz się po ostatnim kroku, klękasz i ponownie wiążesz but. To jest twój program ISR.
Następnie kontynuuj od miejsca, w którym się zatrzymałeś; nie zaczynasz od początku. Kiedy idziesz bez opieki po świecie i cały czas, nie przejmujesz się, nawet jeśli musisz wiązać but co drugi krok. Jeśli jednak zrobisz to z ograniczeniami czasowymi, takimi jak bieganie w odległości 100 metrów na olimpiadzie (lub bieganie z głodnego drapieżnika, który zjada mięso), zatrzymanie i zawiązanie butów może mieć tragiczne konsekwencje. To samo dotyczy mikrokontrolerów. Nawet jeśli wykonasz tylko jedną linię kodu, twój program będzie kontynuował, choć powolny. Jeśli w ogóle nie zależy ci na prędkości, nie będzie problemu. Jeśli musisz zrobić trochę czasu, na przykład używając innych działań zależnych od timera, interferencja może być bardzo niepożądana i problematyczna.
Mniej znaczy więcej! Szybszy zegar nie zawsze jest lepszy. Wolniej taktowane urządzenia zużywają znacznie mniej energii. Może to być kluczowy punkt w urządzeniu zasilanym bateryjnie.
Potrzebne cykle pochodzą z tych wzorów:
(prędkość zegara / (wartość prekalera * potrzebna częstotliwość wywoływania ISR)) - 1