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

[ATmega8] [Bascom] licznik T0

magik128 21 Gru 2008 20:44 3028 11
  • #1 5887262
    magik128
    Poziom 22  
    Witam

    Mam problem ze zmuszeniem licznika T0 w bascomie do pracy z częstotliwością większą niż 25kHz.

    
    $regfile="m8def.dat"
    $crystal="8000000"
    
    Config portd.0= output
    Config timer0=timer,prescaler=1
    Enable interrupts
    enable timer0
    start timer0
    
    on timer0 nosna
    
    do
    loop
    end
    
    nosna:
    load timer0,1
    toggle portd.0
    return
    

    Program napisany z pamięci więc mogą być literówki.Problem w tym że zmiana parametru prescaler nic nie zmienia poniżej wartości 64. Czy liczniki mają jakąś częstotliwość graniczną?

    Pozdrawiam
  • #3 5887731
    magik128
    Poziom 22  
    Cytat:
    Częstotliwość zależy od zegara, preskalera oraz wartości wpisanej do timera.

    Po za tym błędy: Kod:

    $crystal="8000000"
    load timer0,1


    Błędem jest deklaracja częstotliwości zegara,czy ładowanie wartości 255 do timera0? Wiem jak działają liczniki w AVR ,wiem także od czego zależy częstotliwość. Wytłumacz mi tylko dlaczego przy zegarze 8MHz ,preskalerze 1 oraz ładowaniu licznika do 255 (czyli praktycznie przerwanie występuje po jednym takcie zegara) częstotliwość zmian stanu na PD.0 jest około 25kHz?
  • #4 5887768
    dawid512
    Poziom 32  
    Przerwanie następuje dokładnie po 0,1200µs pod warunkiem że masz na prawdę 8MHz i ładujesz do licznika 255. Co do poprzedniego postu:
    $crystal = 8000000 
    counter0=255
    Widzisz różnicę? Mam nadzieje że przestawiłeś fuse bity jak trzeba.
  • #5 5887831
    K_o_n_r_a_d
    Poziom 23  
    Jeśli chcesz generować konkretną częstotliwość to wykorzystaj do tego tryb COMPARE timera:
    Config Timer1 = Timer , Prescale = 1 , Compare A = Toggle , Clear Timer = 1
    Częstotliwość wtedy zmieniasz wpisując odpowiednią wartość do rejestru Compare1a lub Pwm1a (ten sam rejestr - nie ma znaczenia który). W ten sposób nie obciążasz uK przerwaniami a przebieg prostokątny jest generowany całkowicie sprzętowo.
  • #6 5887929
    magik128
    Poziom 22  
    Tamten program napisałem z pamięci,bo korzystałem z komputera na którym nie mam bascoma.

    $regfile = "m8def.dat"
    $crystal = 8000000
    
    Config Portd.0 = Output
    Config Timer0 = Timer , Prescale = 1
    Enable Interrupts
    Enable Timer0
    Start Timer0
    
    On Timer0 Nosna
    
    Do
    Loop
    
    
    
    Nosna:
    Counter0 = 255
    Portd.0 = Not Portd.0
    
    Return


    Fusbity ok ,praca na kwarcu zew 8Mhz.

    [ATmega8] [Bascom] licznik T0

    Tak wygląda efekt pracy mikrokontrolera (podstawa czasu ustawiona na 10us)

    Problem w tym że czy mam prescale=1 czy 8 to i tak jest jedno licho.

    ------------------------------------------------------------------------------------

    Sposób podany przez kolego Konrada działa bez zarzutu.Ale nadal mnie intryguje co mi nie wychodzi z tym Timer0 .
  • #7 5888118
    mirekk36
    Poziom 42  
    Rozumiem, że za pomocą tej swojej pierwszej metody chciałbyś uzyskać bardzo wysoką częstotliwość, ale nie bierzesz w tym przypadku pod uwagę, że takie programowe generowanie nośnej dosyć istotnie różni się od sprzętowego, o kótrym wspominał Konrad co sam już zauważyłeś. Tam czuwa sprzęt nad tym

    a w twoim programowym przypadku musisz wziąć pod uwagę, że w tym przerwaniu jest niewiele czasu na realizację poleceń tymczasem czy jesteś świadomy co się dzieje w tak zdefiniowanym Bascomowym przerwaniu?

    1. Odkładane są na stos wszystkie potrzebne Bascomowi rejestry (więc już strata iluś tam cyki zegara)

    2. wykonywane są polecenia , które ty napisałeś w przerwaniu , więc też strta iluś tam cykli zegara - nawiasem mówiąc nie wiem czy w tym przypadku szybciej nie wykonywałoby się polecenie Toogle

    3. zdejmowane są ze stosu wszystkie rejestry - i znowu zjedzone masz sporo cykli zegara jak na tak krótkie przerwanie

    .... co można z tym zrobić?

    1. W tym testowym przypadku, skoro w pętli głównej nic nie robisz i dasz do definicji procedury przerwania parametr NOSAVE - to Bascom w ogóle nie odłoży i nie zdejmie rejestrów na i ze stosu - przez co już zaoszczędzisz trochę czasu i twój oscylogram już powinien się od tego nieco zmienić

    2. obsługę przerwania w timerze - pisać w asemblerze - jak najkrócej - i znowu będzie lepiej.

    .... ale i tak zawsze przy tak krytycznie czasowej procedurze musisz sobie liczyć ile cykli zajmą ci wszystkie polecenia w przerwaniu aby się upewnić czy przypadkiem nie będzie się ono wykonywało za długo i czy kolejne nie będą "opuszczane" tzn odkładane na później
  • #8 5888130
    K_o_n_r_a_d
    Poziom 23  
    Odpowiedz wydaje mi się być prosta: do licznika timera wpisujesz 255 a więc 1 takt zegara po tym rozkazie następuje przepełnienie i wywołanie przerwania. Wtedy program jeszcze będzie wykonywał podprogram obsługi przerwania, więc się nie wywoła ponowne przerwania a zostanie ono odłożone do czasu zakończenia aktualnego. Najwidoczniej pomiędzy wpisaniem do licznika timera a wyjściem z przerwania + jeszcze wejściem do następnego przerwania mija więcej niż 8 cykli zegara dlatego taki sam efekt jest przy preskalerze 8.

    Dodano po 4 [minuty]:

    Dodaj jeszcze kilka poleceń w podprogramie obsługi przerwania a i przy prescalerze 64 będziesz miał ten sam efekt.

    Spóźniłem się o 2 minuty :)
  • #9 5888175
    magik128
    Poziom 22  
    tak właśnie podejrzewałem że bascom nie lubi operacji z dokładnym czasem.Zmiana polecenia z Toggle na not nic nie zmienia.Pozostanie przy sprzętowej generacji.Mam tylko jeszcze jedno pytanie,bo fala którą generuje to będzie nośna dla pilota SIRC.I teraz przy włączaniu i wyłączaniu T1 raz zostaje stan wysoki ,a raz niski na PB1. Na razie załatwiłem to w ten sposób ,ale może znacie coś bardziej eleganckiego żeby wyłączać timer , a końcówka zostawała w stanie wysokim?

    
    $regfile = "m8def.dat"
    $crystal = 8000000
    
    Config Pinb.1 = Output
    
    
      Compare1a = 105
    
    
    Do
    Gosub Nosna_start
    
    Loop
    
    
    
    Nosna_start:
    Config Timer1 = Timer , Prescale = 1 , Compare A = Toggle , Clear Timer = 1
    Start Timer1
    Return
    
    Nosna_stop:
    Stop Timer1
    
    Config Timer1 = Timer , Prescale = 1 , Compare A = Set , Clear Timer = 1
    Start Timer1
    
    Return
    
  • #10 5888261
    mirekk36
    Poziom 42  
    magik128 napisał:
    tak właśnie podejrzewałem że bascom nie lubi operacji z dokładnym czasem.

    nie opowiadaj bajek i własnych teorii wyssanych z palca ;) to zależy od programisty a podobna sytuacja może ci się zdażyć pisząc tego typu kod w każdym języku. Trzeba poprostu wiedzieć co dany kompilator robi, inaczej mówiąc jaki kod w asm generuje.

    magik128 napisał:
    Mam tylko jeszcze jedno pytanie,bo fala którą generuje to będzie nośna dla pilota SIRC.

    ludzie - to po co ci aż takie wysokie nośne - jakie próbowałeś uzyskać ;) przy obsłudze dowolnego standardu IR nie ma aż tak wysokich częstotliwości, co nie zmienia faktu, że najlepiej do tego wykorzystywać i tak sprzętową generację bo po to ona jest

    magik128 napisał:
    może znacie coś bardziej eleganckiego żeby wyłączać timer , a końcówka zostawała w stanie wysokim?

    każdy sposób jest dobry ten twój też ;)
  • #11 5888303
    K_o_n_r_a_d
    Poziom 23  
    magik128 napisał:
    tak właśnie podejrzewałem że bascom nie lubi operacji z dokładnym czasem.
    Bascom (nie) lubi operacji precyzyjnych czasowo tak samo jak i każdy inny język. Wpisując do rejestru licznika 8bitowego wartość 255 i preskaler 1 lub 8 to nawet w asemblerze będziesz miał taki sam efekt.
  • #12 5888304
    magik128
    Poziom 22  
    Tak wysokie nośne nie są mi potrzebne,ale zauważyłem problem i chciałem się dowiedzieć gdzie leży jego przyczyna.Co do operacji o sztywnych czasach ,to i tak uważam że bascom nie jest do tego idealny,ale wcale nie twierdzę że nie da sie w nim tego zrobić:)

    Pozdrawiam
REKLAMA