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

ATmega32 - rzeczywista częstotliwość kwarcu i czas wykonania programu

cys_ek 12 Sie 2007 23:04 1161 6
REKLAMA
  • #1 4172305
    cys_ek
    Poziom 10  
    Posty: 60
    Pomógł: 1
    cześć, zna ktoś z Was dokładną wartość 'podswatowego' kwarcu w ATmaga32? Ponieważ wyliczyłem (chyba że źle policzyłem,dlatego pokazuje algorytmy) ile cykli musi minąć żeby odczekać sekundę, ale nawet na oko to trwa więcej niż minute, a nie mam oscyloskopu żeby sprawdzić :(

    Cytat:
    sekunda:

    petla1:
    inc r17 ; 1 takt

    petla2:
    inc r18 ; 1 takt

    sto_u:
    inc r19 ; 1 takt
    cpi r19,32 ; 1 takt
    brne sto_u ; 1/2 takt
    ldi r19,0 ; 1 takt

    cpi r18,102 ; 1 takt
    brne petla2 ; 1/2 takt
    ldi r18,0 ; 1 takt

    cpi r17,98 ; 1 takt
    brne petla1 ; 1/2 takt
    ldi r17,0 ; 1 takt

    ret ; 4 takty
    w tym przypadku czas wykonania podprogramu powinno wynosic 0,999997 sekundy (jeśli brne zajmuje 1 cykl)

    i pod w Delphi w którym szukałem tego czasu
    program Project1;
    
    uses
      SysUtils,
      Dialogs;
    
    {$R *.res}
    
    var
      licznik: integer;
      licznik1,licznik2,licznik3: integer;
    
    begin
      licznik:= 0 ;
    
      for licznik1 := 1 to 98 do
      begin
        licznik := licznik + 3;
    
          for licznik2 := 1 to 102 do
          begin
            licznik := licznik + 3;
    
            for licznik3 := 1 to 32 do
            begin
              licznik := licznik + 3;
            end;
            licznik := licznik + 1;
    
          end;
          licznik := licznik + 1;
    
      end;
      licznik := licznik + 1;
    
      licznik := licznik + 4; // ret
    
      showmessage(inttostr(licznik));
    end.
  • REKLAMA
  • #2 4172352
    BoskiDialer
    Poziom 34  
    Posty: 1530
    Pomógł: 353
    Ocena: 42
    Szybkie wyliczenia i wychodzi, że ten twój kod "sekunda" trwa równo 1319868 cykli (licząc ret, ale nie licząc rcall), zakładając, że z początku r17,r18 i r19 były równe 0... kod o tyle zagmatwany, że można to zrobić na jednej pętli o wiele czytelniej i efektywniej...
  • REKLAMA
  • #3 4172920
    cys_ek
    Poziom 10  
    Posty: 60
    Pomógł: 1
    BoskiDialer napisał:
    Szybkie wyliczenia i wychodzi, że ten twój kod "sekunda" trwa równo 1319868 cykli (licząc ret, ale nie licząc rcall), zakładając, że z początku r17,r18 i r19 były równe 0... kod o tyle zagmatwany, że można to zrobić na jednej pętli o wiele czytelniej i efektywniej...
    tak rejestry miały wartość 0. A jak obliczyłeś to(ja szukałem tej liczby w delphi, i algorytm poprawnie działał, bo sprawdziłem ręcznie dla dwóch wartości)?
  • REKLAMA
  • Pomocny post
    #4 4173168
    BoskiDialer
    Poziom 34  
    Posty: 1530
    Pomógł: 353
    Ocena: 42
    Wkleje tutaj jeszcze raz ten kod, ale odpowiednio wcięty:
    sekunda: 
    	petla1: 
    	inc r17
    
    		petla2: 
    		inc r18
    
    			sto_u: 
    			inc r19
    			cpi r19,32
    			brne sto_u
    			ldi r19,0
    
    		cpi r18,102
    		brne petla2
    		ldi r18,0
    
    	cpi r17,98
    	brne petla1
    	ldi r17,0
    
    	ret

    a więc analiza od wewnątrz:
    sto_u: 
    inc r19
    cpi r19,32
    brne sto_u
    ldi r19,0

    - jeden przebieg pętli to: inc(1ck)+cpi(1ck)+brne(2ck), przy ostatnim przebiegu, gdy brne nie wykona skoku to będzie jeden cykl mniej, ale ldi=+1ck, więc pętla to 32 iteracje po 4 cykle -> 128ck
    petla2: 
    inc r18
    
    ; +128ck
    
    cpi r18,102
    brne petla2
    ldi r18,0

    - jeden przebieg: 128+4, ostatni przebieg cykl mniej na skoku, jedno ldi czyli cykl więcej, całość trwa (128+4)*102 = 13464 (ck)
    petla1: 
    inc r17
    
    ; +13464 ck
    
    cpi r17,98
    brne petla1
    ldi r17,0
    

    - (13464+4)*98 = 1319864ck
    No i jeszcze ret...
  • REKLAMA
  • #5 4173389
    myrcioch
    Poziom 18  
    Posty: 150
    Pomógł: 30
    Ocena: 5
    ...i do tego wszystkiego trzeba jeszcze zablokować przerwania, bo obliczenia się rozjadą. Do takich długich czasów w 99% przypadków używa się timerów - odpowiedni podzielnik razy licznik w przerwaniu i bez skomplikowanych obliczeń masz dokładny wynik.
  • #6 4173931
    cys_ek
    Poziom 10  
    Posty: 60
    Pomógł: 1
    Dzięki, teraz przeliczyłem jeszcze raz wszystko i źle policzyłem.

    :arrow:myrcioch
    wiem ale nie mam pojęcia jak to zrobić, mógłbym poprosic o jakiś w asemblerze? bo tylko znajduje przykłady pod bascoma albo uC
  • #7 4173949
    Ch.M.
    Poziom 27  
    Posty: 1009
    Pomógł: 62
    Ocena: 15
    Czekaj: ; ustawiam opoznienie 250ms CTC naT0 zliczam do 2000dec=07D0hex
    ; Timer1 ustawiam w trybie CTC(WGM01) z preskalerem 64(CS00, CS02) i zliczam do 2000 co daje nam 250ms
    ; OCIE01 ustawiam przerwanie
    ldi R16, 0b10
    out TCCR0A, R16
    ldi R16, 0b101
    out TCCR0B, R16 ; prescaler 1024
    ldi R16, 255
    out OCR0A, R16

    nic1:
    in R16, TIFR0
    sbrc R16, OCF0A ; czekamy na ustawienie flagi
    rjmp koniec ; jesli zostanie ustawiona to wychodzimy z petli nic1
    nop
    rjmp nic1

    koniec:


    Nie patrz na dokładny opis bo pewnie juz pozmieniałem 10razy ustawienia. generalnie program stoi w petli, dopuki nie zostanie ustawiona flaga OCF0A

    To samo mozesz zrobic na przerwaniach, ale akurat w tym programie nie chciałem do tego ich mieszac. Program pisany dla serii M88 i zapewne trzeba by pozmieniac nazwy rejestrow i poszczególne bity

Podsumowanie tematu

LABEL_AI_GENERATED
Dyskusja dotyczy dokładnej wartości częstotliwości kwarcu w mikrokontrolerze ATmega32 oraz precyzyjnego pomiaru czasu wykonania programu odliczającego sekundę. Użytkownik przedstawił algorytm w asemblerze i Delphi, który miał odmierzać 0,999997 sekundy, jednak w praktyce czas ten był znacznie dłuższy. Analiza kodu asemblerowego wykazała, że pętla odlicza około 1 319 868 cykli zegara, co odpowiada obliczeniom dla zadanej częstotliwości. Zwrócono uwagę na konieczność blokowania przerwań podczas długich opóźnień, aby uniknąć rozjechania się pomiaru czasu. Zaproponowano również użycie timerów sprzętowych z odpowiednim preskalerem i licznikami w trybie CTC (Clear Timer on Compare Match) dla uzyskania dokładnych opóźnień bez skomplikowanych obliczeń. Przykład kodu asemblerowego pokazuje konfigurację Timer0 z preskalerem 1024 i przerwaniem na ustawienie flagi OCF0A, co pozwala na precyzyjne odliczanie czasu 250 ms. Wskazano, że takie podejście jest bardziej efektywne i dokładne niż opóźnienia realizowane pętlami programowymi.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA