Saalin Napisano Luty 24, 2019 Udostępnij Napisano Luty 24, 2019 #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> #define LED_DDR DDRB #define LED_PORT PORTB #define LED0 PB0 #define LED2 PB1 #define LED1 PB2 ISR(TIMER1_COMPA_vect) { LED_PORT ^= (1 << LED0); } int main(void) { LED_DDR |= (1 << LED0) | (1 << LED1) | (1 << LED2); TCCR1A = (1 << COM1A0); //toggle OC1A on compare match TCCR1B |= (1 << CS12) | (1 << CS10) | (1 << WGM12) | (1 << WGM13); //CTC, presacler 1024 ICR1 = 15624; // 1Hz TIMSK1 |= (1 << OCIE1A); sei(); while (1) { _delay_ms(1000); LED_PORT ^= (1 << LED1); } } Działanie programu do pewnego momentu zgodne z oczekiwaniami - 3 diody LED zapalają się i gasną co sekundę. W pewnym momencie jednak następuje przesunięcie migania w fazie - dzieje się to nagle, nie jest tak, że coś tam niedokładności, miganie się rozjeżdża powoli itd - w pewnym momencie LED0 ma przestój nie 1s, tylko 2s (przynajmniej tak mi się wydaje po obserwacjach) i później diody migają na zmianę: raz LED0, raz LED1 wspólnie z LED2. Da się to jakoś logicznie wytłumaczyć? Nie zauważyłem, żeby zjawisko występowało okresowo. Cytuj Link do komentarza Share on other sites More sharing options...
miszczu18 Luty 24, 2019 Udostępnij Luty 24, 2019 Tak zapytam z ciekawości, na jakiej częstotliwości działa ta atmega? Bo może coś z tym preskalerem jest nie tak. Taka luźna opcja bo jestem super początkujący 😀 Cytuj Link do komentarza Share on other sites More sharing options...
Saalin Luty 25, 2019 Autor tematu Udostępnij Luty 25, 2019 Korzystam z Cytron Maker Uno, który taktowany jest kwarcem 16 MHz, kod kompiluję z opcją -D F_CPU 16000000. Cytuj Link do komentarza Share on other sites More sharing options...
andrews Marzec 2, 2019 Udostępnij Marzec 2, 2019 (edytowany) Dnia 24.02.2019 o 17:22, Saalin napisał: W pewnym momencie jednak następuje przesunięcie migania w fazie - dzieje się to nagle, nie jest tak, że coś tam niedokładności, miganie się rozjeżdża powoli itd - w pewnym momencie LED0 ma przestój nie 1s, tylko 2s (przynajmniej tak mi się wydaje po obserwacjach)... Da się to jakoś logicznie wytłumaczyć? Najprawdopodobniej przyczyną jest brak atomowego dostępu do portu LED_PORT. Instrukcja języka C - LED_PORT ^= (1 << LED1); wymaga tak naprawdę wykonania przez mikrokontroler kilku instrukcji asemblera. Jeśli pomiędzy tymi instrukcjami wystąpi przerwanie i zmieni zawartość portu, to po powrocie z procedury obsługi przerwania ta zmiana zostanie cofnięta. Rozwiązaniem może być wyłączenie przerwań na czas zmiany stanu portu: // ... while (1) { _delay_ms(1000); cli(); LED_PORT ^= (1 << LED1); sei(); } // ... Powinno pomóc, jednakże stosowanie funkcji _delay_ms() (szczególnie przy włączonej obsłudze przerwań) nie pozwala na jakieś precyzyjne odmierzanie czasu, więc miganie i tak się prędzej czy później rozjedzie 😐 Edytowano Marzec 2, 2019 przez andrews 1 Cytuj Link do komentarza Share on other sites More sharing options...
Polecacz 101 Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Produkcja i montaż PCB - wybierz sprawdzone PCBWay! • Darmowe płytki dla studentów i projektów non-profit • Tylko 5$ za 10 prototypów PCB w 24 godziny • Usługa projektowania PCB na zlecenie • Montaż PCB od 30$ + bezpłatna dostawa i szablony • Darmowe narzędzie do podglądu plików Gerber Zobacz również » Film z fabryki PCBWay
Anonim Marzec 9, 2019 Udostępnij Marzec 9, 2019 Dnia 2.03.2019 o 19:57, andrews napisał: stosowanie funkcji _delay_ms() (szczególnie przy włączonej obsłudze przerwań) nie pozwala na jakieś precyzyjne odmierzanie czasu, więc miganie i tak się prędzej czy później rozjedzie 😐 Dokładnie tak, dlatego do precyzyjnego odmierzania czasu należy korzystać z timerów i przerwań. W twoim programie czas wykonywania przerwania dodaje się do _delay_ms() i w rezultacie jedna dioda mruga wolniej. Proponuję też zajrzeć sobie do pliku *.lss po kompilacji i policzyć takty wykonywanych instrukcji w jednym i drugim przypadku wtedy będzie wszystko jasne zupełnie. Może okazać się również, że implementacja własnej wstawki asm będzie bardziej optymalnym rozwiązaniem niż kod wyprodukowany przez kompilator ale to kwestia wymagań dla konkretnego przypadku. Owocnej nauki. Cytuj Link do komentarza Share on other sites More sharing options...
Pomocna odpowiedź
Dołącz do dyskusji, napisz odpowiedź!
Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!