Skocz do zawartości

Arduino i timery - problem ze zrozumieniem preskalerów


Pomocna odpowiedź

To jeszcze obsługa przerwania OVF

ISR(TIMER2_OVF_vect) {
	static uint8_t ovfCount;
	static int8_t dir = 1;

	if (++ovfCount > 5) {
		ovfCount = 0;
		if (OCR2B == 255)dir = -1;
		if (!OCR2B)dir = 1;
		OCR2B += dir;
	}
}

 

45 minut temu, _LM_ napisał:

Nie muszę chyba pisać że manipulując rejetrami A i B zmieniasz pwm sygnału. 

Nie musisz...😉 jest to juz zrozumiale dla mnie...

 

46 minut temu, _LM_ napisał:

ADD: manipulując bitami COM2A....B itd oraz FOC można sprzętowo generować pwm bez udziału funkcji zawartych w przerwaniach, problem w tym że wtedy trzeba posługiwać się pinami przypisanymi na stałe(przez producenta) do kanałów pwm danego timera.

To tez juz zalaplem z wczesniejszych lektur...🙂 Dzieki wielkie za konkretne odpowiedzi kolego @_LM_ ...dzis bede spal spokojnie , bo nie ukrywam ze jak mi cos do tej lepetyny wpadnie to musze znac odpowiedz juz! teraz!!...bo mnie zjesc chce zywcem..😅 a teraz juz wiem o co kaman z tymi COMPA/COMPB...

Kurcze no...nie moge zrozumiec zasady dzialania tego trybu...podales przyklad z trybem "pwm z poprawna faza"...i nie moge zrozumiec jak bedzie sie zmienial stan pinu na przeciwny...rozumiem zapis w ISR...w normalnym trybie kiedy OCR jest porownane z TCNT nastepuje przerwanie...a jak tutaj sie to dzieje ze raz warunek bedzie spelniony a raz nie..??

OCR2A = 250;

ISR(TIMER2_COMPA_vect){

(OCR2A > TCNT2) ? (PORTC|=(1<<PC2)) : (PORTC&=~(1<<PC2));
}

 

(edytowany)

To jest operator trójargumentowy tę instrukcję można rozpisać tak

if(OCR2A > TCNT2){
		PORTC|=(1<<PC2);
	}else{
		PORTC&=~(1<<PC2);	
	}

http://www.algorytm.edu.pl/wstp-do-c/trojargumentowy-operator.html

Czyli: jeśli aktualna wartość timera jest mniejsza od OCR2A to ustawia PC2 jeśli nie to zeruje PC2, fakt że użyłem nadmiarowych nawiasów ale to nie zmienia działania funkcji. Przerwanie TIMER2_COMPA_vect jest wykonywane przy każdym zgodnym porównaniu.

Edytowano przez _LM_
5 minut temu, _LM_ napisał:

Przerwanie TIMER2_COMPA_vect jest wykonywane przy każdym zgodnym porównaniu.

No wlasnie...wiec warunek zawsze bedzie spelniony lub nie...🙄 (tamten zapis z "?" ja dobrze rozumiem) chodzi mi jak to jest ze raz OCRx bedzie wiekszy a raz mniejszy od TCNT??...przeciez przerwanie wywolane jest wlasnie w momencie kiedy oba sa takie same tak?

43 minuty temu, farmaceuta napisał:

przeciez przerwanie wywolane jest wlasnie w momencie kiedy oba sa takie same tak?

Tak ale tutaj niechcący wprowadziłem Cię w błąd, pisząc że timer się "przekręca" a tak naprawdę to nie. W tym trybie, kiedy timer doliczy do 255  kierunek zliczania odwraca się, więc liczy z powrotem do zera, zaś przy osiągnięciu zera wołane jest przerwanie TOV. Widać to na tym kawałku noty:

timer.thumb.JPG.6a9641ae1ee58f426077532311c53a72.JPG

wniosek jest taki że w czasie całego cyklu 0...255 255...0 przerwanie od porównania wykonuje się dwa razy i stąd mamy informację o tym czy TCNT jest większy od OCR czy mniejszy. Także przepraszam za wcześniejszą głupotę którą palnąłem.

 

  • Lubię! 1
16 minut temu, _LM_ napisał:

Tak ale tutaj niechcący wprowadziłem Cię w błąd, pisząc że timer się "przekręca" a tak naprawdę to nie. W tym trybie, kiedy timer doliczy do 255  kierunek zliczania odwraca się, więc liczy z powrotem do zera, zaś przy osiągnięciu zera wołane jest przerwanie TOV. Widać to na tym kawałku noty:

timer.thumb.JPG.6a9641ae1ee58f426077532311c53a72.JPG

wniosek jest taki że w czasie całego cyklu 0...255 255...0 przerwanie od porównania wykonuje się dwa razy i stąd mamy informację o tym czy TCNT jest większy od OCR czy mniejszy. Także przepraszam za wcześniejszą głupotę którą palnąłem.

 

nie no nic nie palnales...wszystko jest ok..wiem ze timer liczy w obie strony tylko dalej nie rozumiem jaka wartosc bedzie mial TCNT w momencie przerwania, bo generalnie wedlug przykladu OCRx = 250 raz musi byc mniejszy a raz wiekszy zeby mozna zmieniac stan  wedlug kodu powyzej..

No więc zobacz do tego pdfa tam jest dodatkowy rejestr - cyfrowy komparator i to on nadzoruje i zarządza pośrednio tym kiedy ma nastąpić przerwanie. To jest rozwiązane sprzętowo wewnątrz mikrokontrolera. Zapewne jakąś matryca bramek powiedzmy AND. I kiedy ta matryca wykryje że wszystkie bity rejestru OCR == TCNT to wtedy wystawia odpowiedni sygnał który jest interpretowany zależnie od nastaw timera. No nie chciałbym wchodzić w takie niuanse bo za krótki na to jestem 🙂

  • Lubię! 1

Niech mnie ktos poprawi jesli sie myle...ale doszedlem do takiej teotrii ze w tym calym pwm licze od 0-255 i od 255-0...i to jest jasno napisane, w momencie zrownania sie OCRx z TCNT (np. te 250) TCNT zostaje zwiekszony o 1 i zostaje wykonane przerwanie..po czym licznik liczy do konca i zaczyna odliczac do zera..przy ponownym "spotkaniu" OCRx zostaje odjete 1 od TCNT i wykonane przerwanie..............no niewiem, tak mi wyszlo z testu z serialem...

if(OCR2A > TCNT2){
    PORTC|=(1<<PC2);
      Serial.println(TCNT2);
  }else{
    PORTC&=~(1<<PC2); 
    Serial.println(TCNT2);

  }

raz mam 251 a raz 249.......

Tu jeszcze drobna uwaga: to porownanie o którym wyżej pisałem dokonuje się na jednym zboczu sygnału zegarowego: można powiedzieć że system "pamięta" poprzedni stan matrycy a kiedy przyjdzie następny impuls a stan matrycy jest różny od poprzedniego to wtedy następuje przerwanie. Także wcześniej znów nieco mylnie napisałem. 

3 minuty temu, farmaceuta napisał:

raz mam 251 a raz 249.......

Ładowanie bufora i wysyłka danych też zajmuje nieco czasu. 

1 minutę temu, _LM_ napisał:

Ładowanie bufora i wysyłka danych też zajmuje nieco czasu. 

tak tak rozumiem ale wynik jest zawsze taki sam...251/249/251/249.....no i dobrze bo gdyby podczas wykonania przerwania TCNT mial te 250 to zawsze bybly warunek niespelniony z powyzszego kodu i stan pinu nigdy nie zostal by odwrocony i to wlasnie bylo dla mnie nie zrozumiale...w suie dalej nie jestem pewny

Jeśli chcesz programowo przejąć i odczytać wartość TCNT to najlepiej zrobić to za pomocą dodatkowej zmiennej ze spscyfikatorem register następnie do niej wpisać wartość TCNT a dopiero w pętli głównej wysłać na serial. Przykładu już nie podam bo kompa wyłączyłem. Ale z grubsza powinno to wyglądać tak:

register uint8_t tcntx;

I przerwaniu ładujesz do tej zmiennej wartość rejestru plus ustawiasz sobie jakąś flagę że przerwanie nastąpiło aby potem móc odczytać wartość tej zmiennej 

Wynikiem powinno być na przemian wartość o 1 większa lub mniejsza od OCR inaczej nie miałoby to szans na działanie 

Musi to jakos tak dzialac jak napisalem bo wprzeciwnym razie ten kod zawsze bylby wykonany tak samo bez wzgledu czy licznik idzie w gore czy w dol...

if(OCR2A > TCNT2){
		PORTC|=(1<<PC2);
	}else{
		PORTC&=~(1<<PC2);	
	}

jezeli w przerwaniu TCNT mialby te 250 to pin bylby zawsze "gaszony" a tu mam tak ze liczni k jest wiekszy lub miejszy o 1 w zaleznosci w ktora strone liczyl

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...