Odpowiedź Sztucznej Inteligencji
Bezpośrednia odpowiedź na pytanie
- Najdokładniejszy sposób: użyj zewnętrznego rezonatora kwarcowego 32,768 kHz jako źródła zegara systemowego ATtiny2313 i Timer1 w trybie CTC. Wtedy półokres 64 s uzyskasz jednym przerwaniem od porównania (OCR1A=2047, preskaler 1024), a na PB3 i PB4 otrzymasz naprzemiennie 64 s LOW i 64 s HIGH.
- Alternatywnie (prościej, lecz mniej dokładnie): przy wewnętrznym RC 1 MHz (CKDIV8=ON) zostaw preskaler 1024 i ustaw OCR1A=62499 (62500 zliczeń). Półokres dalej wyniesie dokładnie 64 s względem lokalnego zegara, ale dokładność absolutna będzie gorsza.
Kluczowe punkty:
- Timer1 (16‑bit) w trybie CTC, przerwanie OC1A do przełączania PB3/PB4.
- Dla 32,768 kHz: Ftimer=32 Hz, 64 s → 2048 taktów → OCR1A=2047.
- Dla 1 MHz: Ftimer≈976,5625 Hz, 64 s → 62500 taktów → OCR1A=62499.
- Stan początkowy PB3=0, PB4=0; w ISR przełączanie obu bitów.
Szczegółowa analiza problemu
- Wymagany okres: 128 s (50% wypełnienia), tzn. 64 s niski, 64 s wysoki.
- ATtiny2313 ma 16‑bitowy Timer1 z trybem CTC (Clear Timer on Compare Match), idealny do odmierzania długich interwałów bez „liczenia w programie”.
- Dokładność czasu determinuje dokładność źródła zegara:
- Zewnętrzny kwarc 32,768 kHz (typowy zegarkowy) zapewnia stabilność rzędu 10–20 ppm → błąd ok. 1,3–2,6 ms na cały okres 128 s.
- Wewnętrzny RC (1 MHz z domyślnym CKDIV8, ewentualnie 8 MHz bez podziału) ma błąd typowo do kilku procent (nawet po kalibracji OSCCAL zwykle >±1%), co daje błąd rzędu sekund na 128 s.
- Dobór parametrów:
- Tryb CTC, TOP=OCR1A, preskaler 1024.
- Dla FCPU=32,768 kHz: Ftimer=32 Hz, więc 64 s × 32 = 2048 zliczeń, OCR1A=2047 (licznik zlicza 0…2047).
- Dla FCPU=1 MHz: Ftimer≈976,5625 Hz, więc 64 s × 976,5625 = 62500 zliczeń, OCR1A=62499.
Kod w asemblerze – wariant A (najdokładniejszy, kwarc 32,768 kHz)
Uwaga: wymaga ustawienia fuse na „Low‑frequency Crystal Oscillator 32.768 kHz”, wyłączenia CKDIV8 i dobrania SUT dla stabilnego startu.
; ATtiny2313 — 128 s okres (64 s LOW / 64 s HIGH) na PB3 i PB4
; Wariant A: F_CPU = 32 768 Hz (zewnętrzny kwarc), Timer1 CTC, preskaler 1024, OCR1A=2047
.nolist
.include "tn2313def.inc"
.list
.def tmp = r16
.cseg
.org 0x0000
rjmp RESET
; Wektor przerwania OC1A (etykieta zgodna z plikiem nagłówkowym)
.org OC1Aaddr
rjmp TIMER1_COMPA_ISR
RESET:
; Stos
ldi tmp, low(RAMEND)
out SPL, tmp
; PB3, PB4 jako wyjścia; start od stanu niskiego
ldi tmp, (1<<PB3) | (1<<PB4)
out DDRB, tmp
ldi tmp, 0x00
out PORTB, tmp
; Timer1: CTC, preskaler 1024, TOP=OCR1A=2047
ldi tmp, high(2047)
out OCR1AH, tmp
ldi tmp, low(2047)
out OCR1AL, tmp
ldi tmp, 0x00
out TCCR1A, tmp
; WGM12=1 (CTC), CS12=1, CS11=0, CS10=1 => preskaler 1024
ldi tmp, (1<<WGM12) | (1<<CS12) | (1<<CS10)
out TCCR1B, tmp
; Włącz przerwanie OCIE1A
ldi tmp, (1<<OCIE1A)
out TIMSK, tmp
sei
MAIN:
rjmp MAIN
; ISR co 64 sekundy — przełącz PB3 i PB4
TIMER1_COMPA_ISR:
push tmp
in tmp, SREG
push tmp
in tmp, PORTB
ldi r17, (1<<PB3) | (1<<PB4)
eor tmp, r17
out PORTB, tmp
pop tmp
out SREG, tmp
pop tmp
reti
Kod w asemblerze – wariant B (prostszy, wewnętrzny RC 1 MHz)
Uwaga: to rozwiązanie da „dokładne” 64 s względem tego RC, ale absolutna dokładność czasu będzie słaba (dryf).
; ATtiny2313 — 128 s okres (64 s LOW / 64 s HIGH) na PB3 i PB4
; Wariant B: F_CPU ≈ 1 000 000 Hz (wewnętrzny RC + CKDIV8), Timer1 CTC, preskaler 1024, OCR1A=62499
.nolist
.include "tn2313def.inc"
.list
.def tmp = r16
.cseg
.org 0x0000
rjmp RESET
.org OC1Aaddr
rjmp TIMER1_COMPA_ISR
RESET:
ldi tmp, low(RAMEND)
out SPL, tmp
ldi tmp, (1<<PB3) | (1<<PB4)
out DDRB, tmp
ldi tmp, 0x00
out PORTB, tmp
; OCR1A = 62499 -> 62500 zliczeń przy ~976.5625 Hz = 64.000 s
ldi tmp, high(62499)
out OCR1AH, tmp
ldi tmp, low(62499)
out OCR1AL, tmp
ldi tmp, 0x00
out TCCR1A, tmp
ldi tmp, (1<<WGM12) | (1<<CS12) | (1<<CS10) ; CTC, preskaler 1024
out TCCR1B, tmp
ldi tmp, (1<<OCIE1A)
out TIMSK, tmp
sei
MAIN:
rjmp MAIN
TIMER1_COMPA_ISR:
push tmp
in tmp, SREG
push tmp
in tmp, PORTB
ldi r17, (1<<PB3) | (1<<PB4)
eor tmp, r17
out PORTB, tmp
pop tmp
out SREG, tmp
pop tmp
reti
Aktualne informacje i trendy
- Dla „długiego, dokładnego czasu” w prostych AVR-8 nadal króluje zegarkowy kwarc 32,768 kHz (najkorzystniejszy kompromis dokładność/zużycie energii/koszt).
- W nowszych rodzinach AVR (np. ATtiny1/DA/DB) dostępne są peryferia TCB/RTC z dedykowanym zegarem 32 kHz – gdybyś w przyszłości modernizował projekt, te układy uproszczą konfigurację i pozwolą zachować bardzo niskie zużycie energii.
Wspierające wyjaśnienia i detale
- Dlaczego 32,768 kHz? To 2^15 Hz, więc po preskalerze 1024 masz 2^5=32 Hz. 64 s × 32 = 2048 = 2^11 – idealnie mieści się w 16-bitowym liczniku i daje „okrągłe” wartości rejestrów.
- Przełączanie wyjść w ISR z użyciem EOR z maską jest bezpieczne i nie narusza stanów innych bitów PORTB.
- Alternatywnie można użyć sztuczki „toggle przez zapis 1 do PINB”, ale EOR na PORTB jest bardziej czytelny i jednoznaczny.
Aspekty etyczne i prawne
- Zmiana fuse (źródło zegara) może uniemożliwić dalsze programowanie niskonapięciowe (ISP), jeśli ustawisz nieprawidłowe parametry – upewnij się co do ustawień przed zapisem. W razie pomyłki potrzebny będzie programator HV.
- Zapewnij zgodność EMC i bezpieczeństwo elektryczne w urządzeniach końcowych (odsprzęganie zasilania, poprawne prowadzenie masy, separacja sygnałów jeśli sterujesz elementy mocy).
Praktyczne wskazówki
- Fuses (wariant A – kwarc 32,768 kHz):
- Clock source: Low‑frequency Crystal Oscillator 32.768 kHz.
- CKDIV8: wyłączony.
- SUT: najdłuższy czas startu dla niskiej częstotliwości (zależnie od noty).
- Zawsze zweryfikuj w kalkulatorze fuse dla ATtiny2313 i w dokumentacji.
- Sprzęt:
- Kwarc 32,768 kHz do pinów XTAL1/XTAL2 + dwa kondensatory do GND (typowo 12–22 pF zgodnie z notą kwarcu i pojemnościami pasożytniczymi PCB).
- Odsprzęganie: 100 nF blisko VCC–GND mikrokontrolera.
- PB3, PB4: jeśli sterujesz LED-ami, użyj rezystorów 330–1kΩ; dla obciążeń większych – tranzystor/MOSFET z diodą flyback (cewki).
- Test i kalibracja:
- Pomiar okresu wykonaj licznikiem czasu/oscyloskopem na PB3/PB4.
- Przy wewnętrznym RC możesz skorygować OSCCAL (zapis do rejestru w RESET), ale pamiętaj o dryfie temperaturowym.
Ewentualne zastrzeżenia lub uwagi dodatkowe
- Watchdog Timer (WDT) jako „generator 8 s” bywa kuszący, ale jego wewnętrzny RC ma dużą tolerancję i zależność od temperatury/napięcia – nie jest to metoda „jak najdokładniejsza” w ujęciu absolutnym.
- Wariant B (RC 1 MHz) jest funkcjonalny, ale nie zapewnia precyzji bez kalibracji i stabilnych warunków.
Sugestie dalszych badań
- Jeśli potrzebujesz jeszcze lepszej dokładności długoterminowej: kwarc o lepszym T.C. (np. 10 ppm) lub zewnętrzny RTC 32,768 kHz z kompensacją temperaturową (TCXO/DS3231) i wyjściem 1 Hz, z którego „zliczysz” 64 s sprzętowo lub programowo.
- Analiza wpływu temperatury na błąd czasowy (ppm/°C) i dobór elementów o niskim T.C. kondensatorów (NP0/C0G).
Krótkie podsumowanie
- Dla maksymalnej dokładności użyj zewnętrznego kwarcu 32,768 kHz jako zegara systemowego ATtiny2313 i Timer1 w trybie CTC z preskalerem 1024 oraz OCR1A=2047. ISR przełącza PB3 i PB4 co 64 s, dając okres 128 s z bardzo małym błędem.
- Jeśli zostajesz przy wewnętrznym RC 1 MHz, ustaw Timer1 CTC, preskaler 1024, OCR1A=62499 – rozwiązanie prostsze, ale mniej dokładne w czasie absolutnym.
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.