logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[Atmega8][bascom] timer2 CTC generuje przerwanie tylko raz

nanab 28 Paź 2018 02:04 777 10
REKLAMA
  • #1 17522444
    nanab
    Poziom 27  
    Czy da się generować przerwania od timer2 przy każdym przepełnieniu w trybie CTC? Próbuję generować częstotliwość w zależności od ustawienia potencjometru, ale timer generuje przerwanie tylko raz, cały program poniżej:
    Kod: VB.net
    Zaloguj się, aby zobaczyć kod

    Do OCR2 zostaje wpisana tylko pierwsza odczytana wartość zaraz po starcie programu, dalej już nie generuje przerwań. Po wrzuceniu " OCR2 = Dowpisania" do głównej pętli działa prawidłowo, zmienia częstotliwość. Po wyłączeniu CTC w configu ("Clear timer=0") wchodzi do przerwania, ale nie reaguje na wartość ocr2, mogę wpisać cokolwiek, a generowana częstotliwość się nie zmienia.
  • REKLAMA
  • #2 17524324
    kamyczek
    Poziom 38  
    Zastanów się jaką częstotliwość będzie generował Licznik2 dla wartości zero ? Zastanów się też jak wpisać 10 bitową wartość przetwornika do 8 bitowego rejestru danych . Kolejne zagadnienie ,to jak się ma czas konwersji przetwornika adc do częstotliwości wystąpienia przerwań ? . Ten program przestanie się wykonywać gdy czas obsługi przerwania będzie dłuższy do częstotliwości jego wystąpień .
  • REKLAMA
  • #3 17524426
    nanab
    Poziom 27  
    kamyczek napisał:
    Zastanów się jaką częstotliwość będzie generował Licznik2 dla wartości zero ?

    Równą częstotliwości jaką dostaje od prescalera. Tylko w jakim celu skoro taka sytuacja nigdy nie wystąpi? Wartość którą wyrzuca adc to 512+-320, potencjometr jest mechanicznie ograniczony.

    kamyczek napisał:
    Zastanów się też jak wpisać 10 bitową wartość przetwornika do 8 bitowego rejestru danych .

    Kod: VB.net
    Zaloguj się, aby zobaczyć kod

    To jest końcówka obliczania średniej z dwóch pomiarów (/2) i skracanie wartości o 2 bity(/4) żeby weszła w 8b rejestr. Deklarując zmienną "dowpisania" jako bajt nic się nie zmienia.
    kamyczek napisał:
    Kolejne zagadnienie ,to jak się ma czas konwersji przetwornika adc do częstotliwości wystąpienia przerwań ?

    W czasie jednej pełnej pętli głównej licznik zwiększa się o 3, więc dla najwyższej możliwej częstotliwości pętla wykona się 16 razy zanim dojdzie do przerwania, nawet zostawiając w głównej pętli wysyłanie ocr2 przez uart, gdyby wywalić tę linijkę, pewnie trwałoby to jeszcze krócej.
    kamyczek napisał:
    Ten program przestanie się wykonywać gdy czas obsługi przerwania będzie dłuższy do częstotliwości jego wystąpień .

    Czas obsługi przerwania-nie mam pojęcia ile trwa, ale nic tam nie ma, odłożenie adresu na stos, wpisanie jednej wartości do jednego rejestru i powrót, kwestia pojedynczych us(nie liczyłem, zgaduję).
  • #4 17525530
    kamyczek
    Poziom 38  
    nanab napisał:
    Równą częstotliwości jaką dostaje od prescalera. Tylko w jakim celu skoro taka sytuacja nigdy nie wystąpi? Wartość którą wyrzuca adc to 512+-320, potencjometr jest mechanicznie ograniczony.


    Jak wpiszesz wartość 512+320 do 8 bitowego rejestru ?
  • #5 17525549
    nanab
    Poziom 27  
    kamyczek napisał:

    Jak wpiszesz wartość 512+320 do 8 bitowego rejestru ?

    nanab napisał:

    Kod: vbnet [rozwiń] [zaznacz wszystko]
    Dowpisania = Last / 8

    To jest końcówka obliczania średniej z dwóch pomiarów (/2) i skracanie wartości o 2 bity(/4) żeby weszła w 8b rejestr. Deklarując zmienną "dowpisania" jako bajt nic się nie zmienia.
  • REKLAMA
  • #6 17525908
    Konto nie istnieje
    Poziom 1  
  • #7 17526457
    nanab
    Poziom 27  
    emarcus napisał:


    Nie zmienia, bo masz błąd w innym miejscu.

    Dokładnie to miałem na myśli-że błąd jest gdzieś indziej.
    emarcus napisał:
    Zastanów się, co oznacza nazwa trybu CTC (?) – w ang. jest to ‘Clear Timer on Compare’ (pol. - wyzeruj zawartość licznika/timera, gdy jego zawartość jest równa wyznaczonej z góry i ustalonej, bądź to wyliczonej jakiejś wartości w zmiennej ‘Compare’). Zmienna ta jest umieszczona w rejestrze OCR2 (Compare2).
    Zatem (w tym trybie), zawartość licznika nigdy nie osiągnie jego maksymalnego stanu 255, momentu w którym może wystąpić interrupt OVF2 (w Bascom jest to nazwane ‘Timer2’) z tytułu przepełnienia tego licznika.
    Jeżeli chcesz wywołać przerwanie przy porównaniu zawartości TCNT2 z OCR2, to powinieneś skonfigurować przerwanie od ‘OC2’, albo w Bascom jest to ‘Compare2’, gdzie obie nazwy są akceptowane.

    OC2 zamaist timer2, ok, sprawdzę jak będę w domu.
    emarcus napisał:
    Zadeklarowanie zmiennej ‘integer’ do odczytu ADC nie jest poprawne.
    W Bascom zmienna integer może mieścić liczby zarówno ujemne jak i dodatnie: (-32768 do +32767).

    W późniejszej wersji programu ta zmienna będzie mogła przyjmować ujemne wartości.
    emarcus napisał:

    W Bascom, nie musisz nic kombinować z uśrednianiem zmiennej z dwóch pomiarów bo program już to robi za ciebie, chociaż tego w programie nie widać!

    Tzn.? Za jednym poleceniem robi kilka pomiarów? Z tego co słyszałem(i doświadczyłem w sumie) jest wręcz przeciwnie, bascom nie potrafi poprawnie dokonać normalnego pomiaru, trzeba dla pewności robić po kilka razy "getadc" jedna po drugiej, bo przy pojedynczej może podać wartość z innego wejścia albo całkiem jakieś śmieci.
    emarcus napisał:
    Aby zabezpieczyć się od zerowych odczytów z potencjometru możesz wprowadzić ograniczenie (SW) softwarowe w programie warunkiem ‘If/then’ albo HW; dodając odpowiedni rezystor pomiędzy potencjometr i GND.

    To wiem, będzie w dalszej wersji programu.
    emarcus napisał:
    Jeżeli chcesz mieć 8-bitowy odczyt z ADC (obcinając dwa dolne bity), możesz tego dokonać inna metodą:
    Ustawić bit (5) ADLAR w rejestrze ADMUX powodujący przesunięcie w lewo wyniku z konwersji ADC i odczytywać tylko górny bajt ADCH. Praktycznie podzielenie przez 4 całego odczytu ADC daje ten sam rezultat.

    Bardziej intuicyjne i przejrzyste wydało mi się właśnie dzielenie w kodzie zamiast ustawianie w rejestrach.

    Dodano po 2 [godziny] 44 [minuty]:

    Sprawdziłem- ani z on OC2 tajmer ani z on compare2 tajmer nic się nie zmienia... A właściwie jedno się zmienia-teraz wcale nie wchodzi do przerwania, przy on timer2 tajmer chociaż ten jeden raz się udawało.
  • #8 17529522
    Konto nie istnieje
    Poziom 1  
  • #9 17529639
    nanab
    Poziom 27  
    emarcus napisał:

    Bascom nie wykonuje dwóch działań arytm. lub instrukcji w jednej lini.

    Wiem to, wskaż w którym miejscu próbowałem coś takiego zrobić. Chodzi o last=last+getadc(1)? Instrukcja wykonuje się poprawnie.
    emarcus napisał:

    Wyglada że chcesz mi wmówic, że wprowadziłem cię w błąd.

    Nie, po prostu stwierdzam, że po wprowadzeniu zmian nadal nie działa tak jak bym chciał.
    emarcus napisał:
    To wyjaw jeszcze sposób 'sprawdzania' :było to na aktualnym sprzęcie(?); czy w symulatorze?

    Na sprzęcie, dla pewności na dwóch płytkach(korzystam z klona arduino nano z wstawionym atmega8a+7805 zamiast atmega328+ams1117), na obu identyczne zachowanie.

    emarcus napisał:
    Wyjaw także swój kod: (ten skorygowany wg wskazówek i nie pracujący ) , a wtedy uzyskasz korektę błędów, które z pewnością nie uważnie popełniasz./

    To kod z pierwszego postu, tylko konfiguracja przerwania jest:
    Kod: VB.net
    Zaloguj się, aby zobaczyć kod

    lub
    Kod: VB.net
    Zaloguj się, aby zobaczyć kod
  • REKLAMA
  • #10 17530832
    Konto nie istnieje
    Poziom 1  
  • #11 17531965
    nanab
    Poziom 27  
    emarcus napisał:


    No to jeszcze zmień zamiast:


    Kod: vbnet [rozwiń] [zaznacz wszystko]

    Enable Interrupts
    Enable Timer2
    Stop Timer2

    na:


    Kod: vbnet [rozwiń] [zaznacz wszystko]
    Enable Interrupts
    Enable Oc2
    albo
    'Enable Compare2 'robi to samo co linia wyzej

    Trafna uwaga, o tym zapomniałem. I to rozwiązało problem :)
    emarcus napisał:

    ‘Stop Timer2 – nie jest potrzebny bo później potrzebujesz go ponownie startowac.

    To akurat tak samo jak deklaracja zmiennej "last" jako integer-na przyszłość. W finalnej wersji programu poniżej pewnej częstotliwości timer ma być zatrzymywany. Timer ma generować sygnał dla sterownika silnika krokowego, silnik ma być sterowany z potencjometru-w połowie ma być neutrum(timer zatrzymany), silnik stoi, w skrajnych położeniach silnik kręci z max prędkością w jedną lub w drugą stronę. Dlatego też ten integer, po odjęciu offsetu z odczytanej z potencjometru wartości może wyjść wartość ujemna, wtedy zmieniam stan na "dir" sterownika silnika, a liczbę mnożę razy (-1) dla zmiany znaku i dalej przetwarzam.

    emarcus napisał:
    Dalej, instrukcja: ‘Dowpisania = Last / 8’ - zajmuje 247 cykli zegarowych, gdy tymczasem może to byc zastąpione instrukcjami:

    Kod: vbnet [rozwiń] [zaznacz wszystko]
    Shift Last , Right , 3
    Dowpisania = Last

    Co w efekcie zajmuje odpowiednio 34 i 38 cykli zegarowych. Czas tej ostatniej instrukcji obejmuje również konversję 2 bajtowej zmiennej ‘Last’ na zmienną 8-bitową. Zwykłe przypisanie wartości do zmiennej 'kosztuje' 2 do kilka cykli.

    O tym nie miałem pojęcia, myślałem że to dokładnie to samo polecenie tylko pod innymi literkami, magia bascoma :)
REKLAMA