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



Teraz jest 25 kwi 2024, o 11:38


Strefa czasowa: UTC + 1





Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 2 ] 
Autor Wiadomość
PostNapisane: 31 mar 2019, o 06:59 
Offline
Nowy

Dołączył(a): 30 mar 2019
Posty: 1
Pomógł: 0

Witam , walczę ostatnio z pewnym kodem .
Teoretycznie wszystko powinno działać i w sumie działa ale rezultat jest inny od zakładanego.
Procek to Atmega8 taktowany z wewnętrznego oscylatora ustawionego na 8MHz.

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Ponieważ częstotliwość to 8MHz a preskaler ustawiony jest na 8 i OCR1A na 1, wiec procedura przerwania powinna być wywoływana
co 1us i po 4 us zmienna licznik powinna wynosić ok 4.
Tymczasem wyświetlana jest wartość 7 ?
Gdy zmieniam czas oczekiwania np na 2us to wynik = 5.
Wydaje mi się że wszystko robię dobrze , aż taki wpływ ma to że procek jest taktowany wewnętrznym oscylatorem a nie kwarcem ?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 31 mar 2019, o 10:01 
Offline
Użytkownik

Dołączył(a): 07 cze 2016
Posty: 563
Pomógł: 143

napuchanimator napisał(a):
Wydaje mi się że wszystko robię dobrze

Obawiam się, że nie do końca.

  1. Zmienna licznik powinna być zdefiniowana jako volatile, ponieważ jest używana zarówno w procedurze obsługi przerwania, jak i w pętli głównej programu. Być może tutaj nie jest to podstawowe źródło problemu, ale jest to istotne. Przy okazji taka sugestia odnośnie typów danych. Lepiej moim zdaniem używać typów całkowitych w stylu uint8_t, uint16_t, int 16_t itp. Określają one jednoznacznie rozmiar zmiennej w bajtach i łatwiej taki program analizować. Zmienna typu short może mieć inny rozmiar w zależności od platformy sprzętowej.
  2. Ustawiłeś wprawdzie preskaler 8, ale przy wartości OCR1A równej 1 przerwanie nie będzie co 8, tylko co 16 taktów. Okres przerwania w zastosowanym trybie CTC (w taktach) wynosi:
    (OCR1A + 1) * preskaler
  3. Procedurę obsługi przerwania masz wprawdzie krótką, ale i tak wywoływanie przerwania co 16 taktów zegara (a tym bardziej co 8) to nie najlepszy pomysł. Samo wejście w procedurę obsługi przerwania i powrót (instrukcja asm RETI) zajmują po 4 takty. Do tego prolog i epilog, załadowanie zmiennet z RAM, jej inkrementacja, ponowne zapisanie do RAM, więc mikrokontroler na pewno nie zdąży się wyrobić przed następnym przerwaniem.
  4. W komentarzach masz napisane, że włączasz i wyłączasz zezwolenie na przerwanie od porównania, ale czym te linijki się różnią? Z przedstawionego kodu wynika, że tak na prawdę wcale nie wyłączasz zezwolenia na przerwanie.
  5. Opóźnienie wprowadzane przez macro _delay_us() w sytuacji, gdy obsługiwanie są przerwania (tutaj jeszcze dodatkowo z bardzo dużą częstotliwością), jest bardzo niedokładne.

Podsumowując, taki kod nie będzie działał poprawnie i zgodnie z założeniem. Przede wszystkim przerwania nie mogą występować tak często. Jeśli chcesz sprawdzić poprawność odmierzania czasu, to użyj większego preskalera oraz większej wartości OCR1A, aby czasy były zauważalne dla człowieka. Jeśli chcesz sprawdzić dokładniej i/lub dla większych częstotliwości, pozostaje oscyloskop lub analizator stanów logicznych.



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: 2 ] 

Strefa czasowa: UTC + 1


Kto przegląda forum

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


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:  
Sitemap
Technologię dostarcza phpBB® Forum Software © phpBB Group phpBB3.PL
phpBB SEO