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

Jak skonfigurować licznik impulsów w ATmega16 w języku ASM?

marian_em 30 Mar 2008 21:27 5918 7
REKLAMA
  • #1 4974693
    marian_em
    Poziom 25  
    Posty: 843
    Pomógł: 60
    Ocena: 182
    Witam

    Próbuje napisać program, którego głównym zadaniem będzie zliczanie impulsów i oczywiście odpowiednie reakcje po przekroczeniu zadanych poziomów. Problem w tym, że nie bardzo potrafię sobie poradzić z wykorzystaniem wbudowanego licznika, na elektrodzie jest kilka tematów z tym związanych, ale nie bardzo potrafię to poskładać w całość :| Znalazłem też takie coś: http://mikrokontrolery.net/avr_asm_06.htm ale w symulacji licznik jeździ w kółko i nie ma poza tym żadnego efektu :roll: .
    Może mógłby ktoś na przykładzie (najlepiej by było w asm) wytłumaczyć jak użyć tego licznika i jak skonfigurować port?

    Druga rzecz, w programie chce mieć możliwość ustawiania progu, do którego zlicza licznik, po nim następuje określona reakcja. Obecnie zrobiłem tak, że "główna" pętla programu chodzi w kółko non stop i sprawdza stan na dwóch określonych pinów w porcie. Z tego co gdzieś wyczytałem, nie jest to najszczęśliwsze rozwiązanie i lepiej by było zrobić na przerwaniach (tylko ze na razie nie wiem jak ) , czy takie sprawdzanie w nieprzerwanej pętli może doprowadzić do jakichś niechcianych efektów np "zawieszenia" układu?
  • REKLAMA
  • #2 4974846
    GienekS
    Poziom 32  
    Posty: 1971
    Pomógł: 139
    Ocena: 15
    A może łatwiej by była funkcja porównania licznika z zadaną wartością ? Co generowało by przerwanie sygnalizujące przekroczenie ustalonej wartości ?
  • REKLAMA
  • #3 4974853
    Balu
    Poziom 38  
    Posty: 4397
    Pomógł: 323
    Ocena: 48
    Sprawdzanie w nieskończonym loopie nie zawiesi programu.
    Skonfiguruj liczniki żeby działały na Overlfow (przepełnienie) i wpisuj początkową wartość, lub na compare (porównaj) i wpisz wartość porównania do odpowiedniego rejestru.
    Skonfiguruj piny jako wejścia.
    Odblokuj przerwania od timera/ów.
    Odblokuj przerwania globalne.
    Pozdrawiam.
    Coś dokładniej? Napisz co masz, co Ci nie działa, będziemy próbować.
    P.S. Wszystko jest w datasheecie...
  • REKLAMA
  • #4 4974906
    marian_em
    Poziom 25  
    Posty: 843
    Pomógł: 60
    Ocena: 182
    Może być i porównaniem (będzie <200 impulsów) tylko powiedz jak to zrobić? Po skończeniu liczenia układ ma w jakiś sposób "dać znać" że skończył liczenie, wtedy zmieniam na chwile stan kilku pinów w porcie, licznik zostaje zresetowany i czeka na kolejne odliczanie. Takie są założenia, tylko jak już pisałem nie mogę zrozumieć działania tego portu timer/counter :roll:
  • #5 4975069
    Balu
    Poziom 38  
    Posty: 4397
    Pomógł: 323
    Ocena: 48
    tccr0
    wgm01 wgm00 zapisz 0 - praca normal
    com01, com00 <- zapisz 00 bez wyjscie Compare output
    cs02 cs01 cs00 <- 110 lub 111 fallin/risin edge
    ocr0 <- Wpisz przy jakiej wartości ma nastąpić flaga comparacji
    timsk
    ocie0 <- 1 włącz przerwanie od compare on counter0
    toie <- imo 0 - przerwanie od przepełnienia


    na początku w wektorach przerwań:
    .org 0x026
    rjmp obsluz_compare


    gdzieś tam dopisz sobie procedurę obsluz_compare i w niej

    obsluz_compare:
    co tam Sobie chcesz pozmieniać...


    reti

    i w sumie tyle.
    Pamiętaj, że musi być globalne zezwolenie na przerwania! I żeby ustawić nóżkę T0 jako wejście (rej. DDRX zapisz odpowiednio 0 na nóżce T0).



    Nie wiem czy działa, ale na pierwszy rzut oka powinno wystarczyć.

    Pozdrawiam:)
  • REKLAMA
  • #6 4975590
    marian_em
    Poziom 25  
    Posty: 843
    Pomógł: 60
    Ocena: 182
    dziękuję :) po "małych" :lol: przeróbkach program wygląda tak, wykorzystałem dwa przerwania do ustawiania licznika:
    .include "2313def.inc"
    .equ ocr0 =$3C
    .equ ddra =$1A
    .equ porta =$1B
    
    .DEF cnt = r31 
    .DEF max = r29
    .DEF man = r30
    
    .cseg
    .org 0x00
    rjmp main
    .org 0x02
    rjmp set_up
    .org 0x04
    rjmp set_down
    .org 0x026
    rjmp counter_match
    
    main:
    	sei
    	ldi man, 0xFF
    	out ddra, man ;port a jako wyjscia
    	ldi man, 0x00
    	out porta, man ;port a = 0
    	ldi man, 0x07
    	out tccr0, man ;wyzwalanie zboczem narastajacym 
    	ldi man, 0x02
    	out timsk, man ;przerwanie licznika
    	ldi max, 20
    	ldi cnt, 5
    	out ocr0, cnt
    	
    mainx:
    	ldi man, 0x00
    	sbic pinb, 2
    	out tcnt0, man ;reset licznika
    	rjmp mainx
    
    counter_match:
    	ldi man, 0x01
    	out porta, man ;zmiana stanu portu a
    	ldi man, 0x00
    	out tcnt0, man ;wyzerowanie licznika
    	;*********
    	ldi man, 0x00
    	out porta, man ;wyzerowanie portu a
    	reti
    
    
    set_up:
    	cp cnt, max
    	brlo xx
    	reti
      xx:
    	inc cnt
    	out ocr0, cnt ;aktualizacja stanu licznika++
    	reti
    
    set_down:
    	cpi cnt, 1
    	brge yy
    	reti
      yy:
    	dec cnt
    	out ocr0, cnt ;aktualizacja stanu licznika--
    	reti
    
    ;pina0 - wyjscie ukladu
    ;pinb0 - wejscie impulsatora
    ;pinb2 - reset licznika
    ;pind2 - zwiekszanie licznika
    ;pind3 - zmniejszanie licznika

    "Na sucho" niby działa ok, rzuć fachowym okiem co może ewentualnie być nie tak. W miejscu gwiazdek będzie jakaś procedura opóźniająca, chociaż i tak wymagane podtrzymanie pewnie zrobię już poza mikrokontrolerem. Chciałem wykorzystać jeszcze jedno przerwanie (int2) na reset ale nie chce działać, może trzeba jakoś je włączyć. Na razie zrobiłem w pętli głównej.
  • #7 4975612
    Balu
    Poziom 38  
    Posty: 4397
    Pomógł: 323
    Ocena: 48
    Tak, trzeba włączyć zezwolenie na to przerwanie.
    mcucsr
    isc2 <- 0 fallin edge, 1 risin edge
    gicr
    int2 <-1 włącz przerwanie.


    Wygląda w miarę ok :) Nic nie razi:)
  • #8 8901581
    hondur87
    Poziom 2  
    Posty: 2
    Ocena: 1
    Mam pytanie apropo liczenie impulsów na liczniku ATmegi. Chce podłączyć generator 10 MHz pod któryś z 16-bitowych liczników ATmegi 128 z 16MHz kwarcem. Czy nie będzie gubić impulsów i będzie liczyć w sposób prawidłowy?

Podsumowanie tematu

✨ Dyskusja dotyczy konfiguracji licznika impulsów w mikrokontrolerze ATmega16 przy użyciu języka asemblera (ASM). Głównym problemem jest prawidłowe wykorzystanie wbudowanego licznika/timera do zliczania impulsów oraz implementacja reakcji po przekroczeniu zadanej wartości progowej. Proponowane rozwiązania obejmują konfigurację trybu pracy licznika (normalny, porównawczy), ustawienie rejestrów kontrolnych (TCCR0, OCR0, TIMSK), konfigurację pinów jako wejścia oraz włączenie przerwań globalnych i od licznika. Przerwania od porównania (Compare Match) są sugerowane jako mechanizm sygnalizujący osiągnięcie progu, co pozwala na reset licznika i zmianę stanu wyjściowego portu. Przykładowy kod ASM pokazuje implementację obsługi przerwań, konfigurację portów i rejestrów oraz pętlę główną programu. Wskazano również, że sprawdzanie stanu pinów w nieskończonej pętli jest mniej efektywne niż obsługa przerwań. Dodatkowo pojawiło się pytanie o możliwość zliczania impulsów z generatora 10 MHz na 16-bitowym liczniku ATmegi128 z kwarcem 16 MHz, dotyczące potencjalnej utraty impulsów.
Wygenerowane przez model językowy.
REKLAMA