Próbuję użyć Timera1 mikrokontrolera AVR Atmel, albo AtMega328, jak w Arduino, lub ATTiny85, aby wyprowadzić dwa sygnały zegarowe, które są wzajemnie odbiciami lustrzanymi. Częstotliwość, którą próbuję wygenerować, jest zmienną od 1 MHz do 2 MHz lub więcej, które są zbyt wysokie, aby to zrobić za pomocą kodu do przełączania pinów wyjściowych, chyba że nie chcę nic więcej robić w kontrolerze. Chcę więc użyć wyjścia timera bezpośrednio na powiązanych pinach. Korzystam z zestawu narzędzi GCC, więc nie są ograniczone bibliotekami lub językami Arduino.
Timer1 w Atmega328 ma z nim dwa piny i mogę wydobyć z nich dwa identyczne sygnały od 1MHz do 2MHz. Chociaż wydaje się, że arkusz danych mówi, że mogę uzyskać odwrócony przebieg, to mnie dezorientuje. Jestem w stanie uzyskać dwa sygnały, które są różnymi cyklami pracy przy 1 MHz, używając ustawień PWM z Timerem 1, ale oba sygnały idą jednocześnie w górę, tym krótszy wcześniej. To nie służy mojemu projektowi. Nie potrzebuję nawet zmiany szerokości impulsu PWM, potrzebuję tylko dwóch identycznych sygnałów typu „zegar” przeciwnej fazy, to wszystko.
Nie proszę nikogo o napisanie dla mnie kodu, po prostu potrzebuję kogoś, kto powie mi, który tryb / flagi timera powinny dać mi prosty odwrócony przebieg na jednym z dwóch pinów powiązanych z timerem. Jeśli to możliwe, chcę uniknąć używania zewnętrznego obwodu odwracającego dla jednego z wyjść, chyba że jest to tylko opcja.
Jeśli jest to w ogóle możliwe w ATTiny, będzie jeszcze lepiej. ATTiny ma również 2 piny związane z jednym zegarem, ale nie jestem pewien, czy ma takie same opcje jak ATMega.
Mam już kryształ 20 MHz i kondensatory podłączone na płytce drukowanej, a zegar 20 MHz działa niezawodnie na ATMega328. Na płytce ATTiny85 mam kryształ 8 MHz, który również działa niezawodnie.
Proszę pomóż. Dziękuję Ci.
AKTUALIZACJA : Do tej pory w odpowiedziach i komentarzach są pewne nieprawidłowe założenia, więc może powinienem wyjaśnić: Zauważ, że w moim oryginalnym poście stwierdziłem, że używam zegara 20 MHz, a nie 8 MHz , a także, że nie potrzebuję PWM .
Jedynym trybem, który zapewnia wystarczająco wysoką częstotliwość wyjściową, wydaje się być tryb CTC, ponieważ tryby PWM nie działają na wyjściu 2 MHz. Czy istnieje sposób na odwrócenie wyjścia Timera 1 A lub wyjścia B w trybie CTC?
Teraz sprawdziłem swój kod na standardowym Arduino Uno (ATMega328, 16 MHz) zamiast na własnej płycie 20 MHz, a to jest mój kod ładnego stałego zegara 2 MHz w trybie CTC ze styków 9 i 10, Timer 1 styki wyjściowe:
#define tick 9
#define tock 10
void setup() {
pinMode(tick, OUTPUT);
pinMode(tock, OUTPUT);
TCCR1A = _BV(COM1A0) | _BV(COM1B0) ; // activate both output pins
TCCR1B = _BV(WGM12)| 1; // set CTC mode, prescaler mode 1
// various frustrating attempts to invert OC1B failed. What do I put here?
OCR1A = 3; // set the counter max for 2 MHz
}
void loop() {
}
Ślady oscyloskopu dla obu pinów są identyczne i zsynchronizowane, jak mogę odwrócić jeden z dwóch sygnałów? Tryb odwracania w arkuszu danych wydaje się nic nie robić w trybie CTC. Czy źle czytam arkusz danych, czy w końcu będę zmuszony użyć niższej częstotliwości i trybu PWM?
Aby dodać określone pytanie „nagroda” do mojego pierwotnego zapytania:
Więc jakie zmiany muszę wprowadzić w powyższym kodzie, aby nadawał idealnie odwrócony sygnał na styku 9 i 11 przy najwyższej możliwej częstotliwości dla zegara 16 MHz , czy to jest 2 MHz czy nie?
Na razie będę się trzymał standardowego Arduino Uno, aby moja własna płyta nie wprowadziła trybu błędu i aby każdy, kto ma arduino, mógł wypróbować mój kod powyżej i potwierdzić, że działa tak, jak wspomniałem, a nie tak, jak ja potrzeba!
Odpowiedzi:
Z arkusza danych ATtiny85:
Tabela 11-5 pokazuje, jak ustawić tryb.
Chcesz szybkiego trybu PWM (więc albo w trybie 3, albo w trybie 7). Jeśli chcesz zmieniać cykl pracy i brzmi to tak, jak chcesz, chcesz tryb 7 i zmieniać cykl pracy, ustawiając OCRA.
Tabela 11-3 pokazuje, jak ustawić tryb wyjścia porównania dla trybu szybkiego PWM.
To znaczy, możesz ustawić wyjście OC0A tak, aby było niskie, gdy wartość Timera == OCR0A, i wysokie, gdy wartość Timera == 0x00, ustawiając COM0A1: COM0A0 = 0b10. Lub odwrotnie, ustawiając COM0A1: COM0A0 = 0b11. I podobnie dla OC0B, OCR0B, COM0B0, COM0B1.
Częstotliwość PWM jest określana przez Zegar I / O (8MHz, jak dla Ciebie brzmi) i ustawienie preskalera timera. Równanie jest podane jako f_clk_IO / (N * 256) dla trybu szybkiego PWM.
Możesz więc użyć OC0A dla polaryzacji „normalnej” i OC0B dla polaryzacji „odwróconej”, ustawiając OCR0A i OCR0B na tę samą wartość i ustawiając COM0A1: COM0A0 = 0b10 i COM0B1: COM0B0 na 0b11.
AKTUALIZACJA
Biorąc pod uwagę, że chcesz przełączyć wyjście tak szybko, jak to możliwe i używasz Mega328 pracującego z częstotliwością 16 MHz, tryb pracy CTC pozwoli ci uzyskać częstotliwość przełączania:
f_OCnA = f_clk_IO / (2 * N * [1 + OCRnA) = 16e6 / (2 * 1 * [1 + 1]) = 4 MHz
Tryb Fast PWM pozwala przełączać pin na:
f_OCnxPWM = f_clk_IO / (N * [1 + TOP]) = 16e6 / (1 * [1 + 1]) = 8 MHz
Więc nadal uważam, że chcesz szybkiego trybu PWM. W szczególności tryb 3 z OCR0A = OCR0B = 0x80 dla 50% cyklu pracy. I ustaw bity COM0A na 0x3, a bity COM0B na 0x2, aby utworzyć dwa przebiegi na odwróceniu OC0A i OC0B.
Aktualizacja # 2 Więcej Mega328 Wypróbuj ten kod Arduino:
źródło
Rodzina ATtinyX5 ma PLL wewnątrz, użyj go, duży chłopcze.
Używam również wewnętrznego PLL do zasilania zegara procesora i mam 16 MHz bez XTAL. Jest to cenne, ponieważ masz tylko 5 pinów. (Nie liczę kodu PIN resetowania). Również jeden PWM (PLCR) PWM (OCR1B) działa na pinach XTAL z opcjonalnym wyjściem komplementarnym. Musisz tylko wyregulować bezpieczniki dla Xtalless ATtiny 16 MHz ... Lub po prostu pozwolić procesorowi pracować na 8 MHz, ale uruchomić PWM z zegarem 64 MHz bez zmiany bezpieczników.
Możesz mieć PWM z zegarem do 64 MHz (ale z rozdzielczością 1-bitową). Lub 125 Khz przy rozdzielczości 8 bitów. Możesz zmniejszyć rozdzielczość PWM i zwiększyć prędkość poprzez zmniejszenie rejestru OCR1C.
Dla 1 Mhz musisz ustawić OCR1C na 63. Dla 2 Mhz musisz ustawić OCR1C na 31. Dla 4 Mhz musisz ustawić OCR1C na 15. ...
Wystarczy włączyć PLL za pomocą tego kodu:
Teraz masz 64 MHz zegar na PWM „OCR1B0 / OCR1A0”.
Możesz także ustawić OCR1 [A / B] 0 i XOCR1 [A / B] 0 dla wyjścia lustrzanego.
Musisz wiedzieć, że Dead Time Generator zje PWM outout, jeśli ustawisz OCR1A = 1. Potrzebujesz wartości wyższych niż czas martwy.
Pozdrowienia,
Erdem
źródło