Stoper | DSM51 (asm)

To forum jest dla wszystkich pasjonatów wiecznie młodych mikrokontrolerów '51. Wymiana doświadczeń i pomoc dla początkujących w pisaniu programów zarówno w C, Asemblerze jak i BASCOM. Zapraszam znawców tematu, aby pomogli wszystkim początkującym!
ODPOWIEDZ
mikajlo
-
Posty: 8
Rejestracja: 31 mar 2011, 22:25
Lokalizacja: Polska

Stoper | DSM51 (asm)

Post autor: mikajlo » 15 sie 2011, 13:30

Witam,
Muszę przygotować na zajęcia projekt stopera z opcją zapamiętywania między czasów.

Przygotowując się do projektu przerobiłem poszczególne tematy z książki Gałków. Jednak nadal nie wiele sam potrafię zrobić.

Znalazłem przykład stopera, który nie posiada opcji zapamiętywania między czasów. Od 2 dni analizuje kod, ale nadal cały czas gubię się w działaniu tego stopera. Proszę Was o pomoc.

Kod wygląda tak:

Kod: Zaznacz cały


;.TITLE	'STOPER'
;============================

STOS	EQU	60H		;wartość wskaźnika stosu w RAMie

SEG_ON	EQU	P1.6		;linia wygaszania wyświetlacza

;Pamięć wyświetlacza
DISPLAY	EQU	30H
LEDS	EQU	DISPLAY+6
DOTS	EQU	LEDS+1
NEXT	EQU	DOTS+1



;Timer 0 przeglądanie wskaźników
;uaktywniany co ok. 1ms - niższy priorytet
;1ms =~30 * 32 cykli
;Mod 0 - starszy bajt liczy do 30
 
;Timer 1 odliczanie czasu 10 ms
;10ms = 36*256 cykli
;Mod 1 - przestawiam tylko starszy bajt

TMOD_SET	EQU	00010000B
TH0_SET		EQU	256-30
TH1_SET		EQU	256-36
IE_SET		EQU	10001010B	;przerwania T0 i T1
IP_SET		EQU	00001000B	;wyższy priorytet T1
TCON_SET	EQU	00010000B	;start timer T0
;(setb TR1 - start Timer 1)

BANK0	MACRO
	CLR	RS0
	MACEND

BANK1	MACRO
	SETB	RS0
	MACEND



	LJMP	START

	ORG	0BH
;przerwanie Timer 0
	PUSH	ACC
	PUSH	PSW
	BANK1
	MOV	TH0,#TH0_SET
	AJMP	CONT_INTT0

	ORG	1BH
;przerwanie Timer 1
	PUSH	ACC
	PUSH	PSW
	
	MOV	TH1,#TH1_SET

	INC	DISPLAY
	MOV	A,#10
	CJNE	A,DISPLAY,INTT1_END
	MOV	DISPLAY,#0

	INC	DISPLAY+1
	MOV	A,#10
	CJNE	A,DISPLAY+1,INTT1_END
	MOV	DISPLAY+1,#0

	INC	DISPLAY+2
	MOV	A,#10
	CJNE	A,DISPLAY+2,INTT1_END
	MOV	DISPLAY+2,#0

	INC	DISPLAY+3
	MOV	A,#6
	CJNE	A,DISPLAY+3,INTT1_END
	MOV	DISPLAY+3,#0

	INC	DISPLAY+4
	MOV	A,#10
	CJNE	A,DISPLAY+4,INTT1_END
	MOV	DISPLAY+4,#0

	INC	DISPLAY+5
	MOV	A,#6
	CJNE	A,DISPLAY+5,INTT1_END
	MOV	DISPLAY+5,#0

INTT1_END:
	POP	PSW
	POP	ACC
	RETI



CONT_INTT0:
	MOV	R0,#CSDB	;R0 - adres bufora wyswietlaczy

	SETB	SEG_ON
	MOV	A,@R1
	CJNE	R1,#LEDS,D7SEG

;wyświetlenie Ledów
	SJMP	DISP_SET	
D7SEG:
	ACALL	CODE7_GET

;dodanie kropki
	PUSH	ACC
	CLR	C
	MOV	A,R2
	ANL	A,DOTS
	JZ	DOT_NO
	SETB	C
DOT_NO:
	POP	ACC
	MOV	ACC.7,C

DISP_SET:
	MOVX	@R0,A

	MOV	A,R2		;kolejny wskaźnik
	MOV	R0,#CSDS	;R0 - adres wyboru wskaźnika
	MOVX	@R0,A

	CLR	SEG_ON

	RL	A
	MOV	R2,A
	INC	R1
	CJNE	R1,#DOTS,NEXT_SEG

;ustaw segment 0
	MOV	R2,#1
	MOV	R1,#DISPLAY	;wskaźnik na pamięć wyświetlacza

NEXT_SEG:
	POP	PSW
	POP	ACC
	RETI



	ORG	100H
START:
	MOV	SP,#STOS	;wskaźnik stosu

	ACALL	STOPPER_CLEAR

	MOV	TMOD,#TMOD_SET
	MOV	TH0,#TH0_SET
	MOV	TH1,#TH1_SET
	MOV	TL1,#0
	MOV	IE,#IE_SET
	MOV	IP,#IP_SET
	MOV	TCON,#TCON_SET


	BANK1
	MOV	R2,#1		;wybór wskaźnika - 0 (kod 1 z 7)
	MOV	R1,#DISPLAY	;wskaźnik na pamięć wyświetlacza
	BANK0

LOOP:
	LCALL	LCD_CLR
	MOV	DPTR,#TEXT1
	LCALL	WRITE_TEXT

	LCALL	WAIT_ENTER_NW
;start timer
	SETB	TR1
	MOV	LEDS,#10H

	LCALL	LCD_CLR
	MOV	DPTR,#TEXT2
	LCALL	WRITE_TEXT

	LCALL	WAIT_ENTER_NW

;stop timer
	CLR	TR1
	MOV	LEDS,#20H

	AJMP	LOOP	


CODE7_GET:
	INC	A
	MOVC	A,@A+PC
	RET

	DB	03FH	;0
	DB	006H	;1
	DB	05BH	;2
	DB	04FH	;3
	DB	066H	;4
	DB	06DH	;5
	DB	07DH	;6
	DB	007H	;7
	DB	07FH	;8
	DB	06FH	;9
	DB	077H	;A
	DB	07CH	;b
	DB	039H	;C
	DB	05EH	;d
	DB	079H	;E
	DB	071H	;F


STOPPER_CLEAR:
	CLR	A
	MOV	DISPLAY,A
	MOV	DISPLAY+1,A
	MOV	DISPLAY+2,A
	MOV	DISPLAY+3,A
	MOV	DISPLAY+4,A
	MOV	DISPLAY+5,A
	MOV	LEDS,#20H
	MOV	DOTS,#00010100B
	RET


TEXT1:
	DB	'ENTER -> START  '
	DB	'RESET RAM->CLR ',0
TEXT2:
	DB	'ENTER -> STOP',0

Wszystkie rozkazy, mnemoniki, które są zastosowane w programie znam i wiem, "co robią" (przynajmniej tak mi się wydaje). Natomiast nie rozumiem do końca, kiedy zaczynają działać timery (1 | 2), za co odpowiadają poszczególne timery, w jaki sposób przetwarzany jest kod..

Przedstawią może teraz, jak ja teraz interpretuje "widzę" ten kod.

---
Rusza program START:
ustawia się stos;; wpisuje 0 (wyzerowuje) dane wskaźników na wyświetlaczu 7-segmentowym;; ustawia wartości początkowe dla timerów; timer1 ma priorytet wyższy niż timer0; startuje timer0

i teraz po 1ms (bo tak jest ustawiony timer0) następuje przepełnienie timera0 i zgłaszane jest przerwanie, czyli zaczynają wykonywać się instrukcje timera0, ale główny program idzie dalej??-i wykonuje międzyczasie dalsze instrukcje?-czyli: wstawia dane na R2,R1 w Banku1; wstawia tekst na wyśw. LCD i czeka na wciśnięcie ENTER, aby stoper ruszył (czy dobrze to rozumiem???)

Po wciśnięciu Enter rusza timer1; program główny czeka na Enter, aby zatrzymać program, a reszta działa dalej sama.

Tylko jak "współpracują" ze sobą te timery? Co właściwie robi timer0? (z tego, jak ja to rozumiem, to timer0 raz uruchomiony działa co 1ms? i za pierwszym razem, jeszcze przed uruchomieniem timera1, ustawia i wyświetla na wyśw. 7-segm. same zera).
Natomiast timer1 z tego co analizuje to Akumulator jest jakby ograniczeniem do ilu (do jakiej cyfry) ma wyświetlać dany wskaźnik, tzn. np. wskaźnik, który odpowiada za wyświetlanie dziesiątek sekund (10, 20,..,60) może liczyć tylko do 6 (trochę to skomplikowanie opisuje). Ale do czego jeszcze służy ten timer1?

Podsumowując: nie potrafię spojrzeć na program całościowo; jak realizowane są jego działania; jak następują "przeskoki" między timerami, powrotami z przerwań, itp.

Ponadto prosiłbym o jakąś sugestie dotyczącą międzyczasów - jak proponujecie to zaimplementować w ten kod.

Czekam na odpowiedź,
Michał

P.S. Proszę moderatorów o nie usuwanie tematu.

keruseykaryu

Post autor: keruseykaryu » 15 sie 2011, 15:45

mikajlo pisze:Natomiast nie rozumiem do końca, kiedy zaczynają działać timery (1 | 2),
Najpierw przygotować:

Kod: Zaznacz cały

    MOV    TMOD,#TMOD_SET 
     MOV    TH0,#TH0_SET 
     MOV    TH1,#TH1_SET 
     MOV    TL1,#0 
     MOV    IE,#IE_SET 
     MOV    IP,#IP_SET 
i wio:
przemiatanie wyświetlacza, co działa zawsze

Kod: Zaznacz cały

     MOV    TCON,#TCON_SET
odliczanie czasu co działa po enter

Kod: Zaznacz cały

    SETB    TR1
no i po następnym enter prr!

Kod: Zaznacz cały

    CLR    TR1
mikajlo pisze:głaszane jest przerwanie, czyli zaczynają wykonywać się instrukcje timera0, ale główny program idzie dalej??
Nie idzie dalej tylko czeka, aż się przerwanie wykończy. Z przerwaniami to jest tak: pętla co się kończy

Kod: Zaznacz cały

    AJMP LOOP
sobie biega i drukuje, czy też oczekuje na klawisz, a tajmery sobie biegają cały czas i przerywają jej na chwilę.
mikajlo pisze:Tylko jak "współpracują" ze sobą te timery?
Sobie same biegają i przerywają jak coś mają do zrobienia więcej. Punktem wspólnym jest 6 porcji pamięci DISPLAY - DISPLAY+6. Tajmerek 1 sobie to zwiększa, bo kod od niego to tylko licznik od 00:00:00 do 59:59:99. A jak tajmerek 1 ma wolne to tajmerek 0 sobie te dane zabiera i wyświetla po jednej cyferce co każde okrążenie. Jakby się spotkały i próbowały coś zrobić razem to tajmerek 1 ma pierwszeństwo bo ustawiliśmy mu znak z żółtym rombem:

Kod: Zaznacz cały

     MOV    IP,#IP_SET 

mikajlo
-
Posty: 8
Rejestracja: 31 mar 2011, 22:25
Lokalizacja: Polska

Post autor: mikajlo » 16 sie 2011, 15:51

Dzięki za zainteresowanie (bo na konkurencyjnym forum zostawili mnie bez odpowiedzi).
A teraz do rzeczy..

W sumie na to, to co mi napisałeś już wiedziałem. Może jedynie nie wiedziałem dokładnie, czy przerwanie zatrzymuje pracę programu głównego.

Ale jeśli już to wiem, to mam pytanie. Timer0 startuje po na początku programu po 1ms

Kod: Zaznacz cały

START:
    ...
    MOV    TMOD,#TMOD_SET
    MOV    TH0,#TH0_SET
    MOV    TH1,#TH1_SET
    MOV    TL1,#0
    MOV    IE,#IE_SET
    MOV    IP,#IP_SET
    [b]MOV    TCON,#TCON_SET [/b]
czyli po upłynięciu 1ms następuje przerwanie i skok do "programu" timera0 ? W tym momencie dalsze instrukcje programu głównego:

Kod: Zaznacz cały

BANK1
    MOV    R2,#1        ;wybór wskaźnika - 0 (kod 1 z 7)
    MOV    R1,#DISPLAY    ;wskaźnik na pamięć wyświetlacza
    BANK0

LOOP: 
          ...
zostają przerwany do momentu powrotu z przerwania?

Teraz pytanie odnośnie timer1. Nie wiem czy dobrze rozgryzłem kod, który ten timer 'przerabia'. Ja widzę to tak:

Kod: Zaznacz cały

    INC    DISPLAY
    MOV    A,#10
    CJNE    A,DISPLAY,INTT1_END
    MOV    DISPLAY,#0

    INC    DISPLAY+1
    MOV    A,#10
    CJNE    A,DISPLAY+1,INTT1_END

    ....
przy pierwszym "przejściu" timera w DISPLAY jest 0, więc inkrementuje na 1; do A wpisuje 10 i robi porównanie - jeśli jest mniej niż 10 skacze do INTT1_END (procedura powrotu z przerwania).

Czyli przez pierwsze 9 "przejść" timera1, przetwarzanie kodu timera kończy się na pierwszej części? (tzn. nie robi DISPLAY+1, DISPLAY+2, ... bo od razu 'wyskakuje'). Dopiero gdy na DISPLAY osiągnie 10 wpisywane jest 0 i następnie 1 na DISPLAY+1 i skok do INTT1_END? TAK?

I jeszcze odnośnie:
Timery sobie same biegają i przerywają jak coś mają do zrobienia więcej.
Czyli po naciśnięciu enter (po starcie programu), działają na przemian timer0 i timer1, z tym, że timer1 ma wyższy priorytet. I działa to na zasadzie takiej, że timer1 odlicza czas, a timer0 odświeża wyświetlacz 7-segmentowy aby pokazywać aktualny czas? tak?

keruseykaryu

Post autor: keruseykaryu » 16 sie 2011, 17:07

mikajlo pisze:Timer0 startuje po na początku programu po 1ms
START:
...
MOV TMOD,#TMOD_SET
MOV TH0,#TH0_SET
...
MOV TCON,#TCON_SET
czyli po upłynięciu 1ms następuje przerwanie i skok do "programu" timera0 ? W tym momencie dalsze instrukcje programu głównego: Kod:

BANK1
MOV R2,#1 ;wybór wskaźnika - 0 (kod 1 z 7)
MOV R1,#DISPLAY ;wskaźnik na pamięć wyświetlacza
BANK0
LOOP:
...
zostają przerwany do momentu powrotu z przerwania?
Tak. Ale nie wiesz kiedy to nastąpi. Idzie to wyliczyć, ale nie o to.
Jest duża szansa, że przerwania strzelają dokładnie w to co znajduje się tam:
LCALL WAIT_ENTER_NW
mikajlo pisze:Teraz pytanie odnośnie timer1. Nie wiem czy dobrze rozgryzłem kod, który ten timer 'przerabia'. Ja widzę to tak:

INC DISPLAY
MOV A,#10
CJNE A,DISPLAY,INTT1_END
MOV DISPLAY,#0

INC DISPLAY+1
MOV A,#10
CJNE A,DISPLAY+1,INTT1_END

....



przy pierwszym "przejściu" timera w DISPLAY jest 0, więc inkrementuje na 1; do A wpisuje 10 i robi porównanie - jeśli jest mniej niż 10 skacze do INTT1_END (procedura powrotu z przerwania).

Czyli przez pierwsze 9 "przejść" timera1, przetwarzanie kodu timera kończy się na pierwszej części? (tzn. nie robi DISPLAY+1, DISPLAY+2, ... bo od razu 'wyskakuje'). Dopiero gdy na DISPLAY osiągnie 10 wpisywane jest 0 i następnie 1 na DISPLAY+1 i skok do INTT1_END? TAK?
Tak to wygląda. Najdłużej timerek 1 przerwie program jak będzie 59:59:99. Bo wtedy przeleci jak burza po wszystkich elementach. Idzie to napisać krócej, ale masz dużo pamiąchy, nie trzeba się męczyć.
Czyli po naciśnięciu enter (po starcie programu), działają na przemian timer0 i timer1, z tym, że timer1 ma wyższy priorytet. I działa to na zasadzie takiej, że timer1 odlicza czas, a timer0 odświeża wyświetlacz 7-segmentowy aby pokazywać aktualny czas? tak?
Nooooo.... Prawie. Bo jeszcze jest jakaś enigma z dwoma instrukcjami,
MOV LEDS,#10H
...
MOV LEDS,#20H
a nie mam już książki o dsmku by zajrzeć czy to właśnie wygasza wyświetlacz.

mikajlo
-
Posty: 8
Rejestracja: 31 mar 2011, 22:25
Lokalizacja: Polska

Post autor: mikajlo » 16 sie 2011, 18:23

Ok, cieszy mnie to, że jednak coś tam zrozumiałem.

Co do tych ostatnich poleceń to zmieniają one jedynie diodę z ER na OK :)

A mam jeszcze pytanie - wiesz może w jaki sposób możnaby łatwo wprowadzić funkcję międzyczasów do tego stopera? Chodzi o taką funkcje - biegnie 5 biegaczy i każdy przybiega na metę w innym czasie. Stoper ma zapamiętać wszystkie czasy biegaczy i czas całkowity. Potem można te czas podejrzeć.

keruseykaryu

Post autor: keruseykaryu » 17 sie 2011, 5:31

mikajlo pisze:A mam jeszcze pytanie - wiesz może w jaki sposób możnaby łatwo wprowadzić funkcję międzyczasów do tego stopera?
Wiem, ale to twoje zadanie nie moje.

ODPOWIEDZ