| Author |
Message
|
Lukaszek_69 Poziom 12

Joined: 01 Oct 2009 Posts: 107
|
#1
11 Mar 2010 00:04 [Attiny2313][Asm] Synchronizacja przerwań i skalowanie czasu |
|
|
|
Witam!
Zbudowałem prosty układ i chciałbym na nim nauczyć się dobrze obsługiwać i synchronizować przerwania. Jego głównym założeniem będzie liczenie co jedną sekundę do 99 na dwóch wyświetlaczach siedmiosegmentowych(obsługa "multipleksacją") z dodatkowymi opcjami(odebrać coś z komputera itp). Pisałem w C a z assemblerem dopiero zaczynam dlatego proszę o pomoc w poniższym programie:
| Code: |
.include "tn2313def.inc"
;-----definicje---------------------
.def tmp = r16
.def tmp2 = r17
;-----wektory przerwan--------------
.cseg
.org 0x00
rjmp reset
.org 0x04
rjmp timer1_compA
.org 0x0D
rjmp timer0_compA
;-----------------------------------
reset:
ldi tmp, 0x72
out DDRD, tmp
ldi tmp, 0xFF
out DDRB, tmp ;konfiguracja PORTB i PORTD
ldi tmp, 0x10
out PORTD, tmp ;wstepne ustawienie multipleksacji
ldi tmp, RAMEND
out SPL, tmp ;ustawienie stosu
ldi tmp, 0x01
out TCCR0B, tmp
out TCCR1B, tmp ;preskaler
ldi tmp, 0x41
out TIMSK, tmp ;wlaczenie przerwania compA dla obu timerow
ldi tmp, 0x06
out OCR0A, tmp ;comp0A = 6
ldi tmp, 0xD0
out OCR1AL, tmp
ldi tmp, 0x03
out OCR1AH, tmp ;comp1A = 976
sei
end:
rjmp end
;-----------------------------------
timer0_compA:
ldi tmp, 0x00
out TCNT0, tmp
in tmp, PORTD
ldi tmp2, 0x30
eor tmp, tmp2
out PORTD, tmp
reti
timer1_compA:
ldi tmp, 0x00
out TCNT1H, tmp
out TCNT1L, tmp
in tmp,PORTB
ldi tmp2, 0xFF
eor tmp, tmp2
out PORTB, tmp
reti
|
Debugowałem powyższy program i nie wiem jak poradzić sobie ze zsynchronizowaniem przerwań. Puki co zasada ma być prosta PD4 i PD5 ma się zmieniać z 0 -> 1 z częstotliwością ok 150Hz(nie posiadam oscyloskopu żeby się przekonać czy tyle naprawdę jest) zaś cały PORTB ma zmieniać swoją wartość na przeciwną co jedną sekundę. Problem w tym że gdy jestem w jednym przerwaniu drugie jest ignorowane. Jak temu zaradzić tak żeby wszystko się ładnie wykonało?
I jeszcze jedno... Aby otrzymać przerwanie timer1_compA co jedną sekundę policzyłem tak:
fosc/preskaler = 1000000/1024 = 976Hz
daje to czas ok 1.024m/s
1.024 * 976 = 1sek <- w przybliżeniu
Dlatego zrobiłem takie przypisanie:
| Code: |
ldi tmp, 0xD0
out OCR1AL, tmp
ldi tmp, 0x03
out OCR1AH, tmp
|
Niestety zmiana stanu następuje zdecydowanie szybciej. Dlaczego? Czyżbym przeoczył coś w nocie katalogowej?
|
|
| Back to top |
|
 |
robson_s-ec Poziom 12

Joined: 19 Apr 2003 Posts: 92
|
#2
11 Mar 2010 12:25 Re: [Attiny2313][Asm] Synchronizacja przerwań i skalowanie c |
|
|
|
| Lukaszek_69 wrote: |
| Problem w tym że gdy jestem w jednym przerwaniu drugie jest ignorowane. Jak temu zaradzić tak żeby wszystko się ładnie wykonało? |
System przerwań jest automatycznie blokowany po wejściu do obsługi dowolnego przerwania.
| Quote: |
When an interrupt occurs, the Global Interrupt Enable I-bit is cleared and all interrupts are disabled.
The user software can write logic one to the I-bit to enable nested interrupts. All enabled
interrupts can then interrupt the current interrupt routine. The I-bit is automatically set when a
Return from Interrupt instruction – RETI – is executed. |
Właściwie to pozostałe przerwania nie są ignorowane a obsługiwane po zakończeniu obsługi pierwszego zgłoszonego.
|
|
| Back to top |
|
 |
Google

|
#
11 Mar 2010 12:25 |
|
|
|
|
|
| Back to top |
|
 |
Nawigator Poziom 22

Joined: 18 Jan 2005 Posts: 1770 Location: Ostrowiec Św.
|
#3
11 Mar 2010 12:54 Re: [Attiny2313][Asm] Synchronizacja przerwań i skalowanie c |
|
|
|
Nie wnikając w cały kod wpis do rejestrów 16-bitowych powinien być odwrotnie - najpierw H potem L. Odczyt napierw L potem H.
Czyli:
ldi tmp, 0x03
out OCR1AH, tmp
ldi tmp, 0xD0
out OCR1AL, tmp
N.
|
|
| Back to top |
|
 |
Google

|
#
11 Mar 2010 12:54 |
|
|
|
|
|
| Back to top |
|
 |
wojtek8-7 Poziom 12

Joined: 12 Dec 2009 Posts: 97
|
#4
11 Mar 2010 13:13 Re: [Attiny2313][Asm] Synchronizacja przerwań i skalowanie c |
|
|
|
Jeśli chcesz aby w trakcie jednego przerwania zostało obsłużone drugie, ważniejsze, dopisz w przerwaniu SEI. Wchodząc do przerwania flaga I jest zerowana i są wyłączane przerwania, rozkaz RETI ponownie ustawia flagę I.
|
|
| Back to top |
|
 |
Lukaszek_69 Poziom 12

Joined: 01 Oct 2009 Posts: 107
|
#5
11 Mar 2010 19:06 Re: [Attiny2313][Asm] Synchronizacja przerwań i skalowanie c |
|
|
|
Właśnie problem w tym że przy debugowaniu po zakończeniu jednego przerwania kolejne nie było wykonane(chyba że coś źle zinterpretowałem)... Tak czy inaczej jutro spróbuje to zasymulować jeszcze raz bo dziś mam napięty dzień i o efektach poinformuje.
Puki co priorytet przerwań nie ma większego znaczenia tak więc nie daje sei w przerwaniu.
Dzięki za wskazówkę dotyczącą wpisów do rejestrów! Przyda się.
A co myślicie o skalowaniu zegara tak żeby otrzymać żądaną jedna sekundę(1 Hz)?
Korzystam ze złego sposobu? Dodam że zegara nie przestawiałem i jest domyślny 1MHz.
|
|
| Back to top |
|
 |
JarekC Poziom 16

Joined: 09 Jan 2003 Posts: 290 Location: "-"
|
#6
11 Mar 2010 20:02 Re: [Attiny2313][Asm] Synchronizacja przerwań i skalowanie c |
|
|
|
Witam,
Kilka uwag:
1. nie skonfigurowałeś trybu pracy timerów (rejestry TCCRxA, TCCRxB)
Po resecie timery pracują w trybie "Normal", natomiast w twoim przypadku znacznie lepszy byłby tryb "CTC"
2. ustawiłeś prescaler a 1 a nie na 1024
3. brak zachowania stanu PSW i rejestrów w przerwaniach. W twoim konkretnym przykładzie nie spowoduje to błędu ale już np. zaproponowane odblokowanie przerwania spowoduje problemy.
Poczytaj sobie o trybie CTC pracy timerów.
Pozdrawiam
JarekC
|
|
| Back to top |
|
 |
grysek Poziom 16

Joined: 29 Jun 2007 Posts: 340 Location: Limanowa
|
#7
11 Mar 2010 20:19 Re: [Attiny2313][Asm] Synchronizacja przerwań i skalowanie c |
|
|
|
To proste:
Aby odczekać sekundę to przy zegarze 1Mhz musisz odczekać 1 000 000 cykli. Możesz użyć do tego preskalera (1,8,64,256,1024). Jesli chcesz odmierzyć sekundę to musisz użyć preskalera 64 (256 i 1024 nie wchodzi w gre ponieważ jeśli podzielimy 1 000 000 przez te liczby to nie wychodzi liczba całkowita).
I tak przy preskalerze 64 timer musi zliczyć do 15625 (64 * 15625 = 1000000) aby to trwało 1 sekundę. I tą watrość możesz wsadzić do rejestru np OCR1A i puścić Timer w trybie CTC - czyli normalnego zliczania lecz po osiągnięciu tej wartości zawartość TCNT1 będzie kasowana i Timer bedzie zliczał od zera. Albo mozesz też wpisać wartość 0xFFFF - 15625 do TCNT1 bezpośrednio i ustawić Timer w trybie normalnego zliczania wtedy to za każdym przerwaniem musisz ładować tą wartość od nowa.
Spójrz tu :arrow: http://www.wkretak.pl/readarticle.php?article_id=3
Pozdrawiam :P
|
|
| Back to top |
|
 |
Google

|
#
11 Mar 2010 20:19 |
|
|
|
|
|
| Back to top |
|
 |
Lukaszek_69 Poziom 12

Joined: 01 Oct 2009 Posts: 107
|
#8
27 Mar 2010 21:05 Re: [Attiny2313][Asm] Synchronizacja przerwań i skalowanie c |
|
|
|
Niestety nie miałem możliwości wcześniej wszystkiego posprawdzać, ale zrobiłem to teraz i wszystko ładnie działa. Dziękuję wszystkim za zainteresowanie, uwagi były pomocne aczkolwiek układ nie działał w dużej mierze przed moją częstą nieuwagę.
Poniżej przedstawiam działający kod. Mam nadzieje że się komuś przyda.
| Code: |
.include "tn2313def.inc"
;-----definicje---------------------
.def tmp = r16
.def tmp2 = r17
;-----wektory przerwan--------------
.cseg
.org 0x00
rjmp reset
.org 0x04
rjmp timer1_compA
.org 0x06
rjmp timer0_ovf
;-----------------------------------
reset:
ldi tmp, 0xFF
out DDRD, tmp
ldi tmp, 0xFF
out DDRB, tmp ;konfiguracja PORTB i PORTD
ldi tmp, RAMEND
out SPL, tmp ;ustawienie stosu
ldi tmp, 0x0B
out TCCR1B, tmp ;preskaler 64 + CTC dla timera 1
ldi tmp, 0x05
out TCCR0B, tmp ;preskaler 1024 dla timera 0
ldi tmp, 0x42
out TIMSK, tmp ;wlaczenie przerwania compA dla timera 1
;wlaczenie przerwania overflow dla timera 0
ldi tmp, 0x3D
out OCR1AH, tmp
ldi tmp, 0x09
out OCR1AL, tmp ;comp1A = 15625
sei
end:
rjmp end
;-----------------------------------
timer1_compA:
in tmp,PORTD
ldi tmp2, 0x0F
eor tmp, tmp2
out PORTD, tmp
reti
timer0_ovf:
in tmp,PORTD
ldi tmp2, 0xF0
eor tmp, tmp2
out PORTD, tmp
reti
|
Temat zamknięty.
|
|
| Back to top |
|
 |