Skocz do zawartości

Arduino i timery - problem ze zrozumieniem preskalerów


farmaceuta

Pomocna odpowiedź

(edytowany)

Panowie takie pytanie...bo widze ze mam dla kazdego timera dwa przerwania "compare"...czyli "A" i "B" no ale po zamianie na literke "B" tam gdzie trzeba nie dziala...ktos ma jakies pomysly dlaczego? Moze cos jeszcze trzeba ustawic?

no i tak..w normalnym trybie oba vectory dzialaja czyli

TIMER1_COMPA_vect
TIMER1_COMPB_vect

oczywiscie pojedynczo bo jest tylko jeden licznik TCNT...natomiast w trybie CTC dziala tylko "wersja-A" ...(sprawdzane na timerze2) czego ja tu nie rozumiem?

Edytowano przez farmaceuta
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

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

2 godziny temu, farmaceuta napisał:

czego ja tu nie rozumiem?

Noty katalogowej 😉 A tak na serio, pokaż całą próbkę programu gdzie ustawiasz timer.

  • Lubię! 1
Link do komentarza
Share on other sites

26 minut temu, _LM_ napisał:

Noty katalogowej 😉

powiedzial co wiedzial...😁haha (zarciki)

int x = 0;

void setup() 
{
  
  cli();  
 
  TCCR2B= 0x00;
  TCCR2A= 0x00;
  
  // TCCR2A |= (1<<WGM21);     //CTC                            
  
  TIMSK2= 6;    // timer2 output compare A & B match enabled
  TCCR2B |= (1<<CS21);      //preskaler na 8
  OCR2A= 120;    // 
  // OCR2B= 15;

  pinMode(13, OUTPUT);

  sei();
}


ISR(TIMER2_COMPA_vect)
{
   x++;
   // TCNT2 = 240;
  
}

ISR(TIMER2_COMPB_vect)
{
   //  x++ ;
   //  TCNT2 = 40;
}

void loop() 
{
  if (x > 5000)  {
  static int stan = 0;
  stan = !stan;
  digitalWrite(13, stan);
  x = 0;
  
  } 
}

to taki bazgral z neta...i masz zupelna racje, nie rozumiem tej noty katalogowej i narazie jej nie zrozumiem chyba, czytajac rozne strony/przyklady calkiem mi sie juz to pomieszalo...powiedzmy ze mam dwie diody...oge je jakos odpalac tymi ISR-A...ISR-B? indywidualnie? pomijam fakt braku kodu odpowiedzialnego za taka prace...chodzi tylko o te przerwania

Link do komentarza
Share on other sites

2 godziny temu, farmaceuta napisał:

powiedzial co wiedzial...😁haha (zarciki)

spoko 😉 ponieważ "z palca" tego nie napiszę to trzeba zajrzeć do tej notki. I tak.... 

 TIMSK2= 6;    // timer2 output compare A & B match enabled

Co to w ogóle oznacza? Według mnie jest to najgorszy możliwy sposób na ustawienie rejestru. Ile czasu zajmuje napisanie czegoś takiego...

DDRC|=(1<<PC2)|(1<<PC3);

TCCR2A |=(1<<WGM21); // CTC
TCCR2B |=(1 << CS20)|(1<<CS21)|(1<<CS22); // Prescaler 1024
TIMSK2 |=(1<<OCIE2B)|(1<<OCIE2A); // przerwania

OCR2A = 70; // co ile?
//OCR2B = 60;


sei();

Przerwania:

ISR(TIMER2_COMPA_vect){

	static uint8_t licznik;

	if(++licznik > 180){
	licznik = 0;
	PORTC ^= (1<<PC2);
	}
	}

ISR(TIMER2_COMPB_vect){

	static uint8_t licznik;

	if(++licznik > 100){
	licznik = 0;
	PORTC ^= (1<<PC3);
	}
}

Ponieważ timer2 jest ma tylko 8bitów niemożliwe jest uzyskanie... jakby to powiedzieć... dwóch niezależnych przerwań od compare math gdyż już pierwsze zrównanie z OCR2A lub B (zależnie od tego które ma niższą nastawę) wyzeruje rejestr TCNT2 i timer zacznie liczyć od zera. O tyle dobrze że zerowanie wywoła oba przerwania dzięki czemu powyższy kod działa. Chciałem wrzucić króciutkiego gif-a z działania ale chyba się nieda 😉

Edytowano przez _LM_
  • Pomogłeś! 1
Link do komentarza
Share on other sites

Ah i jeszcze taki knif u ciebie jest 

int x = 0;

oraz w przerwaniu

ISR(TIMER2_COMPA_vect)
{
   x++;
   // TCNT2 = 240;
  
}

To w gcc ten x może w ogóle nie zmienić swojej wartości gdyż kompilator zoptymalizuje dostęp do tej zmiennej, aby zapis był prawidłowy do zmiennych używanych w przerwaniu jak i później w pętli głównej należy dodać specyfikator volatile czyli:

volatile int x = 0; // poza tym zmienne globalne są zerowane automatycznie więc nie trzeba robić tego przypisania "x=0;"

 

Link do komentarza
Share on other sites

19 minut temu, _LM_ napisał:

 


 TIMSK2= 6;    // timer2 output compare A & B match enabled

Co to w ogóle oznacza? Według mnie jest to najgorszy możliwy sposób na ustawienie rejestru..

 

 

Zgadzam sie z Toba calkowicie...to byl kod z neta wiec juz nie zmienialem zapisu bo wiedzialem ze 6 ustawia dwa mlodsze bity...

 

21 minut temu, _LM_ napisał:

Ponieważ timer2 jest ma tylko 8bitów niemożliwe jest uzyskanie... jakby to powiedzieć... dwóch niezależnych przerwań od compare math gdyż już pierwsze zrównanie z OCR2A lub B (zależnie od tego które ma niższą nastawę) wyzeruje rejestr TCNT2 i timer zacznie liczyć od zera.

I dokladnie tez tak myslalem...ale po wniknieciu w temat zrozumialem ze moge uzywac porownania do OCRx bez opcji CTC...czyli ustawiam co chce w OCRx i wtedy wystapi przerwanie z tym ze TCNT nie zostanie wyzerowany tylko goni dalej az sam sie przekreci i zacznie liczyc od zera...dopoki tego nie zrozumialem to kombinujac z nastawami mialem cuda (a wszystko bylo ok)...inaczej sprawa wyglada w trybie CTC...tu wersja z B nie dziala wogole mimo ze wersja A wylaczona...chodz to i tak bez znaczenia skoro jak sam wyzej napisales licznik sie bedzie zerowal dla jednego porownania...zastanawiam sie tylko po co dwa takie same vectory sa...skoro nie moga dzialac indywidualnie...

  • Lubię! 1
Link do komentarza
Share on other sites

45 minut temu, _LM_ napisał:

Ah i jeszcze taki knif u ciebie jest 


int x = 0;

oraz w przerwaniu


ISR(TIMER2_COMPA_vect)
{
   x++;
   // TCNT2 = 240;
  
}

To w gcc ten x może w ogóle nie zmienić swojej wartości gdyż kompilator zoptymalizuje dostęp do tej zmiennej, aby zapis był prawidłowy do zmiennych używanych w przerwaniu jak i później w pętli głównej należy dodać specyfikator volatile czyli:


volatile int x = 0; // poza tym zmienne globalne są zerowane automatycznie więc nie trzeba robić tego przypisania "x=0;"

 

Tak tak..to jest dla mnie zrozumiale calkowicie...to tylko tak dla testu czy cokolwiek te przerwania dzialaja itp i modyfikuja zmienne...a globalne zawsze z przyzwyczajenia inicjuje "czyms tam"...

Link do komentarza
Share on other sites

24 minuty temu, farmaceuta napisał:

Zgadzam sie z Toba calkowicie...to byl kod z neta wiec juz nie zmienialem zapisu bo wiedzialem ze 6 ustawia dwa mlodsze bity...

Ok wziąłem odpowiednią maść i już mi przeszło xD wiem że wiesz jak to zapisywać.

24 minuty temu, farmaceuta napisał:

zastanawiam sie tylko po co dwa takie same vectory sa...skoro nie moga dzialac indywidualnie...

Heh nie pomyślałem nad tym. W sumie powyższy kod śmiało można zapisać w jednym przerwaniu. 

 

Edytowano przez _LM_
Link do komentarza
Share on other sites

2 minuty temu, _LM_ napisał:

Heh nie pomyślałem nad tym w sumie powyższy kod śmiało można zapisać w jednym przerwaniu

 

Na teraz to mi to do niczego nie potrzebne bylo..tylko jak otworzylem dzis oko to odrazu do glowy mi mysl wpadla..."COMPA"...."COMPB"......?? Wiec pomyslalem ze da sie tak te dwa przerwania pogodzic zeby indywidualnie dzialaly...ale na dzis to mi juz wystarczy tego szalenstwa...😅

Link do komentarza
Share on other sites

To się przydaje kiedy timer jest w trybie PWM a nie CTC. Wtedy faktycznie te dwa vectory działają niezależnie ponieważ w PWM timer "kręci się w kółko". Muszę to kiedyś wypróbować.

//TCCR2A |=(1<<WGM21); // CTC

TCCR2B |=(1 << CS20)|(1<<CS21)|(1<<CS22); // Prescaler 1024
TIMSK2 |=(1<<OCIE2B)|(1<<OCIE2A); // przerwania



OCR2A = 255; // co ile?
OCR2B = 10;

ISR(TIMER2_COMPA_vect){

	static uint8_t licznik;
PORTC ^= (1<<PC2);
//	if(++licznik > 100){
//	licznik = 0;
//
//	}
	}

ISR(TIMER2_COMPB_vect){

	static uint8_t licznik;
PORTC ^= (1<<PC3);
//	if(++licznik > 100){
//	licznik = 0;
//
//	}
}

Zrobiłem taki test, jutro podłączę oscyloskop i zobaczę jak zmienia się stan diod.

Edytowano przez _LM_
Link do komentarza
Share on other sites

(edytowany)
32 minuty temu, _LM_ napisał:

Zrobiłem taki test, jutro podłączę oscyloskop i zobaczę jak zmienia się stan diod.

No to ja Ci juz teraz odpowiem...czas on/off dla obu bedzie identyczny...jedynie moment przelaczania sie odrobinke przesunie(poprawka- przesunie sie prawie na przeciwne stany diod)...nie ma tu modyfikacji TCNT wiec zmiana nastapi co pelny zakres 8-bitow...

Edytowano przez farmaceuta
Link do komentarza
Share on other sites

Ok dotarłem do pracy to mogę działać dalej. 

#include <avr/io.h>
#include <avr/interrupt.h>

int main(void){

DDRC|=(1<<PC2)|(1<<PC3);

//TCCR2A |=(1<<WGM21); // CTC
TCCR2A |=(1<<WGM22)|(1<<WGM20);
TCCR2B |=(1 << CS20)|(1<<CS21);//|(1<<CS22); // Prescaler 1024
TIMSK2 |=(1<<OCIE2B)|(1<<OCIE2A)|(1<<TOIE2); // przerwania

OCR2A = 250; // co ile?
OCR2B = 2;


sei();
	for(;;){

	}
}

ISR(TIMER2_COMPA_vect){

//	static uint8_t licznik;
//PORTC ^= (1<<PC2);

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


//	if(++licznik > 100){
//	licznik = 0;
//
//	}
	}

ISR(TIMER2_COMPB_vect){

//	static uint8_t licznik;
//PORTC ^= (1<<PC3);
//	if(++licznik > 100){
//	licznik = 0;
//
//	}

	(OCR2B > TCNT2) ? (PORTC|=(1<<PC3)) : (PORTC&=~(1<<PC3));

}

ISR(TIMER1_OVF_vect){
}

Tak więc mamy dwa kanały PWM plus wolne przerwanie od przepełnienia 🙂 oczywiście przerwanie to następuje co pełny "obrót" timera i niema co skracać tego cyklu. 

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

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.

Edytowano przez _LM_
EDIT & ADD
  • Pomogłeś! 1
Link do komentarza
Share on other sites

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!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.