Kanał - ATNEL tech-forum
Wszystkie działy
Najnowsze wątki



Teraz jest 10 lut 2026, o 19:51


Strefa czasowa: UTC + 1





Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 9 ] 
Autor Wiadomość
PostNapisane: 11 lis 2015, o 12:36 
Offline
Nowy

Dołączył(a): 04 lip 2013
Posty: 10
Pomógł: 0

Witam, mam dość specyficzny problem, z którym głowię się już od jakiegoś czasu.

Próbuje ustawić timer0 tak by generował mi przerwanie dokładnie co 1us. Zaczynam od ustawienia fusebitów (lfuse = 0xe4) co daje mi taktowanie wewnętrznym oscylatorem z częstotliwościa f_osc=8MHz.
Później zabieram się za ustawienie timera0:
Kod:
TCCR0 = (TCCR0 & 0b11111000);
TCCR0 |= (1<<CS00);
TIMSK |= (1<<TOIE0);
TCNT0 = 0xfe;

czyli kolejno czyszczenie starych ustawień na trzech ostatnich bitach rejestru TCCR0, wrzucenie tam nowej wartości (0b001), uruchomienie przerwania dla "przekręcenia" licznika timera oraz ustawienie licznika na 254. W przerwaniu ustawiam TCNT0 = 0xfe. W ten sposób powinienem uzyskać przerwanie generowane co 1us. Problem polega na tym, że generowane jest ono co 16us. Co dziwniejsze ustawienie preskalera z wartości no_preskaler (0b001 w rejestrze TCCR0) na wartość /8 (0b010 w rejestrze TCCR0) nie powoduje żadnych zmian w działaniu programu tj. przerwanie wywoływane jest cały czas co 16us. Z kolei zmiana na wartości preskalera większe większe niż /8 zmniejsza częstotliwość wywoływania przerwania w sposób prawidłowy (czyli dwukrotne zwiększenie preskalera powoduje zmniejszenie częstotliwości "przekręcania" licznika o połowę).

Przeglądałem notę katalogową i w rozdziale dotyczącym timerów nie znalazłem, żadnych dodatkowych ustawień mogących mieć wpływ na częstotliwość generowania przerwania. Powstaje pytanie - czy ja robię coś źle, czy jest to wina wadliwego uC czy może dochodzę do granic możliwości mikrokontrolera, który fizycznie nie jest w stanie generować przerwania z zadaną częstotliwością przy taktowaniu wewnętrznym oscylatorem 8MHz?

Z góry dziękuję za pomoc,
Pozdrawiam



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 11 lis 2015, o 12:39 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27449
Lokalizacja: Szczecin
Pomógł: 1045

gravell napisał(a):
Powstaje pytanie - czy ja robię coś źle, czy jest to wina wadliwego uC czy może dochodzę do granic możliwości mikrokontrolera,

Matko jeryhejska ! ... sorrry ale jak słyszę że wadliwy uC albo że 1us to granice jego możliwości no to nic innego nie ciśnie mi się na usta ....

Panie kochany - nie szukaj błędu w procku, tylko u siebie bo robisz paskudnego babola a ty tu domyślasz się granic albo złego działania procka ... .masakra

Tryb NORMAL to nie tryb CTC. Więc nic ci to nie da że przy inicjalizacji ustawisz TCNT0 .... jeszcze to samo musisz robić w przerwaniu.

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 11 lis 2015, o 12:43 
Offline
Nowy

Dołączył(a): 04 lip 2013
Posty: 10
Pomógł: 0

mirekk36 napisał(a):
Tryb NORMAL to nie tryb CTC. Więc nic ci to nie da że przy inicjalizacji ustawisz TCNT0 .... jeszcze to samo musisz robić w przerwaniu.


I dokładnie to robię w przerwaniu:

gravell napisał(a):
(...) W przerwaniu ustawiam TCNT0 = 0xfe. (...)


;)

Pozdrawiam



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 11 lis 2015, o 12:49 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27449
Lokalizacja: Szczecin
Pomógł: 1045

To pokaż lepiej to przerwanie - bo zaraz się okaże, że jest naszprycowane kodem, który je rozciąga w czasie ;) do 16 us

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 11 lis 2015, o 13:20 
Offline
Nowy

Dołączył(a): 04 lip 2013
Posty: 10
Pomógł: 0

Kod przerwania:
Kod:
uint32_t tim = 0;
...
ISR(TIMER0_OVF_vect)
{
   tim++;
   if(tim == 1000000)
     {
        tim = 0;
        tbi(PORTB, PB0);
     }
   TCNT0 = 0xfe;
}

Zapewne padnie pytanie po co przerwanie co 1us skoro faktycznie korzystam z niego co milion wywołań - oczekiwanie na co milionowe wywołanie jest tylko i wyłącznie do testów. W samym przerwaniu zamierzam jedynie zmieniać stan jednego z wyjść uC więc docelowy kod będzie wyglądać tak:
Kod:
ISR(TIMER0_OVF_vect)
{
     if(changeRequired)
       tbi(PORTB, PB0);
}



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 11 lis 2015, o 13:47 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 20 sie 2013
Posty: 795
Lokalizacja: Poznań
Pomógł: 59

Zastanów się ile taktów zegara potrzeba na wykonanie tego, co masz w przerwaniu. Skoro chcesz mieć przerwanie co 1us, czyli przerwanie będzie wykonywane z częstotliwością 1MHz. Taktując procesor 16MHz masz max 16 taktów/przerwanie by przerwania się nie nałożyły a co dopiero coś poza przerwaniem wykonać... Operacja na uint32_t to zgon dla 8-bitowca w przerwaniu.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 11 lis 2015, o 13:54 
Offline
Nowy

Dołączył(a): 04 lip 2013
Posty: 10
Pomógł: 0

icer_cmg napisał(a):
Zastanów się ile taktów zegara potrzeba na wykonanie tego, co masz w przerwaniu. Skoro chcesz mieć przerwanie co 1us, czyli przerwanie będzie wykonywane z częstotliwością 1MHz. Taktując procesor 16MHz masz max 16 taktów/przerwanie by przerwania się nie nałożyły a co dopiero coś poza przerwaniem wykonać... Operacja na uint32_t to zgon dla 8-bitowca w przerwaniu.


Stąd w pierwszym poście padło pytanie czy przypadkiem nie docieram do granicy możliwości mikrokontrolera. uC jest taktowany wewnętrznym zegarem 8MHz co oznacza, że mam 8taktów na wykonanie kodu w przerwaniu.
Rozumiem, że w takim wypadku możliwe jest aby dwa różne ustawienia preskalera (no_prescale i /8) dały te same efekty w ilości wykonań przerwań na sekundę? Jeżeli tak, to sprawa rozwiązana :)

Pozdrawiam i dziękuję za pomoc



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 11 lis 2015, o 14:08 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27449
Lokalizacja: Szczecin
Pomógł: 1045

A wiesz, że poza tym co sam napisałeś w przerwaniu to ono ma jeszcze tzw prolog i epilog ? czyli dodatkowy kod na wejściu i na wyjściu ?

Jak ustawisz preskaler na 1 to nie docierasz do granicy możliwości procka tylko docierasz do granicy tego że warto wiedzieć jak to działa. Że rowerem nie jedzie się na wyścigi no motocrosowe

Warto też wiedzieć jak w ogóle działają przerwania ... obejrzyj sobie to:
http://mirekk36.blogspot.com/2013/12/pr ... acego.html

wprawdzie to poradnik troszkę z przymrużeniem oka ale pokazuję w nim dokładnie o co chodzi

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 11 lis 2015, o 17:38 
Offline
Nowy

Dołączył(a): 04 lip 2013
Posty: 10
Pomógł: 0

Wszystko jasne ;).

Dziękuję za pomoc,
Pozdrawiam



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
Wyświetl posty nie starsze niż:  Sortuj wg  
Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 9 ] 

Strefa czasowa: UTC + 1


Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 1 gość


Nie możesz rozpoczynać nowych wątków
Nie możesz odpowiadać w wątkach
Nie możesz edytować swoich postów
Nie możesz usuwać swoich postów
Nie możesz dodawać załączników

Szukaj:
Skocz do:  
cron
Sitemap
Technologię dostarcza phpBB® Forum Software © phpBB Group phpBB3.PL
phpBB SEO