ATtiny2313A timer1 OC1A OC1B kod C i ASM do 50% przebiegu

Pytanie

Jak powinien wyglądać kod w języku .C i w j.ASM na Attiny 2313A według poniższych wskazówek. Oto te wskazówki :

"Cały czas mowa o precyzyjnych częstotliwościach, współczynniku wypełnienia a uczepiłaś się najgorszego z możliwych rozwiązań mając sprzętowe sterowanie GPIO, gdzie trzeba liczyć każdy cykl maszynowy jak w latach 80.
W Generatorze DDS z EP 6/2018 jest sprzętowe sterowanie wyjściem:
void Timer1_Start(uint8_t dzielnik)
{
// OCR1B=dzielnik;
OCR1B=dzielnik;

//Output compare toggles OC1A pin
// TCCR1A |= 0x40; // COM1A = 1
TCCR1A |= 0x10; // COM1B = 1
//start timer without prescaler
TCCR1B = 0b00001001; // WGM 12=1, CS=1

DDRD |= _BV(PD4);
}

Uzyskasz DOKŁADNIE 50% bez liczenia cykli. Nie muszą być włączone przerwania ale mogą. Program główny może robić co chce a nie wpłynie to na generowany przebieg bez względu na to, czy przerwania będą włączone czy nie. Max częstotliwość to Fclk/2, uzyskaj taką przez delay. Taki program jest krótszy niż z delay. Jeśli częstotliwość jest zbyt duża należy timery połączyć w kaskadę.
Można także użyć timera w trybie PWM. Używając OCRxA można ustawić próg zliczania a co za tym idzie, precyzyjnie regulować częstotliwość.

Głupotą jest, mając możliwości sprzętowe, rozwiązywać problem w sposób programowy.
Uważasz, że nie mam racji? Napisz na innych forach i zweryfikuj moją wiedzę."

Odpowiedź Sztucznej Inteligencji


Bezpośrednia odpowiedź na pytanie

Tak, sens wskazówek jest zasadniczo poprawny: na ATtiny2313A przebieg o precyzyjnej częstotliwości i dokładnym wypełnieniu 50% należy generować sprzętowo, przez Timer1 i wyjście OC1x, a nie przez pętle delay i ręczne przełączanie GPIO. Trzeba jednak skorygować dwa istotne błędy z przytoczonego fragmentu: na ATtiny2313A wyjścia OC1A i OC1B są na PB3 i PB4, a nie na PD4/PD5; dodatkowo w trybie CTC mode 4 wartość TOP ustala OCR1A, a nie OCR1B. Zatem pokazany kod w tej postaci nie jest poprawny dla regulacji częstotliwości na OC1B. (ww1.microchip.com)

Najprostsze i najczystsze rozwiązanie dla przebiegu prostokątnego 50% to:

  • Timer1, tryb CTC, TOP = OCR1A
  • Toggle OC1A on Compare Match
  • wyjście na PB3 / OC1A
  • częstotliwość:
    \[
    f{OUT}=\frac{f{clk_I/O}}{2 \cdot N \cdot (1+OCR1A)}
    \]
  • maksimum:
    \[
    f{OUT,\ max}=\frac{f{clk_I/O}}{2}
    \]
    dla OCR1A = 0 i preskalera N = 1. (ww1.microchip.com)

Bezpośrednia odpowiedź na pytanie Szczegółowa analiza problemu

Przytoczone wskazówki są słuszne co do idei, ale wymagają doprecyzowania pod konkretny układ ATtiny2313A. Najważniejsze jest rozróżnienie trzech rzeczy:

  1. który pin naprawdę jest wyjściem OC1A/OC1B,
  2. który rejestr wyznacza TOP w danym trybie,
  3. czy chcemy 50% stałe, czy regulowane wypełnienie PWM. (ww1.microchip.com)

Co w cytowanym kodzie jest błędne

W cytacie ustawiono:

  • TCCR1A |= 0x10; czyli COM1B0 = 1, a więc sprzętowe przełączanie OC1B,
  • DDRD |= _BV(PD4);, czyli jako wyjście ustawiany jest PD4.

To się nie zgadza z mapą pinów ATtiny2313A, bo:

Czyli jeśli chcesz używać COM1B0, to musisz wystawić sygnał na PB4, nie na PD4. (ww1.microchip.com)

Drugi błąd jest bardziej subtelny: w trybie CTC mode 4 (WGM13:0 = 0100) licznik zeruje się przy dopasowaniu do OCR1A. To znaczy, że częstotliwość ustala OCR1A, a nie OCR1B. OCR1B w tym trybie może generować zdarzenie porównania dla kanału B, ale nie definiuje TOP. Innymi słowy: jeśli ustawisz tylko OCR1B, to nie ustawiasz okresu timera. (ww1.microchip.com)

Poprawna architektura rozwiązania

Jeżeli celem jest:

  • dokładna częstotliwość,
  • idealne 50%,
  • brak wpływu kodu głównego,
  • brak konieczności liczenia cykli instrukcji,

to najlepsze rozwiązanie jest takie:

  • użyć Timer1 w CTC,
  • ustawić toggle na OC1A,
  • podać OCR1A = TOP,
  • skonfigurować PB3 jako wyjście. (ww1.microchip.com)

To jest rozwiązanie lepsze od delay, bo przełączanie pinu realizuje blok sprzętowy timera, a nie CPU. Z praktycznego punktu widzenia oznacza to, że pętla główna może wykonywać inne zadania i nie zmieni to generowanej częstotliwości ani wypełnienia; ograniczeniem pozostaje jedynie stabilność źródła zegara mikrokontrolera. To jest wniosek wynikający z tego, że wyjście OC1x jest sterowane bezpośrednio przez moduł compare timera po ustawieniu bitów COM1x i odpowiedniego bitu DDR. (ww1.microchip.com)

Poprawny kod w języku C — rekomendowany wariant 50%

Poniżej jest wersja, którą uznałbym za wzorcową dla prostokąta 50% na OC1A / PB3:

#define F_CPU 8000000UL
#include <avr/io.h>
#include <stdint.h>
static inline uint16_t timer1_top_from_freq(uint32_t f_cpu,
                                            uint16_t prescaler,
                                            uint32_t f_out)
{
    return (uint16_t)((f_cpu / (2UL * prescaler * f_out)) - 1UL);
}
/*
 * Generator prostokąta 50% na OC1A (PB3)
 * Tryb: CTC, TOP = OCR1A
 *
 * f_out = F_CPU / (2 * N * (1 + OCR1A))
 *
 * cs_bits:
 *   (1<<CS10)                    -> N = 1
 *   (1<<CS11)                    -> N = 8
 *   (1<<CS11) | (1<<CS10)        -> N = 64
 *   (1<<CS12)                    -> N = 256
 *   (1<<CS12) | (1<<CS10)        -> N = 1024
 */
void Timer1_Square_OC1A_Start(uint16_t top, uint8_t cs_bits)
{
    TCCR1A = 0;
    TCCR1B = 0;
    TCNT1  = 0;
    OCR1A = top;              // TOP dla trybu CTC mode 4
    DDRB |= _BV(PB3);         // PB3 = OC1A jako wyjście
    TCCR1A = _BV(COM1A0);     // Toggle OC1A on Compare Match
    TCCR1B = _BV(WGM12) | (cs_bits & 0x07);   // CTC, start timera
}
int main(void)
{
    // Przykład: 1 kHz przy F_CPU = 8 MHz, preskaler = 1
    // OCR1A = 8000000 / (2*1*1000) - 1 = 3999
    uint16_t top = timer1_top_from_freq(F_CPU, 1, 1000);
    Timer1_Square_OC1A_Start(top, _BV(CS10));
    while (1)
    {
        // Kod główny może robić co chce.
        // Generacja przebiegu jest sprzętowa.
    }
}

Ten kod jest zgodny z dokumentacją: COM1A0=1 daje przełączanie wyjścia OC1A przy compare match w trybie nie-PWM, a WGM12=1 wybiera tryb CTC mode 4, gdzie OCR1A jest TOP. Pin wyjściowy to PB3, bo to właśnie on pełni funkcję OC1A w ATtiny2313A. (ww1.microchip.com)

Dla maksymalnej częstotliwości wystarczy:

Timer1_Square_OC1A_Start(0, _BV(CS10));

Wtedy dostajesz:
\[
f{OUT}=\frac{F{CPU}}{2}
\]
czyli np. przy 8 MHz będzie to 4 MHz. (ww1.microchip.com)

Poprawny kod w ASM — rekomendowany wariant 50%

Poniżej odpowiednik asemblerowy dla OC1A / PB3. Zakładam F_CPU = 8 MHz i wyjście 1 kHz, czyli OCR1A = 3999 = 0x0F9F. Na ATtiny2313A stos jest reprezentowany przez SPL jako pojedynczy 8-bitowy rejestr. (ww1.microchip.com)

; Uwaga: nazwa pliku include zależy od toolchainu.
; W AVRASM zwykle spotyka się np. "tn2313Adef.inc"
.include "tn2313Adef.inc"
.cseg
.org 0x0000
    rjmp RESET
RESET:
    ; Inicjalizacja stosu
    ldi r16, low(RAMEND)
    out SPL, r16
    ; Wyłączenie / wyzerowanie Timer1 przed konfiguracją
    clr r16
    out TCCR1A, r16
    out TCCR1B, r16
    ; PB3 = OC1A jako wyjście
    sbi DDRB, DDB3
    ; OCR1A = 3999 = 0x0F9F  -> 1 kHz przy 8 MHz, N=1
    ldi r16, high(3999)
    out OCR1AH, r16
    ldi r16, low(3999)
    out OCR1AL, r16
    ; Toggle OC1A on Compare Match
    ldi r16, (1<<COM1A0)
    out TCCR1A, r16
    ; CTC mode 4 (WGM12=1), preskaler = 1 (CS10=1)
    ldi r16, (1<<WGM12) | (1<<CS10)
    out TCCR1B, r16
MAIN:
    rjmp MAIN

Ten kod działa sprzętowo, bez przerwań, bez delay, bez liczenia cykli w pętli. Dokładnie taki styl implementacji wynika z architektury timera i jest poprawniejszy od „programowego machania pinem”. (ww1.microchip.com)

Jeśli koniecznie chcesz użyć OC1B

Jeżeli z jakiegoś powodu chcesz wyjście na OC1B, to na ATtiny2313A będzie to PB4, nie PD4 ani PD5. Dodatkowo, jeśli chcesz aby kanał B był „wyjściem częstotliwości”, to nie możesz w trybie 4 traktować OCR1B jako rejestru wyznaczającego okres. W trybie 4 okres nadal ustala OCR1A. Z tego powodu najprościej jest użyć kanału A. Jeżeli koniecznie chcesz kanał B i osobny rejestr TOP, wtedy poprawną drogą jest CTC mode 12 z TOP = ICR1 albo przejście w tryb PWM. To jest wniosek z tabeli trybów pracy Timer1. (ww1.microchip.com)

Przykład C dla OC1B / PB4 z TOP = ICR1:

#include <avr/io.h>
#include <stdint.h>
void Timer1_Square_OC1B_Start(uint16_t top, uint16_t phase, uint8_t cs_bits)
{
    if (phase > top) phase = top;
    TCCR1A = 0;
    TCCR1B = 0;
    TCNT1  = 0;
    ICR1  = top;              // TOP w CTC mode 12
    OCR1B = phase;            // pozycja zbocza w ramach cyklu
    DDRB |= _BV(PB4);         // PB4 = OC1B
    TCCR1A = _BV(COM1B0);     // Toggle OC1B on Compare Match
    TCCR1B = _BV(WGM13) | _BV(WGM12) | (cs_bits & 0x07);
}

Tu ważna uwaga praktyczna: w tym wariancie częstotliwość wyznacza ICR1, a nie OCR1B. OCR1B określa moment przełączenia w obrębie zliczania, czyli fazę zbocza względem początku cyklu. (ww1.microchip.com)

A jeśli potrzebne jest inne wypełnienie niż 50%?

Wtedy cytowana rada też jest słuszna: trzeba użyć PWM, a nie trybu toggle. Dla Timer1 najpraktyczniejszy wariant to Fast PWM mode 14:

  • ICR1 ustala TOP, czyli częstotliwość,
  • OCR1A lub OCR1B ustala wypełnienie,
  • na wyjściu mamy stabilny PWM bez obciążania CPU. (ww1.microchip.com)

Przykład C dla PWM na OC1B / PB4:

#include <avr/io.h>
#include <stdint.h>
void Timer1_PWM_OC1B_Start(uint16_t top, uint16_t duty, uint8_t cs_bits)
{
    if (duty > top) duty = top;
    TCCR1A = 0;
    TCCR1B = 0;
    TCNT1  = 0;
    ICR1  = top;              // TOP = częstotliwość
    OCR1B = duty;             // duty = wypełnienie
    DDRB |= _BV(PB4);         // PB4 = OC1B
    // Fast PWM, mode 14: WGM13:0 = 1110
    // Non-inverting on OC1B
    TCCR1A = _BV(COM1B1) | _BV(WGM11);
    TCCR1B = _BV(WGM13) | _BV(WGM12) | (cs_bits & 0x07);
}

W tym wariancie:
\[
f{PWM}=\frac{f{clk_I/O}}{N\cdot(1+ICR1)}
\]
a dla trybu nieodwróconego wypełnienie jest w przybliżeniu proporcjonalne do OCR1B. To jest właściwa metoda, gdy potrzebujesz np. 10%, 25%, 73% itd. W trybie toggle uzyskujesz z definicji 50%. (ww1.microchip.com)

Aktualne informacje i trendy

W aktualnej dokumentacji Microchip dla ATtiny2313A/4313 nadal obowiązuje to samo mapowanie pinów i ta sama logika pracy Timer1: OC1A = PB3, OC1B = PB4, w CTC mode 4 TOP jest w OCR1A, a w CTC mode 12 TOP jest w ICR1. W tym sensie „aktualna wiedza” potwierdza, że właściwy kierunek to użycie peryferiów sprzętowych zamiast opóźnień programowych. (ww1.microchip.com)

W praktyce embedded to nadal jest najlepsza praktyka projektowa: jeśli mikrokontroler ma moduł compare/PWM, należy go wykorzystać. „Liczenie cykli w pętli” ma sens głównie w sytuacjach wyjątkowych, np. przy bit-bangingu wymuszonym przez brak zasobów sprzętowych. W przypadku ATtiny2313A taki przymus tutaj nie występuje. To jest wniosek inżynierski oparty na możliwościach Timer1 opisanych w dokumentacji. (ww1.microchip.com)

Wspierające wyjaśnienia i detale

Dlaczego wypełnienie jest dokładnie 50%

W trybie toggle on compare match pin OC1A lub OC1B zmienia stan przy każdym kolejnym zdarzeniu compare. Ponieważ te zdarzenia występują okresowo co dokładnie taką samą liczbę taktów timera, czas stanu wysokiego i niskiego jest identyczny. Stąd bierze się dokładne 50%, bez zależności od długości kodu głównego. (ww1.microchip.com)

Dlaczego nie należy używać delay

Pętla z delay:

  • obciąża CPU,
  • jest wrażliwa na optymalizację kompilatora,
  • staje się niestabilna, gdy dochodzą przerwania,
  • wymaga ręcznego bilansowania czasu stanu wysokiego i niskiego.

Timer sprzętowy eliminuje te problemy, bo pin przełącza peryferium, a nie program. To jest dokładnie ta przewaga, o której mówi cytowana wskazówka. Wniosek wynika z architektury modułu compare. (ww1.microchip.com)

Uwaga przy zmianie częstotliwości „w locie”

W CTC Timer1 nie ma podwójnego buforowania TOP tak jak pewne tryby PWM. Jeśli podczas pracy wpiszesz nowe OCR1A mniejsze od bieżącego TCNT1, może dojść do pominięcia najbliższego compare i timer dojdzie aż do 0xFFFF, zanim znowu zsynchronizuje się z nową wartością. Jeżeli chcesz dynamicznie zmieniać częstotliwość, najbezpieczniej:

  • zatrzymać timer,
  • wyzerować TCNT1,
  • wpisać nowy TOP,
  • uruchomić timer ponownie,

albo rozważyć tryb Fast PWM z OCR1A jako TOP, który ma buforowanie OCR1A. (ww1.microchip.com)

Aspekty etyczne i prawne

W tym problemie nie ma szczególnego aspektu etycznego, ale są aspekty techniczne i bezpieczeństwa:

  • szybkie przebiegi na wyjściu mikrokontrolera mogą generować zakłócenia EMC,
  • nie należy bezpośrednio obciążać pinu zbyt dużym prądem,
  • przy wysokich częstotliwościach trzeba uwzględnić pojemności pasożytnicze, długość przewodów i jakość źródła zegara.

To nie zmienia samej logiki programu, ale wpływa na wynik w praktycznym układzie.

Praktyczne wskazówki

  • Jeśli chcesz tylko 50% i prostokąt: użyj CTC + toggle OC1A. To jest wariant najprostszy i najbardziej elegancki. (ww1.microchip.com)
  • Jeśli chcesz regulować wypełnienie: użyj Fast PWM mode 14 z ICR1 jako TOP i OCR1B lub OCR1A jako duty. (ww1.microchip.com)
  • Jeśli chcesz bardzo niskie częstotliwości, najpierw wykorzystaj preskaler. Dopiero gdy zakres nadal jest za mały, ma sens dodatkowe dzielenie lub kaskada. Z samych wzorów wynika, że kaskada służy zwiększeniu podziału, czyli zejściu na niższe, a nie wyższe częstotliwości. (ww1.microchip.com)
  • W ATtiny2313A ciekawa cecha jest taka, że PD5 pełni funkcję OC0B/T1, a dokumentacja podaje, że Timer1 może być taktowany z pinu T1 nawet wtedy, gdy ten pin jest ustawiony jako wyjście. Inżyniersko oznacza to możliwość realizacji pewnych wariantów kaskady z użyciem Timer0 i Timer1 przez wspólny pin PD5. To jest jednak wariant bardziej zaawansowany i nie jest potrzebny do podstawowego generatora 50%. (ww1.microchip.com)

Ewentualne zastrzeżenia lub uwagi dodatkowe

Jedna z odpowiedzi przykładowych online była niepoprawna, bo traktowała PD4 jako OC1B i przypisywała OCR1B rolę rejestru ustalającego częstotliwość w CTC mode 4. To nie odpowiada dokumentacji ATtiny2313A. Druga odpowiedź online była również niepełna, bo konfigurowała CTC bez rzeczywistego włączenia poprawnego sprzętowego przełączania OC1A/OC1B. Dlatego nie należy tych przykładów kopiować bez korekty. (ww1.microchip.com)

Warto też doprecyzować terminologię: opisane tu rozwiązanie jest świetnym generatorem prostokąta opartym o timer. Jeśli ktoś mówi o „DDS”, to w ścisłym sensie zwykle ma na myśli akumulator fazy i syntezę numeryczną, a nie zwykły toggle na compare. W Twoim pytaniu jednak najważniejszy jest praktyczny efekt: stabilny, sprzętowo generowany sygnał.

Sugestie dalszych badań

Jeżeli chcesz temat pogłębić, sensowne kolejne kroki to:

  • porównać CTC + toggle z Fast PWM i Phase Correct PWM,
  • sprawdzić wpływ typu źródła zegara: RC vs kwarc,
  • przetestować dynamiczną zmianę OCR1A podczas pracy,
  • rozważyć wariant z wykorzystaniem Timer0 + Timer1 jako dzielnika wielostopniowego. (ww1.microchip.com)

Jeśli chcesz, mogę w następnym kroku dopisać jeszcze:

  1. wersję pod konkretną częstotliwość np. 1 kHz, 10 kHz, 100 kHz,
  2. wersję z przyciskami do zmiany częstotliwości,
  3. wersję w ASM dla PWM z regulowanym wypełnieniem,
  4. gotowy projekt pod AVR-GCC / Microchip Studio.

Krótkie podsumowanie

Najkrócej: idea użycia sprzętowego timera jest poprawna, ale przytoczony kod trzeba poprawić pod ATtiny2313A. Dla prostokąta 50% najlepszy jest Timer1 w CTC + toggle OC1A na PB3 + OCR1A jako TOP. Jeśli potrzebujesz regulowanego wypełnienia, przechodzisz na PWM. Błędy, które trzeba bezwzględnie usunąć, to błędne przypisanie pinu OC1B oraz błędne traktowanie OCR1B jako rejestru ustalającego częstotliwość w CTC mode 4. (ww1.microchip.com)

Jeżeli chcesz, przygotuję teraz drugą wersję odpowiedzi: tylko gotowy kod C i ASM bez objaśnień, od razu do wklejenia do projektu.

Oceń odpowiedź:
Zastrzeżenie: Odpowiedzi udzielone przez sztuczną inteligencję (model językowy) mogą być niedokładne i wprowadzające w błąd. Elektroda nie ponosi odpowiedzialności za dokładność, rzetelność ani kompletność prezentowanych informacji. Wszystkie odpowiedzi powinny być zweryfikowane przez użytkownika.

Pytanie

Chcę aby zmiana polaryzacji była co 64 sekund ,50% duty , z kwarcem zegarkowym 32.768 KHz , chba on jest najbardziej odpowiedni , chba że znasz lepszy .

Odpowiedź Sztucznej Inteligencji


Bezpośrednia odpowiedź na pytanie

Tak — kwarc zegarkowy 32,768 kHz jest bardzo dobrym, a w praktyce najwygodniejszym wyborem do uzyskania zmiany stanu co 64 s przy 50% duty.

Kluczowe punkty:

  • 32,768 kHz = (2^{15}), więc bardzo łatwo dzieli się binarnie.
  • Jeśli stan ma się przełączać co 64 s, to:
    • półokres = 64 s,
    • pełny okres = 128 s,
    • sygnał wyjściowy ma częstotliwość (1/128\ \text{Hz}).
  • To oznacza idealne dopasowanie do dzielników binarnych:
    [
    32768 \cdot 64 = 2^{15} \cdot 2^6 = 2^{21}
    ]
  • Czyli po prostu potrzebujesz układu, który wykona dokładnie taki podział.
  • Lepsze rozwiązanie ma sens tylko wtedy, gdy potrzebujesz wyższej dokładności temperaturowej niż daje zwykły kwarc zegarkowy. Wtedy warto rozważyć RTC/TCXO, np. klasę DS3231.

Jeżeli używasz ATtiny2313A, to najlepsza praktyczna metoda to:

  • taktować cały mikrokontroler z 32,768 kHz przez XTAL1/XTAL2,
  • użyć Timer1 w trybie CTC,
  • przełączać wyjście sprzętowo na OC1A.

Szczegółowa analiza problemu

Masz wymaganie:

  • zmiana polaryzacji co 64 sekundy,
  • 50% duty.

To trzeba rozumieć tak:

  • przez 64 s stan A,
  • przez następne 64 s stan B,
  • potem znowu A itd.

Zatem pełny okres wynosi:

[
T = 64\ \text{s} + 64\ \text{s} = 128\ \text{s}
]

A częstotliwość sygnału wyjściowego:

[
f_{out} = \frac{1}{128}\ \text{Hz}
]

Dlaczego 32,768 kHz pasuje idealnie

Częstotliwość zegarkowa:

[
32768\ \text{Hz} = 2^{15}
]

To jest standard właśnie dlatego, że daje bardzo wygodne dzielenie przez 2.

Jeżeli chcesz przełączenie stanu co 64 s, to liczba impulsów wejściowych między przełączeniami wynosi:

[
32768 \cdot 64 = 2097152 = 2^{21}
]

Czyli:

  • do samego przełączenia co 64 s potrzebujesz „odliczyć” (2^{21}) taktów,
  • do uzyskania gotowego prostokąta 128 s potrzebujesz efektywnie podziału do (1/128\ \text{Hz}), czyli o (2^{22}) względem wejścia.

To jest sytuacja niemal idealna dla:

  • liczników binarnych,
  • timerów mikrokontrolerów,
  • RTC i układów zegarkowych.

Najlepsze warianty realizacji

1. Wariant z mikrokontrolerem AVR — najlepszy, jeśli i tak masz MCU

Jeżeli to ma być na ATtiny2313A, to najbardziej eleganckie rozwiązanie jest takie:

  • kwarc 32,768 kHz podłączasz jako główne taktowanie MCU,
  • Timer1 ustawiasz w CTC,
  • na wyjściu OC1A ustawiasz tryb toggle on compare match,
  • wtedy sprzęt sam przełącza pin co 64 s,
  • bez przerwań i bez jitteru programowego.

To daje:

  • bardzo dokładne 50% duty,
  • minimalne obciążenie CPU,
  • prostą konstrukcję.

Obliczenia dla Timer1

Masz dwie wygodne konfiguracje, obie są dokładne.

Wersja A — preskaler 1024

[
f_{T1} = \frac{32768}{1024} = 32\ \text{Hz}
]

Aby uzyskać przełączenie co 64 s:

[
64 \cdot 32 = 2048
]

W trybie CTC licznik zlicza od 0 do OCR1A, więc:

[
OCR1A = 2048 - 1 = 2047
]

To jest bardzo wygodne ustawienie.

Wersja B — preskaler 64

[
f_{T1} = \frac{32768}{64} = 512\ \text{Hz}
]

[
64 \cdot 512 = 32768
]

[
OCR1A = 32767
]

Też idealnie poprawne.

Co jest lepsze?

Praktycznie polecam:

  • preskaler 1024
  • OCR1A = 2047

bo jest czytelniej i prościej.

Minimalny przykład dla ATtiny2313A

Jeżeli rzeczywiście pracujesz na ATtiny2313A, to logika konfiguracji wygląda tak:

#define F_CPU 32768UL
#include <avr/io.h>
static void init_64s_toggle(void)
{
    // OC1A jako wyjście
    DDRB |= (1 << PB3);
    // Timer1: toggle OC1A on compare match
    TCCR1A = (1 << COM1A0);
    // CTC, preskaler 1024
    TCCR1B = (1 << WGM12) | (1 << CS12) | (1 << CS10);
    // 64 s na jedno przełączenie
    OCR1A = 2047;
}
int main(void)
{
    init_64s_toggle();
    while (1)
    {
        // nic nie trzeba robić
    }
}

Uwaga praktyczna

To zadziała poprawnie tylko wtedy, gdy mikrokontroler jest faktycznie taktowany z zewnętrznego kwarcu 32,768 kHz, a fuse bity są ustawione na:

  • Low-frequency crystal oscillator,
  • CKDIV8 wyłączony.

Ważna korekta względem jednej z przykładowych odpowiedzi

Pojawiła się sugestia użycia asynchronicznego Timer2 z kwarcem zegarkowym. Dla ATtiny2313A to nie jest właściwy kierunek. W praktyce dla tego układu poprawne podejście to:

  • użyć 32,768 kHz jako zegara systemowego,
  • a nie jako osobnego oscylatora dla „Timer2”.

Czyli w tym konkretnym przypadku lepiej myśleć o:

  • XTAL1/XTAL2 + Timer1,
  • nie o „zegarkowym Timer2”, jak w niektórych innych AVR.

2. Wariant bez mikrokontrolera — czysta logika CMOS

Jeżeli nie chcesz używać mikrokontrolera, to także da się to zrobić bardzo dobrze.

Wtedy potrzebujesz:

  • oscylatora 32,768 kHz,
  • licznika/dzielnika binarnego.

Najważniejsze:

  • CD4060 sam nie wystarczy do uzyskania gotowego sygnału 128 s z 32,768 kHz, bo ma za mało stopni podziału.
  • Trzeba dodać kolejny dzielnik albo przerzutnik.
  • Wygodniejsze są układy typu CD4521 lub zestaw:
    • oscylator + licznik 24-bitowy / dodatkowy licznik binarny.

Jeśli chcesz rozwiązanie:

  • najprostsze sprzętowo,
  • bez programowania,
  • bardzo energooszczędne,

to układ CMOS + kwarc zegarkowy jest dobry, ale:

  • wymaga starannego doboru elementów oscylatora,
  • watch crystal jest dość delikatny pod względem warunków pracy.

3. Jeśli „zmiana polaryzacji” dotyczy realnego obciążenia

To jest bardzo ważne rozróżnienie.

Jeżeli potrzebujesz tylko sygnału logicznego:

  • sprawa jest prosta.

Jeżeli potrzebujesz rzeczywistego odwracania polaryzacji na obciążeniu, to sam pin mikrokontrolera nie wystarczy. Wtedy potrzebujesz jeszcze:

  • mostka H,
  • albo przekaźnika,
  • albo przełącznika analogowego/tranzystorowego.

Dobór zależy od:

  • napięcia obciążenia,
  • prądu,
  • rodzaju obciążenia.

Przykładowo:

  • mały prąd i niskie napięcie: mostek tranzystorowy,
  • większe napięcie/prąd, przełączanie rzadkie: przekaźnik może być bardzo dobrym wyborem,
  • jeśli to obciążenie indukcyjne: potrzebne zabezpieczenia,
  • jeśli to elektrody/układ elektrochemiczny: trzeba uważać na przebiegi przejściowe i średnią składową DC.

Aktualne informacje i trendy

W praktyce inżynierskiej nadal stosuje się trzy główne klasy rozwiązań:

Rozwiązanie Zaleta Wada Kiedy wybrać
Kwarc 32,768 kHz + licznik/timer bardzo prosty, tani, energooszczędny typowa dokładność zależna od temperatury większość zastosowań
RTC z kompensacją temperatury bardzo wysoka dokładność większa cena i złożoność gdy czas ma być stabilny w szerokim zakresie temperatur
Wewnętrzny RC MCU najmniej elementów dużo gorsza dokładność tylko gdy precyzja nie ma znaczenia

Obecnie standardowe podejście jest takie:

  • do zwykłego odmierzania czasu: 32,768 kHz
  • do lepszej dokładności: RTC/TCXO
  • do bardzo dużej dokładności: synchronizacja z zewnętrznym wzorcem czasu

Dla Twojego wymagania 64 s / 50% duty:

  • zwykły watch crystal 32,768 kHz jest nadal najbardziej sensowny.

Wspierające wyjaśnienia i detale

Jak dobrać dokładność

Typowy kwarc zegarkowy ma np. około ±20 ppm.

To oznacza błąd rzędu:

[
64\ \text{s} \cdot 20 \cdot 10^{-6} = 1{,}28\ \text{ms}
]

na pojedynczym odcinku 64 s, pomijając wpływ temperatury i starzenia.

W skali doby daje to około:

[
86400\ \text{s} \cdot 20 \cdot 10^{-6} \approx 1{,}7\ \text{s/dobę}
]

Czyli:

  • dla większości zastosowań to bardzo dobrze,
  • ale jeśli oczekujesz stabilności „zegarowej” przez długi czas i szeroki zakres temperatur, to lepszy będzie RTC z kompensacją.

Kwarc zegarkowy a układ oscylatora

Przy 32,768 kHz trzeba pamiętać, że taki rezonator:

  • ma małą moc dopuszczalną,
  • nie lubi przeciążenia,
  • jest wrażliwy na pojemności pasożytnicze.

Dlatego należy:

  • dobrać pojemności zgodnie z CL z datasheet kwarcu,
  • nie dawać „na oko” zbyt dużych kondensatorów,
  • prowadzić krótkie ścieżki,
  • trzymać oscylator z dala od zakłóceń.

Czy istnieje „lepszy” rezonator?

Tak, ale tylko w określonym sensie:

  • lepszy kosztowo / energetycznie / prostotą: nie, 32,768 kHz jest bardzo dobry,
  • lepszy dokładnością temperaturową: tak, RTC z kompensacją temperatury,
  • lepszy prostotą uruchomienia: czasem gotowy moduł zegarowy/RTC jest wygodniejszy niż „goły” kwarc.

Aspekty etyczne i prawne

W tym przypadku aspekt etyczny jest marginalny, ale technicznie trzeba uwzględnić:

  • bezpieczeństwo elektryczne, jeśli odwracasz polaryzację na realnym obciążeniu,
  • zgodność napięć i prądów z parametrami elementów,
  • ochronę styków przekaźnika lub tranzystorów,
  • kompatybilność elektromagnetyczną, jeśli sterujesz przewodami dłuższymi lub obciążeniem indukcyjnym.

Jeżeli układ pracuje w urządzeniu użytkowym:

  • należy zachować odstępy izolacyjne,
  • stosować zabezpieczenia przeciwprzepięciowe,
  • nie obciążać bezpośrednio pinu MCU ponad dopuszczalne limity.

Praktyczne wskazówki

Co polecam wprost

Jeśli używasz ATtiny2313A:

  1. Zastosuj kwarc 32,768 kHz.
  2. Ustaw MCU na external low-frequency crystal.
  3. Wyłącz CKDIV8.
  4. Użyj Timer1, CTC, toggle na OC1A.
  5. Ustaw:
    • preskaler 1024
    • OCR1A = 2047

To jest rozwiązanie:

  • dokładne,
  • proste,
  • bezobsługowe,
  • z idealnym 50% duty.

Jeśli nie chcesz MCU:

  1. Użyj oscylatora 32,768 kHz.
  2. Dodaj licznik binarny o wystarczającej liczbie stopni.
  3. Weź wyjście odpowiadające podziałowi do sygnału 128 s.
  4. Jeśli trzeba odwracać polaryzację obciążenia, dodaj stopień wykonawczy.

Czego nie polecam

  • wewnętrznego RC, jeśli zależy Ci na czasie,
  • „na siłę” budowania układu na niewłaściwym dzielniku, np. zbyt małej liczbie stopni,
  • generowania tego wyłącznie programowo w pętli opóźniającej.

Ewentualne zastrzeżenia lub uwagi dodatkowe

  • Jeśli pytając o „zmianę polaryzacji” masz na myśli dwa przewody obciążenia, to sam sygnał z timera nie załatwia sprawy — potrzebny jest jeszcze układ przełączający.
  • Jeśli to ma być na konkretnym AVR, trzeba potwierdzić dokładny model i obudowę, bo rozmieszczenie pinów może się różnić.
  • Jeżeli układ ma działać w zmiennej temperaturze i wymagasz wysokiej zgodności czasu przez miesiące, zwykły kwarc może być niewystarczający.
  • Jeśli potrzebujesz bardzo małego poboru mocy, warto rozważyć tryby uśpienia MCU.

Sugestie dalszych badań

Jeżeli chcesz dopracować układ, warto przeanalizować dalej:

  • dobór CL kwarcu i rzeczywistych kondensatorów,
  • fuse bity konkretnego AVR,
  • sposób realizacji odwracania polaryzacji:
    • przekaźnik,
    • mostek H,
    • przełącznik CMOS,
  • wpływ temperatury na dokładność,
  • ewentualną kalibrację czasu,
  • porównanie zwykłego kwarcu 32,768 kHz z RTC kompensowanym temperaturowo.

Jeśli chcesz, mogę w następnym kroku przygotować jedną z trzech rzeczy:

  1. gotowy schemat na ATtiny2313A,
  2. wersję bez mikrokontrolera na CMOS,
  3. układ odwracania polaryzacji obciążenia do tego generatora.

Krótkie podsumowanie

Tak, 32,768 kHz to właściwy wybór. Do przełączania co 64 s z 50% duty pasuje niemal idealnie, bo daje dokładne dzielenie binarne bez błędu.

Najlepsza praktyczna odpowiedź:

  • dla ATtiny2313A: kwarc 32,768 kHz + Timer1 CTC + sprzętowe toggle OC1A,
  • jeśli potrzebujesz tylko logiki bez MCU: oscylator 32,768 kHz + licznik binarny o odpowiedniej liczbie stopni,
  • jeśli potrzebujesz wyższej dokładności niż typowy kwarc: rozważ RTC/TCXO.

Jeżeli chcesz, mogę od razu narysować Ci konkretny schemat połączeń i podać ustawienia fuse bitów dla ATtiny2313A.

Zastrzeżenie: Odpowiedzi udzielone przez sztuczną inteligencję (model językowy) mogą być niedokładne i wprowadzające w błąd. Elektroda nie ponosi odpowiedzialności za dokładność, rzetelność ani kompletność prezentowanych informacji. Wszystkie odpowiedzi powinny być zweryfikowane przez użytkownika.

Pytanie

gotowy schemat na ATtiny2313A,

Odpowiedź Sztucznej Inteligencji


Bezpośrednia odpowiedź na pytanie

Tak — poniżej masz gotowy, praktyczny schemat bazowy na ATtiny2313A.
Zakładam, że chodzi o układ z kwarcem 32,768 kHz oraz wyjściem PB3/OC1A, które ma zmieniać stan co 64 s. Jeśli Twoim celem jest tylko „goły” mikrokontroler do dalszego projektu, to ten sam schemat stanowi poprawną bazę sprzętową.

Kluczowe punkty

  • ATtiny2313A zasilany z 5 V lub 3,3 V.
  • Kwarc 32,768 kHz do pinów XTAL1/XTAL2.
  • PB3/OC1A jako wyjście sygnału.
  • Jeśli trzeba rzeczywiście odwracać polaryzację obciążenia, sam pin mikrokontrolera nie wystarczy — potrzebny jest przekaźnik DPDT albo mostek H.
  • W przykładowych odpowiedziach była rozbieżność fuse bitów. Dla oscylatora Low-Frequency Crystal 32,768 kHz poprawne ustawienie lfuse to 0xE6, nie 0xE4.

Bezpośrednia odpowiedź na pytanie Szczegółowa analiza problemu

Poniżej podaję dwie wersje:

  1. Minimalny gotowy schemat ATtiny2313A
  2. Wersję rozszerzoną z przekaźnikiem DPDT, jeśli chcesz zmieniać polaryzację obciążenia co 64 s

1. Minimalny gotowy schemat bazowy na ATtiny2313A

                 +5V
                  │
                 [10k]
                  │
RESET ────────────┴─────────────── złącze ISP: RESET
                  │
VCC  ───────────────────────────── +5V
GND  ───────────────────────────── GND
Między VCC i GND:
C3 = 100 nF ceramiczny, jak najbliżej mikrokontrolera
XTAL1 ─────┬────[ Kwarc 32.768 kHz ]────┬──── XTAL2
           │                            │
         C1 18..22 pF                 C2 18..22 pF
           │                            │
          GND                          GND
PB5/MOSI ───────────────────────────── złącze ISP MOSI
PB6/MISO ───────────────────────────── złącze ISP MISO
PB7/SCK  ───────────────────────────── złącze ISP SCK
VCC      ───────────────────────────── złącze ISP VCC
GND      ───────────────────────────── złącze ISP GND
PB3/OC1A ───────────────────────────── wyjście sygnału 64 s / 64 s

Zalecane elementy

Element Wartość Uwagi
C3 100 nF obowiązkowy kondensator odsprzęgający
R1 10 kΩ podciąganie RESET do VCC
X1 32,768 kHz kwarc zegarkowy
C1, C2 18–22 pF dobra wartość startowa; zależy od CL kwarcu
Złącze ISP 6 pin do programowania AVR

2. Gotowy schemat, jeśli wyjście ma sterować zmianą polaryzacji

Jeżeli na wyjściu ma być realne odwracanie „+ / –” na obciążeniu, dodaj stopień wykonawczy:

PB3/OC1A ──[1k]──B   NPN (np. BC337)
                    C─────────────┬──── cewka przekaźnika ─── +5V
                    E─────────────┘
                    │
                   GND
Dioda równolegle do cewki:
anoda  -> kolektor tranzystora
katoda -> +5V

Styki przekaźnika DPDT do odwracania polaryzacji

              PRZEKAŹNIK DPDT
          NC1 o──── GND_obc
         COM1 o──── LOAD_A
          NO1 o──── +V_obc
          NC2 o──── +V_obc
         COM2 o──── LOAD_B
          NO2 o──── GND_obc

Działanie

  • przekaźnik wyłączony:
    LOAD_A = GND, LOAD_B = +V
  • przekaźnik włączony:
    LOAD_A = +V, LOAD_B = GND

To daje pełne odwrócenie polaryzacji.

Dlaczego to jest poprawne rozwiązanie

Sam pin PB3:

  • może podać tylko poziom logiczny,
  • nie może bezpośrednio zasilać cewki, silnika, elektrod, zaworu itd.,
  • nie zapewnia odwrócenia polaryzacji bez dodatkowego układu.

Aktualne informacje i trendy

Na podstawie dostarczonych odpowiedzi online najpewniejsze źródło odniesienia dla ATtiny2313A to:

  • nota katalogowa Microchip/Atmel,
  • gotowe symbole EDA,
  • standardowy interfejs AVR ISP.

W praktyce projektowej obecnie najczęściej stosuje się:

  • schemat bazowy z ISP + reset + odsprzęganie + kwarc,
  • zamiast przekaźnika coraz częściej mostek H:
    • dla obciążeń DC,
    • gdy wymagana jest większa trwałość,
    • gdy przełączeń jest dużo.

Trend praktyczny

  • przekaźnik DPDT — najprostszy i bardzo czytelny,
  • mostek H — lepszy do pracy ciągłej i bezgłośnej,
  • sprzętowe wykorzystanie timera — lepsze niż opóźnienia programowe, bo daje stabilniejszy czas i odciąża CPU.

Wspierające wyjaśnienia i detale

Dlaczego kwarc 32,768 kHz

To częstotliwość:
[
32768 = 2^{15}
]

Dzięki temu bardzo wygodnie dzieli się ją przez preskalery i timery.

Przy preskalerze 1024:
[
\frac{32768}{1024} = 32 \text{ Hz}
]

Aby uzyskać przełączenie co 64 s:
[
32 \cdot 64 = 2048
]

Zatem:
[
OCR1A = 2048 - 1 = 2047
]

Konfiguracja Timer1

Dla PB3/OC1A:

  • tryb CTC,
  • sprzętowe toggle OC1A przy compare match,
  • preskaler 1024,
  • OCR1A = 2047.

To daje:

  • stan wysoki przez 64 s,
  • stan niski przez 64 s,
  • pełny okres 128 s,
  • wypełnienie 50%.

Uwaga o kondensatorach przy kwarcu

W jednej z przykładowych odpowiedzi padło 33 pF, ale dla typowego kwarcu zegarkowego to bywa zbyt dużo.
Praktycznie zalecam:

  • zacząć od 18 pF lub 22 pF,
  • sprawdzić w nocie kwarcu parametr CL.

Przybliżenie:
[
CL \approx \frac{C1 \cdot C2}{C1 + C2} + C{stray}
]

Dla 22 pF i typowych pojemności pasożytniczych układ zwykle pracuje poprawnie.

Uwaga o numerach pinów

Najbezpieczniej projektować po nazwach sygnałów:

  • VCC
  • GND
  • RESET
  • XTAL1
  • XTAL2
  • PB3/OC1A
  • PB5/MOSI
  • PB6/MISO
  • PB7/SCK

Numeracja zależy od obudowy i biblioteki EDA, więc przed wykonaniem PCB trzeba ją zweryfikować z notą katalogową dla konkretnej wersji: PU / SU / MU / MMH.


Aspekty etyczne i prawne

W elektronice użytkowej i przemysłowej trzeba uwzględnić:

Bezpieczeństwo elektryczne

  • nie wolno podłączać obciążeń o większym napięciu bez odpowiedniej separacji,
  • dla cewek obowiązkowo stosować diodę gaszącą,
  • dla obciążeń indukcyjnych i przekaźników należy uwzględnić zakłócenia EMC.

Aspekty prawne i zgodności

Jeżeli układ ma być częścią urządzenia komercyjnego:

  • trzeba uwzględnić zgodność EMC,
  • bezpieczeństwo zasilania,
  • odpowiedni dobór przekrojów, odstępów izolacyjnych i zabezpieczeń.

Trwałość

Przy przełączaniu co 64 s:

  • około 1350 przełączeń na dobę,
  • około 0,5 mln przełączeń rocznie.

To oznacza, że dla przekaźnika mechanicznego trwałość staje się realnym parametrem projektowym.


Praktyczne wskazówki

Fuse bity

Tu trzeba wprost skorygować rozbieżność z przykładowych odpowiedzi.

Dla pracy z kwarcem 32,768 kHz Low-Frequency Crystal:

  • lfuse = 0xE6
  • hfuse = 0xDF
  • efuse = 0xFF

Rozumowanie:

  • CKDIV8 = 1, czyli wyłączony,
  • CKOUT = 1,
  • SUT = 10,
  • CKSEL = 0110.

To daje:
[
1110\,0110_2 = 0xE6
]

Minimalny kod w C

#define F_CPU 32768UL
#include <avr/io.h>
int main(void)
{
    DDRB |= (1 << PB3);     // PB3/OC1A jako wyjście
    TCCR1A = 0;
    TCCR1B = 0;
    TCNT1  = 0;
    OCR1A = 2047;           // 64 s przy 32.768 kHz i /1024
    TCCR1A = (1 << COM1A0); // toggle OC1A on compare match
    TCCR1B = (1 << WGM12)   // CTC
           | (1 << CS12)
           | (1 << CS10);   // preskaler 1024
    while (1)
    {
        // opcjonalnie sleep
    }
}

Jak sprawdzić działanie

  1. Zanim podłączysz przekaźnik, podłącz do PB3:
    • LED + rezystor 1 kΩ do VCC albo do GND.
  2. Zmierz stan na PB3 oscyloskopem lub miernikiem logicznym.
  3. Zweryfikuj:
    • zmiana stanu co około 64 s,
    • pełny cykl około 128 s.

Najlepsze praktyki PCB

  • kondensator 100 nF maksymalnie blisko VCC/GND mikrokontrolera,
  • krótkie ścieżki do kwarcu,
  • nie prowadzić pod kwarcem agresywnych sygnałów przełączających,
  • oddzielić masę części logicznej od prądów cewki przekaźnika.

Ewentualne zastrzeżenia lub uwagi dodatkowe

Ograniczenia

  • Sam ATtiny2313A nie przełączy bezpośrednio większego obciążenia.
  • Przekaźnik mechaniczny ma ograniczoną żywotność.
  • Dokładność czasu zależy od:
    • dokładności kwarcu,
    • temperatury,
    • poprawnego doboru kondensatorów.

Obszary niepewności

Twoje pytanie jest bardzo krótkie:
„gotowy schemat na ATtiny2313A”.

To może oznaczać kilka rzeczy:

  • sam schemat minimalny mikrokontrolera,
  • schemat do odwracania polaryzacji,
  • schemat z programatorem ISP,
  • schemat z konkretną aplikacją.

Dlatego podałem wariant najbardziej użyteczny: pełny schemat bazowy + wersję wykonawczą.

Alternatywna perspektywa

Jeśli układ ma pracować latami i bezgłośnie, lepiej zamiast przekaźnika dać:

  • mostek H na MOSFET-ach,
  • albo gotowy sterownik mostka.

Sugestie dalszych badań

Jeżeli chcesz rozwinąć projekt, sensowne następne kroki to:

Wersje do dopracowania

  • schemat w KiCad / Eagle / EasyEDA,
  • gotowa płytka PCB,
  • wersja z mostkiem H zamiast przekaźnika,
  • wersja niskoprądowa z trybem uśpienia,
  • wersja z zasilaniem bateryjnym.

Co warto jeszcze sprawdzić

  • dobór kondensatorów do konkretnego kwarcu,
  • pobór prądu w sleep mode,
  • odporność na zakłócenia od przekaźnika,
  • procedurę awaryjnego odzyskania mikrokontrolera po błędnym ustawieniu fuse bitów.

Krótkie podsumowanie

Najprostszy gotowy schemat na ATtiny2313A powinien zawierać:

  • VCC + GND + 100 nF,
  • RESET z rezystorem 10 kΩ do VCC,
  • kwarc 32,768 kHz + 2 kondensatory 18–22 pF,
  • złącze ISP,
  • PB3/OC1A jako wyjście.

Jeśli chcesz naprawdę odwracać polaryzację obciążenia, dołóż:

  • tranzystor NPN,
  • diodę przy cewce,
  • przekaźnik DPDT lub mostek H.

Najważniejsza korekta techniczna: dla tej konfiguracji poprawny low fuse to 0xE6.

Jeżeli chcesz, mogę Ci w następnym kroku przygotować:

  1. pełny schemat w formie rysunku ASCII z nazwami pinów,
  2. wersję do KiCad,
  3. albo schemat dokładnie pod obudowę DIP-20 ATtiny2313A-PU.

Zastrzeżenie: Odpowiedzi udzielone przez sztuczną inteligencję (model językowy) mogą być niedokładne i wprowadzające w błąd. Elektroda nie ponosi odpowiedzialności za dokładność, rzetelność ani kompletność prezentowanych informacji. Wszystkie odpowiedzi powinny być zweryfikowane przez użytkownika.