Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Miernik częstotliwości na ATmega8

15 Sie 2007 14:19 10257 26
  • Poziom 39  
    Witam! Mam taki kod z tego tematu https://www.elektroda.pl/rtvforum/viewtopic.ph...ega8&sid=2db825ab9fddbc3d39e8136a4f077ae9 delikatnie przerobiony.
    Code:
    $crystal = 12000000
    
    Cursor Off
    Config Portc.4 = 1
    Config Portc.0 = 0
    Portc.0 = 1
    Portc.4 = 1
    Dim Czestotliwosc As Long

    Const Licznik = 22336
    Config Timer1 = Timer , Prescale = 256
    Config Timer0 = Counter , Edge = Falling

    Deflcdchar 1 , 2 , 4 , 14 , 16 , 16 , 17 , 14 , 32          ' replace ? with number (0-7)
    Deflcdchar 0 , 2 , 4 , 14 , 16 , 14 , 1 , 30 , 32
    Deflcdchar 2 , 32 , 32 , 14 , 17 , 31 , 16 , 14 , 4         ' replace ? with number (0-7)

    On Timer1 Czas
    On Timer0 Zlicz
    Kasuj Alias Portc.4
    Mnoznik Alias Pinc.0
    Cls
    Lcd "    MIERNIK"
    Lowerline
    Lcd " CZESTOTLIWOSCI"
    Wait 1
    Cls
    Enable Interrupts
    Enable Timer1
    Enable Timer0                                               'Pomiar czasu
    Counter1 = Licznik

    Do
    Set Kasuj
    Loop
    End

    Czas:
       Stop Timer0
       Stop Timer1
       Czestotliwosc = Czestotliwosc * 256
       Czestotliwosc = Czestotliwosc + Counter0
       If Mnoznik = 0 Then
       Czestotliwosc = Czestotliwosc * 4
       Else
       Czestotliwosc = Czestotliwosc * 40
       End If
       Locate 1 , 2 : Lcd "Cz" ; Chr(2) ; "stotliwo" ; Chr(0) ; Chr(1)
       If Czestotliwosc < 1000 Then Gosub Wyswietl_hz
       If Czestotliwosc >= 1000 And Czestotliwosc < 1000000 Then Gosub Wyswietl_khz
       If Czestotliwosc >= 1000000 Then Gosub Wyswietl_mhz
       Reset Kasuj : Waitms 2 : Set Kasuj                       'Kasuj przerzutniki
          Czestotliwosc = 0
          Counter0 = 0
          Counter1 = Licznik
       Start Timer0
       Start Timer1

    Return

    Zlicz:
    Incr Czestotliwosc
    Return

    Wyswietl_hz:

    Locate 2 , 2
    Lcd "    " ; Czestotliwosc ; "     "
    Locate 2 , 9 : Lcd " Hz     "
    Return

    Wyswietl_khz:

    Locate 2 , 3
    Lcd " " ; Czestotliwosc ; "       "
    Czestotliwosc = Czestotliwosc \ 1000
    Locate 2 , 2
    Lcd " " ; Czestotliwosc ; "."
    Locate 2 , 11 : Lcd " kHz   "
    Return

    Wyswietl_mhz:

    Locate 2 , 3
    Lcd Czestotliwosc ; "       "
    Czestotliwosc = Czestotliwosc \ 1000000
    Locate 2 , 2
    Lcd Czestotliwosc ; "."
    Locate 2 , 11 : Lcd " MHz  "
    Return

    Efekt taki że po właczeniu wszystko niby jest ok, zapala się miernik częstotliwości, potem częstotliwość i 840 HZ i się za chwile zeruje...ale co dalej? gdzie dopiąć się na wejście? ja sobie zmieniłem 2 porty PC4 i PC0 bo tak mi pasuje, i przerobiłem go z ATtiny2313 ale to chyba nie problem. Podpowiedzcie gdzie się wpiąć z częstotliwością analizując kod. Pozdrawiam
  • Pomocny post
    Poziom 17  
    chyba masz podpiąć impulsy do PD.4. Bo zliczający impulsy masz ustawiony Timer0. Ja to mówię dla ATmegi8 bo nie podałes jaki procek masz u siebie założony.

    Dodano po 55 [sekundy]:

    tylko nie zapomnij dać w $regfile="m8def.dat" bo kompilator nie wie dla jakiego procka pisałeś.
  • Pomocny post
    Poziom 17  
    tylko że do PC.4 nie możesz. Musi być pod PD.4. Bo to jest wejście impulsów zewnętrznych dla Timer0
  • Pomocny post
    Poziom 17  
    a dla jakiego procka to napisałes??
  • Pomocny post
    Poziom 17  
    a ustawiłeś Fuse Bity?? Bo jeśli nie masz ustawionych to ATmega pracuje z częstotliwością 1MHz. Musisz ustawić Fusy na albo 8MHz na wewnętrznym generatorze albo ustawić Fusy na zewnętrzny kwarc.

    i mniej więcej kod by tak wyglądał:
    Code:
    $regfile = "m8def.dat"
    
    $crystal = 8000000
    Cursor Off
    Dim Czestotliwosc As Long

    Const Licznik = 22336
    Config Timer1 = Timer , Prescale = 256
    Config Timer0 = Counter , Edge = Falling
    Config Lcd = 16 * 2
    Config Lcdpin = Pin , Db4 = Portc.3 , Db5 = Portc.2 , Db6 = Portc.1 , Db7 = Portc.0 , E = Portc.4 , Rs = Portc.5

    Deflcdchar 1 , 2 , 4 , 14 , 16 , 16 , 17 , 14 , 32          ' replace ? with number (0-7)
    Deflcdchar 0 , 2 , 4 , 14 , 16 , 14 , 1 , 30 , 32
    Deflcdchar 2 , 32 , 32 , 14 , 17 , 31 , 16 , 14 , 4         ' replace ? with number (0-7)

    On Timer1 Czas
    On Timer0 Zlicz
    Kasuj Alias Portc.4
    Mnoznik Alias Pinc.0
    Cls
    Lcd "    MIERNIK"
    Lowerline
    Lcd " CZESTOTLIWOSCI"
    Wait 1
    Cls
    Enable Interrupts
    Enable Timer1
    Enable Timer0                                               'Pomiar czasu
    Counter1 = Licznik

    Do
    Set Kasuj
    Loop
    End

    Czas:
       Stop Timer0
       Stop Timer1
       Czestotliwosc = Czestotliwosc * 256
       Czestotliwosc = Czestotliwosc + Counter0
       If Mnoznik = 0 Then
       Czestotliwosc = Czestotliwosc * 4
       Else
       Czestotliwosc = Czestotliwosc * 40
       End If
       Locate 1 , 2 : Lcd "Cz" ; Chr(2) ; "stotliwo" ; Chr(0) ; Chr(1)
       If Czestotliwosc < 1000 Then Gosub Wyswietl_hz
       If Czestotliwosc >= 1000 And Czestotliwosc < 1000000 Then Gosub Wyswietl_khz
       If Czestotliwosc >= 1000000 Then Gosub Wyswietl_mhz
       Reset Kasuj : Waitms 2 : Set Kasuj                       'Kasuj przerzutniki
          Czestotliwosc = 0
          Counter0 = 0
          Counter1 = Licznik
       Start Timer0
       Start Timer1

    Return

    Zlicz:
    Incr Czestotliwosc
    Return

    Wyswietl_hz:

    Locate 2 , 2
    Lcd "    " ; Czestotliwosc ; "     "
    Locate 2 , 9 : Lcd " Hz     "
    Return

    Wyswietl_khz:

    Locate 2 , 3
    Lcd " " ; Czestotliwosc ; "       "
    Czestotliwosc = Czestotliwosc \ 1000
    Locate 2 , 2
    Lcd " " ; Czestotliwosc ; "."
    Locate 2 , 11 : Lcd " kHz   "
    Return

    Wyswietl_mhz:

    Locate 2 , 3
    Lcd Czestotliwosc ; "       "
    Czestotliwosc = Czestotliwosc \ 1000000
    Locate 2 , 2
    Lcd Czestotliwosc ; "."
    Locate 2 , 11 : Lcd " MHz  "
    Return



    LCD jest pod Port C podpięty

    Dodano po 14 [minuty]:

    był mały bład w kodzie. Już go poprawiłem
  • Poziom 39  
    A więc tak, kwarc u mnie to 12MHz zewnętrzny więc usunąłem Twoją część, fusebity ustawione, wyświetlacz z PD4 przeniesiony na PD2 i od tego momentu po dotknięciu palcem wejścia wyświetlacz wskazuje 1,840 KHz ale to nie zawsze, często też 80 Hz, albo też 480Hz....podłączenie do komputera i zmienianiu częstotliwości, na wyświetlaczu pozostaje 0 Hz...więc coś już ruszyło ale nie do końca.
  • Pomocny post
    Poziom 17  
    ja po skonfigurowaniu u sibie Timera2 jako PWM i podłączeniu do niego tego miernika to mierzy bez problemu. Tak samo jak zrobi się w pętli Set i Reset jakiegoś portu to też mierzy częstotliwość przełączania.
  • Poziom 39  
    No to niewiem, w tym momęcie się poddaje, zweryfikuj to co mówię:
    podłączam sygnał do PD4
    drugi koniec na mase układu
    powinno działać z tym kodem co jest powyżej tak? jest tam takie coś Kasuj Alias Portc.4
    Mnoznik Alias Pinc.0 co to ma robić w tym momęcie z tym PC4?
  • Pomocny post
    Poziom 17  
    aaa nie zauważyłem tego. To są przyciski. Podłączone do tego.
    Weź zmień te przyciski na jakiś inny port. Np daj na PB.0 i PB.1

    Dodano po 16 [minuty]:

    Tylko ty zrobiłeś taki sam układ jak w tym temacie co podałeś?? Czy to testujesz na jakiejś płycie testowej??
  • Pomocny post
    Poziom 17  
    Przerobiłem troche kod i teraz powinno być dobrze. Ale do jakiej częstotliwości mierzy dobrze to nie sprawdzałem.

    Sygnał podpinasz pod PD.5

    Code:
    $regfile = "m8def.dat"
    
    $crystal = 8000000
    Cursor Off
    Dim Czestotliwosc As Long
    Dim Licz_8ms As Byte
    Config Timer0 = Timer , Prescale = 256
    Config Timer1 = Counter , Edge = Falling
    Config Lcd = 16 * 2
    Config Lcdpin = Pin , Db4 = Portc.0 , Db5 = Portc.1 , Db6 = Portc.2 , Db7 = Portc.3 , E = Portc.4 , Rs = Portc.5
    Deflcdchar 1 , 2 , 4 , 14 , 16 , 16 , 17 , 14 , 32          ' replace ? with number (0-7)
    Deflcdchar 0 , 2 , 4 , 14 , 16 , 14 , 1 , 30 , 32
    Deflcdchar 2 , 32 , 32 , 14 , 17 , 31 , 16 , 14 , 4         ' replace ? with number (0-7)
    On Timer0 Czas
    On Timer1 Zlicz
    Cls
    Lcd "    MIERNIK"
    Lowerline
    Lcd " CZESTOTLIWOSCI"
    Wait 1
    Cls
    Enable Interrupts
    Enable Timer0
    Enable Timer1
    Declare Sub Licz_cze                                        'Pomiar czasu
    Do
    Loop
    End

    Czas:
    Load Timer0 = 250
    Incr Licz_8ms
    If Licz_8ms = 125 Then
       Licz_8ms = 0
       Stop Timer1
       Gosub Licz_cze
       Start Timer1
    End If
    Return

    Sub Licz_cze
        Czestotliwosc = Czestotliwosc * 256
        Czestotliwosc = Czestotliwosc + Counter1
        Locate 1 , 2 : Lcd "Cz" ; Chr(2) ; "stotliwo" ; Chr(0) ; Chr(1)
        If Czestotliwosc < 1000 Then Gosub Wyswietl_hz
        If Czestotliwosc >= 1000 And Czestotliwosc < 1000000 Then Gosub Wyswietl_khz
        If Czestotliwosc >= 1000000 Then Gosub Wyswietl_mhz
        Czestotliwosc = 0
        Counter1 = 0
    End Sub

    Zlicz:
    Incr Czestotliwosc
    Return

    Wyswietl_hz:

    Locate 2 , 2
    Lcd "    " ; Czestotliwosc ; "     "
    Locate 2 , 9 : Lcd " Hz     "
    Return

    Wyswietl_khz:

    Locate 2 , 3
    Lcd " " ; Czestotliwosc ; "       "
    Czestotliwosc = Czestotliwosc \ 1000
    Locate 2 , 2
    Lcd " " ; Czestotliwosc ; "."
    Locate 2 , 11 : Lcd " kHz   "
    Return

    Wyswietl_mhz:

    Locate 2 , 3
    Lcd Czestotliwosc ; "       "
    Czestotliwosc = Czestotliwosc \ 1000000
    Locate 2 , 2
    Lcd Czestotliwosc ; "."
    Locate 2 , 11 : Lcd " MHz  "
    Return


    Dodano po 10 [minuty]:

    ten przyrząd mierzy wolno narastającą - opadającą częstotliwość. Bo wartość jest podawana co 1s.
  • Poziom 39  
    No dzięki bardzo! Już zaczeło być coś ok, ale jest pewien problem, zaniża o 5 kHz, podając mu z generatora wzorcowego TV, przebieg 15,625 on wyświetla mi 10,557kHz ale mysle ze dojdziemy do tego co i jak. Pozdrawiam i dziękuje!

    Dodano po 15 [minuty]:

    To był mój błąd, zmniejszyłem rezonator do 8MHz i pokazuje to co trzeba. Narazie nie zamykam. Dziękuje.
  • Pomocny post
    Poziom 34  
    Widzę, że moje programy znajdują uznanie i dobrze.
    Co do podawania impulsów na uC to nie można zmieniać dowolnie końcówek bo timery mają wejścia przypisane do konkretnych wyprowadzeń. Dla M8 są to T1 - 11, T0 - 6. Trzeba to brać pod uwagę przy projektowaniu układu. Dotyczy to końcówek używanych jako alternatywne.
    Po przeróbce czas odmierza T0 (8bit) a impulsy liczy T1 (16bit). Teraz oba timery zgłaszają przerwania. Poprzednio T1 odmierzał bez przerwania pośredniego całą sekundę i dla tego został wytypowany do pomiaru czasu
  • Poziom 39  
    Jako że miernik działał ok ale po wielu próbach port z timerem 1 odmówił posłuszeństwa, to mam pytanie czy da się ten program powyżej przerobić tak by mierzył timer 0 czyli pin 6 Atmegi8? Moje próby zmiany programu skonczyły się niepowodzeniem.
  • Pomocny post
    Poziom 34  
    Pierwszy podany program liczy impulsy timerem0.
    Aby miernik działał poprawnie należy dobrać wartość Const Licznik = 22336 do częstotliwości taktowania.
    W mierniku był zastosowany stały dzielnik przez 4 i dołączany przez 10. Stąd też następujące instrukcje

    Code:
    If Mnoznik = 0 Then
    
       Czestotliwosc = Czestotliwosc * 4
       Else
       Czestotliwosc = Czestotliwosc * 40
    End If


    które należałoby usunąć.
  • Poziom 39  
    Tak też zrobiłem. Kod wygląda tak
    Code:
    $regfile = "m8def.dat"
    
    $crystal = 8000000
    Cursor Off

    Dim Czestotliwosc As Long

    Const Licznik = 22336
    Config Timer1 = Timer , Prescale = 256
    Config Timer0 = Counter , Edge = Falling

    Deflcdchar 1 , 2 , 4 , 14 , 16 , 16 , 17 , 14 , 32          ' replace ? with number (0-7)
    Deflcdchar 0 , 2 , 4 , 14 , 16 , 14 , 1 , 30 , 32
    Deflcdchar 2 , 32 , 32 , 14 , 17 , 31 , 16 , 14 , 4         ' replace ? with number (0-7)

    On Timer1 Czas
    On Timer0 Zlicz
    Kasuj Alias Portc.4
    Mnoznik Alias Pinc.0
    Cls
    Lcd "    MIERNIK"
    Lowerline
    Lcd " CZESTOTLIWOSCI"
    Wait 1
    Cls
    Enable Interrupts
    Enable Timer1
    Enable Timer0                                               'Pomiar czasu
    Counter1 = Licznik

    Do
    Set Kasuj
    Loop
    End

    Czas:
       Stop Timer0
       Stop Timer1
       Czestotliwosc = Czestotliwosc * 256
       Czestotliwosc = Czestotliwosc + Counter0

       Locate 1 , 2 : Lcd "Cz" ; Chr(2) ; "stotliwo" ; Chr(0) ; Chr(1)
       If Czestotliwosc < 1000 Then Gosub Wyswietl_hz
       If Czestotliwosc >= 1000 And Czestotliwosc < 1000000 Then Gosub Wyswietl_khz
       If Czestotliwosc >= 1000000 Then Gosub Wyswietl_mhz
       Reset Kasuj : Waitms 2 : Set Kasuj                       'Kasuj przerzutniki
          Czestotliwosc = 0
          Counter0 = 0
          Counter1 = Licznik
       Start Timer0
       Start Timer1

    Return

    Zlicz:
    Incr Czestotliwosc
    Return

    Wyswietl_hz:

    Locate 2 , 2
    Lcd "    " ; Czestotliwosc ; "     "
    Locate 2 , 9 : Lcd " Hz     "
    Return

    Wyswietl_khz:

    Locate 2 , 3
    Lcd " " ; Czestotliwosc ; "       "
    Czestotliwosc = Czestotliwosc \ 1000
    Locate 2 , 2
    Lcd " " ; Czestotliwosc ; "."
    Locate 2 , 11 : Lcd " kHz   "
    Return

    Wyswietl_mhz:

    Locate 2 , 3
    Lcd Czestotliwosc ; "       "
    Czestotliwosc = Czestotliwosc \ 1000000
    Locate 2 , 2
    Lcd Czestotliwosc ; "."
    Locate 2 , 11 : Lcd " MHz  "
    Return
    i podając mu sygnał 15,625kHz wyświetla mi 20,960kHz...coś jest nie tak jeszcze, proszę o zweryfikowanie kodu.
  • Pomocny post
    Poziom 34  
    Jaki masz kwarc?
  • Pomocny post
    Poziom 34  
    Jak chcesz mieć miernik częstotliwości z prawdziwego zdarzenia to podłącz kwarc. To za pomocą niego uC odmierza 1s, w której zlicza impulsy. Im "sekunda" ta jest dokładniejsza tym lepszy miernik. Generator wewnętrzny nie jest dokładny, a ponadto częstotliwość jego nie jest stała.
    Inną kwestią jest kształt mierzonego przebiegu. UC jest układem cyfrowym więc lubi przebiegi prostokątne.

  • Poziom 29  
    pamietajcie jeszcze, ze czesto wymaga cpu by sygnal mial okreslona wartosc ... a tu przyda sie bufor na fet-cie :-)

    pozdro
    Marek
  • Poziom 30  
    Też kiedyś robiłem układ, gdzie musiałem mierzyć częstotliwość sygnału. Zrobiłem na ATiny2313. Na początku taktowałem wewnętrznym generatorem, z okresem zliczania około 1/3 sekundy (nie chodziło mi o konkretne wartości częstotliwości, lecz o pewne zależności), przebieg o częstotliwości około 400kHz. No i się dziwiłem, że mam strasznie niestabilną tą częstotliwość mierzoną. Po zmianie na kwarc zewnętrzny częstotliwość mierzona jest poprawnie i nie szaleje. Także jeśli robisz miernik częstotliwości, to musisz taktować procesor zewnętrznym zegarem odniesienia, bo inaczej nic z tego nie wyjdzie...
  • Poziom 11  
    a jak obliczyć wartość "licznik" w zależności od kwarcu? i po co jest linia "Czestotliwosc = czestotliwosc + Counter0"?
  • Poziom 34  
    Do obliczania wpisu do timera bez wdawania sie w "teorię" służy dostępny w sieci kalk.exe.
    Na Timerze0 zliczane są impulsy z zewnątrz w czasie 1 s. Niestety Timer0 może zliczyć tylko 256 impulsów, a częstotliwość np. to 8MHz czyli 8000000. Musimy zliczyć zatem ilość przerwań od timera, pomnożyć to przez 256 i dodać resztkę, która została zliczona ale nie przepełniła Timera.
    Stąd
    Czestotliwosc = czestotliwosc + Counter0
  • Poziom 15  
    Odnośnie częstotliwości, ja mam problem może nie tyle z programem ile z napięciami - chę mierzyć impulsy z cewki zapłonowej lub z wejść tuż przy zegarze - moje pytanie jest następujące: czy nie uszkodze mikroprocesora czy musze zastosować dzielnik rezystorowy no i czy taki dzielnik nie wpłynie na wynik pomiaru? Z góry dziękuję z aodpowiedź.
    Pozdrawiam