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

[atmega8][BASCOM] timer1, błąd odczytu?

Tajoka 07 Lut 2012 23:56 1934 2
  • #1 10512152
    Tajoka
    Poziom 20  
    Witam. Dawno nie pisałem w BASCOM-ie a zdecydowałem się na niego bo myślałem, że tak będzie szybciej i prościej. Nic bardziej błędnego. Do napisania był dwu-trybowy program uśredniający do nieco przerobionego radiometru SOSNA. Ale nie w tym rzecz. O ile kod który zamieszczam powstał w miarę szybko o tyle błędu nie potrafię wyeliminować 3 dzień. Po krótce...program ma co 4 sekundy uzupełniać bufor kołowy (tablica 10 lub 100 elementowa w zależności od trybu) wykonywać odpowiednie przeliczenia i zapisywać do zatrzasków CD4056 sterujących wyświetlacz LCD 4 znakowy. W pewnym etapie programu tryb pierwszy (10 elementów) działał poprawnie, pod dopisaniu dalszej części zaczął szwankować. Docelowo licznik ma zliczać impulsy pochodzące z 2 tub Geigera, do testów jest podłączony do generatora na DDS-ie. Do częstotliwości 63Hz wynik jest obliczany prawidłowo, stabilizuje się na około 12,60. Powyżej od 64Hz w górę....magia....wynik zaczyna rosnąć, zamiast ustabilizować się na poziomie ~12,80 wskakuje 12,80, 19,60 po kolejnych 4 sekundach ~25 po następnych i tak rośnie do 99,99 kiedy to buzer sygnalizuje przepełnienie. Myślałem nad konfliktem zmiennych ale Word dla tablicy i Long dla wyniku są wystarczające. Ich zmiany nic nie poprawiają. Wyłączałem też przerwania na czas obliczeń, bez skutku. Co mogę od razu nasunąć....wynik psuje się gdy Timer1 ma "użyteczny" wynik na dwóch bajtach (64imp/s * 4s > 255), póki wynik można odczytać z jednego bajtu wszystko jest ok, nie wiem czy to ma jakiś związek. Proszę o porady.
    Zamieszczam cały kod programu:

    Kod: text
    Zaloguj się, aby zobaczyć kod
    [/code]
  • Pomocny post
    #2 10552624
    WOBI
    Poziom 19  
    To nie Bascom jest przyczyną tylko źle napisany program ;).

    1. odczyt timera1 16bit odbywa się po przez rejestr pomocniczy TEMP, ten rejestr jest też używany przez inne procedury i funkcje i jeśli jest użyty to właśnie niszczona jest wartość High timer1 bo ona tam jest wpisana gdy używasz komendy.

    wpisując tak timer1 do tablicy możesz gubić High timer1.

    Probki_0(okno_0) = Timer1 'zapis próbek do tablicy
    Load Timer1 , 0
    


    Powinieneś użyć pomocniczej zmiennej Word i tak powinna wygladac obsługa timera1

    
    Dim Wartosc_timer as Word
    
    Atimer = timer1
    
    Probki_0(okno_0) = Wartosc_timer 'zapis próbek do tablicy
    
    timer1 = 0
    


    2. źle wpisujesz do timera1 wartość 0 rozkaz Load Timer1 = 0 działa inaczej niż Timer1 = 0
    Cytat:
    Instrukcja powoduje wpisanie do licznika określonej liczby zliczanych impulsów. Przed załadowaniem wartości do licznika, instrukcja dokonuje niezbędnego przeliczenia w postaci: 256-wartość. Tak więc instrukcja:

    Load Timer0, 10

    spowoduje, że do licznika trafi liczba 246, więc licznik przepełni się właśnie po 10 impulsach.


    Licznik TIMER1 jest 16 bitowy więc, przeliczenie jest wykonywane w postaci 65536-wartość.


    3. Nie masz obsługi przepełnienia timera1, a używając go jako licznika jeśli się przepełni, przy dużej liczbie impulsów powinieneś do tablicy wpisać maksymalną wartość, to ważna kwestia by program działał poprawnie.
    Wpisując Load Timer1 = 0 pierwszy impuls powoduje już przepełnienie licznika (bity OV timer są ustawione) i tylko dlatego że nie używasz przerwania od przepełnienia timera1 to program działa poprawnie, ale... to nie jest prawidłowy algorytm.

    Przed odczytaniem Timera1 powinieneś sprawdzić czy bit przepełnienia Timera1 Bit 2 – TOV1: Timer/Counter1, Overflow Flag nie wskazuje przepełnienia i jak wystąpiło przepełnienie to wpisać do tablicy FFFFhex, a jeśli nie nastąpiło przepełnienie to do tablicy załadować wartość zliczoną Timerem1 i wpisać 0 do Timera1 by liczył od nowa i...

    Teraz bardzo ważne zawsze na końcu wyzerować bit przepełnienia(wpisać jeden, Alternatively, TOV1 can be cleared by writing a logic one to its bit location.), bo mogło nastąpić przepełnienie w trakcie trwania tych czynności i następny odczyt może być źle zinterpretowany.

    tak powinno wyglądac poprawnie napisane

      
    Dim wartosc_timer as Word
    .
    .
    .
    
    Wartosc_timer = Timer1
    
      If Tifr.2 = 1 Then
    
          Wartosc_timer = &HFFFF
    
      end If
    
          Probki_0(okno_0) = Wartosc_timer       'zapis próbek do tablicy
    
        Timer1 = 0
    
         Tifr.2 = 1                              ' zerujemy flage przepelnienia timera1
    .
    .
    .
    


    Sam widzisz że pisanie prawidłowych algorytmów to sprawa prawidłowego i logicznego myślenia ;) a nie jezyka... prosze nie narzekać na Bascom i nie powielać stereotypów... :)

    Sprawdz ten program powinien działać
  • #3 10553197
    Tajoka
    Poziom 20  
    Dziękuję za tak wyczerpującą odpowiedź. Akurat wczoraj czytając help-a do Bascoma wpadłem na podobny wniosek. Kiedyś używałem Load timer1 do timera jako timera i wszystko śmigało, teraz zastosowałem zerowanie Counter1=0 i wszystko działa jak należy. Jeszcze raz dziękuję za obszerną odpowiedź i pozdrawiam.


    Temat można zamknąć.
REKLAMA