Przerwania timera - czy ten kod jest poprawny?

To forum jest dla wszystkich pasjonatów mikrokontrolerów AVR Atmela. Wymiana doświadczeń i pomoc dla początkujących w pisaniu programów zarówno w C, Asemblerze jak i BASCOM. Zapraszam znawców tematu, aby pomogli wszystkim początkującym!
ODPOWIEDZ
owoc0
-
Posty: 13
Rejestracja: 26 cze 2011, 14:11
Lokalizacja: Gdańsk

Przerwania timera - czy ten kod jest poprawny?

Post autor: owoc0 » 28 cze 2011, 21:41

Witam,

Ćwiczę sobie dalej timery. Jako, że dopiero zaczynam programować, nie chcę wyrobić sobie złych nawyków. Napisałem prosty program do znanego efektu Knight Rider. Kod działa, ale chciałbym się dowiedzieć, czy nie popełniłem jakiś zasadniczych błędów, które mogą mi zagrozić w pracy nad większymi projektami. Gdyby któryś z Was miał chwilę, bardzo bym prosił aby zerknąć.

Kod: Zaznacz cały

volatile int count;
volatile int speed;
volatile int flag;

Kod: Zaznacz cały

ISR(TIMER0_OVF_vect) //overflow
{
	if(++speed == 10)
	{
		PORTB = 0x00; 
	
		PORTB |= (1<<count);
		
		if(flag == 0)
		{
			if(++count == 3) flag = 1;
		}
		else if(flag == 1)
		{
			if(--count == 0) flag = 0;
		}
		
		speed = 0;
	}
}

Qwertxx
-
Posty: 33
Rejestracja: 21 kwie 2011, 1:19
Lokalizacja: Polska
Kontakt:

Post autor: Qwertxx » 28 cze 2011, 23:07

Generalnie OK.

Czy zmienna flag przyjmuje tylko wartości 1 lub 0?
Jeżeli tak to upraszczamy:

Kod: Zaznacz cały

ISR(TIMER0_OVF_vect) //overflow
{
	if(++speed == 10)
	{
		PORTB = 0x00; 
	
		PORTB |= (1<<count);
		
		if(flag)
		{
			if(--count == 0) flag = 0;
		}

		else

		{				{
			if(++count == 3) flag = 1;
		}
		
		speed = 0;
	}
}

Konstrukcji else if() używa się w bardziej skomplikowanych algorytmach.

owoc0
-
Posty: 13
Rejestracja: 26 cze 2011, 14:11
Lokalizacja: Gdańsk

Post autor: owoc0 » 28 cze 2011, 23:25

Dziękuję za odpowiedź. Mam jeszcze pewne pytanko. Przymierzam się do budowy układu przedstawiającego na matrycy LED jakąś prostą animacje. Czy mógłby mi Kolega podpowiedź jak powinno to wyglądać ze strony timera? Chciałbym powiedzmy, aby następna klatka ładowana była co 20 przerwań. Rozumiem, że podczas przepełnienia inkrementuję, ale co dalej? Jak to powiązać z main?

Qwertxx
-
Posty: 33
Rejestracja: 21 kwie 2011, 1:19
Lokalizacja: Polska
Kontakt:

Post autor: Qwertxx » 28 cze 2011, 23:34

Coś w tym stylu?:

Obrazek

Nie znam twojego projektu, ale wyobrażając sobie go, zapewne robiłbym wirtualny ekran w pamięci RAM, w którym tworzyłbym następną do wyświetlenia klatkę, a co 20 przerwań timera, zmieniałbym źródło danych do wyświetlenia na przeciwną do aktualnie wyświetlanej klatki.

Czyli w pamięci RAM dwa obszary z danymi do wyświetlenia:

A. aktualnie wyświetlany
B. aktualnie tworzony.

co 20 przerwań zmiana funkcji na przeciwne, czyli:

A. aktualnie tworzony.
B. aktualnie wyświetlany

I tak w kółko.

Czy opisałem to zrozumiale?
Czy o to Ci chodziło?

owoc0
-
Posty: 13
Rejestracja: 26 cze 2011, 14:11
Lokalizacja: Gdańsk

Post autor: owoc0 » 28 cze 2011, 23:42

Również myślałem o czymś podobnym. Mój problem polega jednak na czymś bliższym kodowi. Powiedzmy, że w main wykonuję operacje przygotowujące tablicę do wyświetlenia jej na wyświetlaczu. W jaki sposób zakomunikować o tym, że powinienem już zacząć? Wystawiać jakąś flagę poprzez przerwanie i czekać na nią w pętli w main?

Qwertxx
-
Posty: 33
Rejestracja: 21 kwie 2011, 1:19
Lokalizacja: Polska
Kontakt:

Post autor: Qwertxx » 28 cze 2011, 23:45

Dokładnie tak bym zrobił. Co dwudzieste przerwanie będzie decydowało o zmianie klatki na przeciwną i jednoczesnym rozpoczęciu tworzenia nowej klatki.

owoc0
-
Posty: 13
Rejestracja: 26 cze 2011, 14:11
Lokalizacja: Gdańsk

Post autor: owoc0 » 28 cze 2011, 23:49

Rozumiem. Nie ma więc nic złego w takim łączeniu main z overflow? Nie muszę się przejmować szybkością, ani tym, czy main się "wyrobi" przed następnym przerwaniem?

Qwertxx
-
Posty: 33
Rejestracja: 21 kwie 2011, 1:19
Lokalizacja: Polska
Kontakt:

Post autor: Qwertxx » 28 cze 2011, 23:53

owoc0 pisze:Nie ma więc nic złego w takim łączeniu main z overflow?
To powszechnie stosowana technika. Zasada jest prosta:

PRZERWANIE MUSI WYKONYWAĆ SIĘ JAK NAJSZYBCIEJ I KOŃCZYĆ

Resztę ma robić main().
owoc0 pisze:Nie muszę się przejmować szybkością, ani tym, czy main się "wyrobi" przed następnym przerwaniem?
To że czas tworzenia nowej klatki zajmie Ci kilka czy kilkanaście przerwań nie ma znaczenia, bo dopiero 20 przerwanie oznacza przełączenie na nową klatkę. Czyli Twój deadline to tworzenie nowej klatki przez main() nie może być dłuższe niż 20 przerwań.

owoc0
-
Posty: 13
Rejestracja: 26 cze 2011, 14:11
Lokalizacja: Gdańsk

Post autor: owoc0 » 28 cze 2011, 23:56

Bardzo dziękuję za fachową pomoc. Już jutro wezmę się do pracy i zobaczę jak wygląda to w praktyce. Jeszcze raz dziękuję. Pozdrawiam i życzę spokojnej nocy.

Qwertxx
-
Posty: 33
Rejestracja: 21 kwie 2011, 1:19
Lokalizacja: Polska
Kontakt:

Post autor: Qwertxx » 28 cze 2011, 23:58

Powodzenia i wzajemnie :)
I napisz o rezultatach.

Qwertxx
-
Posty: 33
Rejestracja: 21 kwie 2011, 1:19
Lokalizacja: Polska
Kontakt:

Post autor: Qwertxx » 03 lip 2011, 17:12

owoc0 pisze: a) Czy poprawne jest wykorzystywanie techniki: w main() czekam na flagę, którą wystawiam poprzez przerwanie timera?
b) Jak powinienem odświeżać to, co rysuję na wyświetlaczu? Co kilka przerwań czyścić całą tablicę i rysować ponownie? Przymierzam się do napisania prostej gry, stąd moje pytanie.
c) Jak zrealizować obsługę klawiszy. W jaki sposób sprawdzać stan co jakiś czas, lub reagować tylko na jednorazowe naciśnięcie, a nie przytrzymywanie.
Zaraz odpowiem ...

Qwertxx
-
Posty: 33
Rejestracja: 21 kwie 2011, 1:19
Lokalizacja: Polska
Kontakt:

Post autor: Qwertxx » 03 lip 2011, 17:18

1. Pokaż aktualny Twój program.
2. Schemat także by się przydał.

owoc0 pisze:a) Czy poprawne jest wykorzystywanie techniki: w main() czekam na flagę, którą wystawiam poprzez przerwanie timera?
Już o tym pisałem. Tak, to poprawna metoda.

owoc0 pisze:b) Jak powinienem odświeżać to, co rysuję na wyświetlaczu? Co kilka przerwań czyścić całą tablicę i rysować ponownie?
Także już o tym pisałem. Dodam tylko, że czyścisz ten (jak to nazwałem) obszar, w którym będziesz tworzył następną klatkę, a obszar z którego aktualnie wyświetlasz nie ruszasz. A potem odwrotnie.

owoc0 pisze:c) Jak zrealizować obsługę klawiszy. W jaki sposób sprawdzać stan co jakiś czas, lub reagować tylko na jednorazowe naciśnięcie, a nie przytrzymywanie.
Wykorzystasz do tego ten sam timer, co do multipleksowania wyświetlacza i generowane przez niego przerwanie. czy znasz takie zjawisko jak Bouncing czyli drgania styków: http://mikrokontrolery.blogspot.com/201 ... ncing.html

A rozróżnianie czy przycisk jest trzymany czy naciskany wielokrotnie realizuje się licząc czas przyciśnięcia i czas puszczenia klawisza - nie ma innej metody.

ODPOWIEDZ