Timery w programie zegarek

Pawel9876543210

Użytkownik
Dołączył
Kwiecień 29, 2013
Posty
3
Witam. Mam problem z jednym programem w asemblerze. Mam napisać program który będzie pełnił funkcję zegarka.

Kod:
CSDS16	EQU	0FF30H	;adres zatrzasku wyboru wskaźnika/wyświetlacza
CSDB16	EQU	0FF38H	;adres zatrzasku wyboru segmentów/wzorków

SEGOFF	BIT	P1.6		;ten bit włącza wyświetlacze

LEDRAM EQU	50H
;=======================================
;
;	RESET
;
	ORG	00H	;reset
	LJMP	START	;

;=======================================
;
;	PROGRAM
;
	ORG	100H	;program
START:

	

	MOV   LEDRAM + 1, #5     ;js
	MOV   LEDRAM + 2, #6      ;ds
	MOV   LEDRAM + 3, #3      ;jm
	MOV   LEDRAM + 4, #4      ;dm
	MOV   LEDRAM + 5, #1      ;jg
	MOV   LEDRAM + 6, #2      ;dg
	MOV   LEDRAM + 7, #21

	CLR	SEGOFF		;włącz wyświetlacze

					;można przetestować podstawiając


;na razie zmienia się niewiele, przenosimy funkcje kontrolne do rejestrów R6 i R7
;żeby zwolnić akumulator do innch zadań,
;w dalszym ciągu ten sam wzorek na wszystkich wyświetlaczach

LoopIni:
	MOV	R7, #1		;zaczynamy od najmłodszego wyświetlacza
					;R7 przyjmuje wartości 1, 2, 3, 4, 5, 6, 7
	MOV	R6, #128		;to jest najmłodszy wyświetlacz bitowo
					;R6 przyjmuje wartości 1, 2, 4, 8, 16, 32, 64
	MOV	R0, #LEDRAM		;do rejestru R0 ładujemy wartość LEDRAM
LoopRun:


	MOV  	 A,   @R0               ;wyłuskanie adresu z rejestu R0 do Akumulatora

	
	SETB  SEGOFF               ;wylacz wyswietlacz

	MOV	DPTR, #WZORY	;adres wzorków do DPTR
	MOVC	A, @A+DPTR		;wzorek do A

	MOV	DPTR, #CSDB16	;adres zatrzasku wzorków do DPTR
	MOVX	@DPTR, A		;wzorek do zatrzasku

	MOV	DPTR, #CSDS16	;adres zatrzasku wyboru wskaźników do DPTR

	MOV	A, R6			;maska bitowa wybierająca wyświetlacz do A
	MOVX	@DPTR, A		;wybierz wskaźnik
	
	CLR SEGOFF              ;wlacz wyswietlacz

	RL	A			;w następnym obrocie pętli wybierz następny,
	MOV	R6, A			;starszy wyświetlacz - i zapamiętaj to w R6
	
	INC R0				;inkrementacja-zwiekszenie o 1

LoopDelay:
      DJNZ R2, LoopDelay
      ;DJNZ R3, LoopDelay

	INC	R7			;przestaw wskaźnik na starszy wyświetlacz
	CJNE	R7, #8, LoopRun	;"8" w R7 oznacza minięcie diod F1-ER
	SJMP	LoopIni		;ponownie zacznij od najmłodszego wyświetlacza

WZORY:
	DB	00111111B, 00000110B, 01011011B, 01001111B	;0123
	DB	01100110B, 01101101B, 01111101B, 00000111B	;4567
	DB	01111111B, 01101111B, 01110111B, 01111100B	;89Ab
	DB	01011000B, 01011110B, 01111001B, 01110001B	;cdEF

W chwili obecnej program wyświetla na wyświetlaczu wartości, które są przekazywane do LEDRAM. Teraz pasowałoby pokombinować z timerami aby odmierzał czas niestety nie bardzo je ogarniam :/ próbowałem na podstawie poniższego zadania trochę z nimi pokombinować ale niestety nie udaje mi się.

Kod:
;=======================================
;
;	TIMER INTERRUPT
;
;	1000 przerwań na sekundę od timer 0 w trybie 1

TEST	BIT	P1.7
BUZZ	BIT	P1.5

T0IB	BIT	7FH		;timer 0 interrupt bit

;=======================================
;	RESET

	ORG	00H		;reset
	LJMP	START

;=======================================
;	TIMER 0 INTERRUPT
	ORG	0BH

	LJMP	TI0MAIN	;w ten sposób omijamy ograniczenie do 8 bajtów


;=======================================
;	TIMER 0 INTERRUPT MAIN
	ORG	0B0H			;od B0h do 100h jest 80 bajtów, na pewno wystarczy

TI0MAIN:
	PUSH	ACC			;zabezpieczamy wykorzystywane rejestry
	PUSH	PSW			;

	MOV	TH0, #255 - 3	;wartość typowa

	MOV	A, #256 - 154 + 1	; + 1 aby nadrobić stratę
	ADD	A, TL0		;uwzględnia opóźnienie wywołania przerwania
	MOV	TL0, A		;TL0 ustawione właściwie

	JNC	TI0MAIN_TH0_OK	;jeżeli nie Carry to jest OK
	INC	TH0			;wpr podbijamy TH0 w stosuku do wartości typowej

TI0MAIN_TH0_OK:			;TH0 ustawione właściwie

	POP	PSW			;odzyskujemy wykorzystywane rejestry
	POP	ACC			;

	SETB	T0IB			;informujemy pętlę główną o przerwaniu

	RETI				;powrót z przerwania

;=======================================
;	PROGRAM

	ORG	100H
START:
	MOV	IE,	#00h	;blokada wszystkich przerwań

	MOV	TMOD,	#71h	;T1.GATE=0 T1.C/T=C T1.MODE=3 T0.GATE=0 T1.C/T=T T0.MODE=1
	MOV	TCON,	#10h	;m.in. blokada zliczania przez T1, aktywuje zliczanie przez timer 0
	SETB	ET0		;aktywuje przerwanie od timer 0
	SETB	EA		;globalne zezwolenie na obsługę przerwań

LoopRun:
	JNB	T0IB, LoopRun	;czeka na przerwanie

	CLR	T0IB		;zapomina że było przerwanie

	CPL	TEST		;przełącza diodę
	CPL	BUZZ		;przełącza brzęczyk

	SJMP	LoopRun

Prosiłbym o pomoc z zadaniem osoby lepiej znające asemblera ode mnie a na pewno się dogadamy w sprawie zapłaty :)
 

shoorick

Użytkownik
Dołączył
Lipiec 17, 2008
Posty
66
muszę powiedzieć nie bardzo zrozumiałem kalkulacji w TI0MAIN
spróbuj tak:
Kod:
TI0MAIN:    PUSH    ACC            ;zabezpieczamy wykorzystywane rejestry
    PUSH    PSW            ;


;    MOV    TH0, #255 - 3    ;wartosc typowa
;
;    MOV    A, #256 - 154 + 1    ; + 1 aby nadrobic strate
;    ADD    A, TL0        ;uwzglednia opoznienie wywolania przerwania
;    MOV    TL0, A        ;TL0 ustawione wlasciwie
;
;    JNC    TI0MAIN_TH0_OK    ;jezeli nie Carry to jest OK
;    INC    TH0            ;wpr podbijamy TH0 w stosuku do wartosci typowej
;
;TI0MAIN_TH0_OK:            ;TH0 ustawione wlasciwie


    DJNZ R2,TI0MAIN_DONE  ; uzywami R2 jako wiekszy rejestr liczilnika


    MOV  R2,#20
    SETB    T0IB            ;informujemy petle glowna o przerwaniu
        ; mov TH0,#-XH
        ; mov TL0,#-XL
TI0MAIN_DONE:
    POP    PSW            ;odzyskujemy wykorzystywane rejestry
    POP    ACC            ;




    RETI                ;powrot z przerwania
przerwanie wywoła się kiedy liczylnik przepiełnia się, tymczasem liczy dalej.
65536 cykłów jest mniej niż 1 sekunda, dlatego używami dodatkowy bajt w pamieci jako starszy rejestr liczylnika.
wartość 20 dla R2 obrałem empirycznie, migoci chyba raz na jedną sekundę z kwarcem 24MHz.
dla poprawniej zatrzymki musisz policzyć jakoś tak:
1 sec = (R6*65536 + X + 2 + Y)*trzwałość_jednego_taktu
X - poprawka do ładowania w TH0/TL0. musi być ujemna że liczylnik liczy zawsze naprzud
Y - poprawka na inne: trzeba dokładnie policzyć takty w razie kiedy obsługa ładuje TH0/TL0, inaczej zegarek nie będzie akuratny

inny wariant: zamiast podania sygnału do pętli głownej możesz zmienić liczby czasu prosto w obsluge przerwania.
 
Ostatnia edycja:

Pawel9876543210

Użytkownik
Dołączył
Kwiecień 29, 2013
Posty
3
Ten kod drugi działał poprawnie. Chodziło mi o to że na podstawie tego drugiego kodu muszę jakoś zrobić timery w kodzie pierwszym. Tylko nie wiem za bardzo jak się do tego zabrać.
 

shoorick

Użytkownik
Dołączył
Lipiec 17, 2008
Posty
66
aha, mnie chyba wydało się niby nie działa przez wielką częstotliwość: chyba migociło czybko że wydało że LED świeci ciągło (sprawdzałem na realnim sprzeci) :)

wtedy zrob tak:
1.dodaj inicializację timeru do startu z drugego kodu do pierwszego.
2.dodaj TIOMAIN do pierwszego kodu.
3.w TIOMAIN zamiast kodu
Kod:
[COLOR=#333333]    SETB    T0IB            ;informujemy petle glowna o przerwaniu[/COLOR]
dodaj kod, który powieksza czas, coś w rodzaju:
Kod:
;-----------------------------------------------------------------------
    mov a,LEDRAM + 1
    inc a
    mov LEDRAM + 1,a
    cjne a,#10,TI0MAIN_TH0_OK
    mov LEDRAM + 1,#0
;-----------------------------------------------------------------------
    mov a,LEDRAM + 2
    inc a
    mov LEDRAM + 2,a
    cjne a,#6,TI0MAIN_TH0_OK
    mov LEDRAM + 2,#0
;-----------------------------------------------------------------------
    mov a,LEDRAM + 3
    inc a
    mov LEDRAM + 3,a
    cjne a,#10,TI0MAIN_TH0_OK
    mov LEDRAM + 3,#0
;-----------------------------------------------------------------------
    mov a,LEDRAM + 4
    inc a
    mov LEDRAM + 4,a
    cjne a,#6,TI0MAIN_TH0_OK
    mov LEDRAM + 4,#0
;-----------------------------------------------------------------------
    mov a,LEDRAM + 6
    cjne a,#2,TI0MAIN_A ; <20 godzin
;-----------------------------------------------------------------------
    mov a,LEDRAM + 5 ; 20+ godzin
    inc a
    mov LEDRAM + 5,a
    cjne a,#4,TI0MAIN_TH0_OK
    mov LEDRAM + 5,#0 ; 24:00:00 --> 00:00:00
    mov LEDRAM + 6,#0
    ljmp TI0MAIN_TH0_OK
;-----------------------------------------------------------------------
TI0MAIN_A:
    mov a,LEDRAM + 5
    inc a
    mov LEDRAM + 5,a
    cjne a,#10,TI0MAIN_TH0_OK
    mov LEDRAM + 5,#0
;-----------------------------------------------------------------------
    mov a,LEDRAM + 6
    inc a
    mov LEDRAM + 6,a
;-----------------------------------------------------------------------
TI0MAIN_TH0_OK:


nie mogę sprawdzić, nie mam pod ręką LEDu dołączyć do kontroleru
 

Pawel9876543210

Użytkownik
Dołączył
Kwiecień 29, 2013
Posty
3
Kurcze ma ktoś może jakiś dobry poradnik gdzie łopatologicznie wyjaśnione są te timery?
Bo nie wychodzi mi z nimi i programik nadal leży :/
 
Do góry Bottom