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

89cxx51 - Assembler: Oczekiwanie na sygnały i procedura czasowa na P1.4

MooNTER 15 Cze 2006 14:14 1773 18
REKLAMA
  • #1 2730938
    MooNTER
    Poziom 12  
    Posty: 107
    Ocena: 3
    w programie chodzi o to,ze:
    - powinien oczekiwac na zero logiczne na p1.3
    - jesli pojawi sie to "0" powinien odmierzyc czas i po tym czasie wykonac procedure (***), chyba ze na /t0 zostana podane dwa impulsy, wtedy ma nic nie wlaczyc i czekac az na p1.3 pojawi sie "1" i od nowa program
    - przy 1 na p1.3 powinien sprawdzac, czy na /int nie pojawil sie impuls, jesli sie pojawil ma sie wlaczyc procedura (***)

    procedura (***) polega na czasowym wlaczaniu i wylaczaniu pinu p1.4 (kilka takich cykli po czym koniec)

    oto moj program:

    
    ORG 000H
    LJMP START	              ;IDZ DO START
    ORG 000BH		      ;PRZERWANIE OD T0
    LJMP PRZERW_T0
    ORG 001BH 		      ;PRZERWANIE OD T1
    LJMP PRZERW_T1
    ORG 0013H		      ;PRZERWANIE OD INT1
    LJMP PRZERW_INT1 
    
    START:
    LICZNIK EQU 0 
    
    LICZ_ALARM EQU 0
    SETB ET0         	      ;ODBLOKUJ T0
    SETB ET1       		      ;ODBLOKUJ T1
    SETB EX1		      ;ODBLOKUJ /INT1
    SETB EA        		      ;ODBLOKUJ PRZERWANIA
    CLR P1.4                      ;WYLACZ TO CO JEST NA P1.4
    CLR P1.3
    LJMP PETLA_OTWARCIA
    PETLA_OTWARCIA:               ;SPRAWDZA CZY JEST SYGNAL ("0") NA P1.3
    JB P1.3,PETLA_OTWARCIA        ;JESLI 1 TO PETLA W KOLO
    
    MOV  TMOD,#00010110B	      ;USTAW T0 W TRYB ZLICZ IMP. 			;WEJSC,T1-ODMIERZA CZAS
    
    
    
    			;A TERAZ WLACZAMY T0:
    MOV TH0,#0FEh  		      ;FEh=256-2=254 CZYLI ZLICZA 2 				;IMPULSY
    MOV TL0,TH0		      ;konieczne!
    SETB TR0		      ;WLACZA LICZNIK T0
    
    LJMP TAJMER
    TAJMER:
    
    			;TERAZ WLACZAMY T1:
    MOV TH1,#03CH		;DLA KWARCU 6MHz 600 PRZEPELNIEN TO 				;5S
    MOV TL1,#0B0H		; 1 PRZEPELNIENIE CO 8,(3)ms
    
    LJMP TAJMERSTART
    TAJMERSTART:
    
    SETB TR1		;WLACZA T1
    
    
    
    
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;;TU JEST PRZERWANIE LICZNIKA CZASU ;;
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    
    
    
    PRZERW_T1:
    INC LICZNIK
    LJMP WKOLO
    ;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;;TU JEST GLOWNY PROGRAM;;
    ;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;;;;;;;;;;;;;;;;;;;;;;;;;;
    WKOLO:
    
    MOV A,#00H
    MOV A,LICZNIK
    CJNE A,#064h,NEXT		;CZY LICZNIK SIE ZAPELNIL
    ZAMK:
    CLR TR1			;ZATRZYMAJ T1
    MOV LICZNIK,#0		;JEZELI LICZNIK SIE ZAPELNI WYZERUJ 
    INC LICZ_ALARM		;ZWIEKSZ LICZ_ALARM O 1
    
    MOV A,00H
    MOV A,LICZ_ALARM
    CJNE A,#01H,DWA
    SETB P1.4
    LJMP TAJMERSTART
    
    NEXT:
    JB P1.3,ZAMK	;JESLI ZAMKNIETO SKOCZ
    LJMP WKOLO
    
    DWA:
    MOV A,00H
    MOV A,LICZ_ALARM
    CJNE A,#02H,TRZY
    LJMP TAJMERSTART
    
    TRZY:
    MOV A,00H
    MOV A,LICZ_ALARM
    CJNE A,#03H,CZTERY
    CLR P1.4
    LJMP TAJMERSTART
    
    CZTERY:
    MOV A,00H
    MOV A,LICZ_ALARM
    CJNE A,#04H,PIEC
    LJMP TAJMERSTART
    
    PIEC:
    MOV A,00H
    MOV A,LICZ_ALARM
    CJNE A,#05H,SZESC
    SETB P1.4
    LJMP TAJMERSTART
    
    SZESC:
    MOV A,00H
    MOV A,LICZ_ALARM
    CJNE A,#06H,SIEDEM
    LJMP TAJMERSTART
    
    SIEDEM:
    MOV A,00H
    MOV A,LICZ_ALARM
    CJNE A,#07H,OSIEM
    CLR P1.4
    LJMP TAJMERSTART
    
    OSIEM:
    MOV A,00H
    MOV A,LICZ_ALARM
    CJNE A,#08H,DZIEWIEC
    LJMP TAJMERSTART
    
    DZIEWIEC:
    MOV A,00H
    MOV A,LICZ_ALARM
    CJNE A,#09H,DZIESIEC
    SETB P1.4
    LJMP TAJMERSTART
    
    DZIESIEC:
    MOV A,00H
    MOV A,LICZ_ALARM
    CJNE A,#0AH,JEDENASCIE
    LJMP TAJMERSTART
    
    JEDENASCIE:
    MOV A,00H
    MOV A,LICZ_ALARM
    CJNE A,#0BH,POZOSTALE
    CLR P1.4
    MOV LICZ_ALARM,#00H	;ZERUJ LICZ_ALARM
    WAIT:
    JB P1.3,TRALALA
    LJMP WAIT
    
    POZOSTALE:
    MOV LICZ_ALARM,#00H	;ZERUJ LICZ_ALARM
    
    RETI
    
    
    
    PRZERW_T0:
    LJMP PRZERWANIE
    
    PRZERWANIE:
    MOV LICZ_ALARM,00H	;USTAW LICZ_ALARM NA ZERO
    CLR P1.4		;WYLACZ TO CO JEST NA P1.4
    LJMP CZEKAJ
    CZEKAJ:
    JNB P1.3,CZEKAJ       ;CZEKAJ NA "1" NA P1.3
    LJMP START		;JAK NIE MA TO DALEJ CZEKAJ
    
    RETI
    
    PRZERW_INT1:
    
    LJMP ZAMK	;SKOCZ DO ZAMK W PRZERW_T1
    
    RETI
    
    TRALALA:
    LJMP START
    
    
    
    END


    teraz pytanie: co w nim namieszalem???
  • REKLAMA
  • #2 2731018
    GienekS
    Poziom 32  
    Posty: 1971
    Pomógł: 139
    Ocena: 15
    To ty najlepiej wiesz co namieszałeś. A nic nie napisałeś jakie masz objawy, program na pewno chodzi dobrze to z reguły namiesza programista.
  • #3 2731038
    MooNTER
    Poziom 12  
    Posty: 107
    Ocena: 3
    Troche zle zadalem pytanie: generalnie interesuje mnie tylko czy nie mieszam cos przy ustawieniu zegara, czy czegos tam zle nie ustawiam (moze cos trzeba dopisac??)
    Rozumiem ze od technicznej strony jesli na nozke podam +5V to mam "1" logiczna, jesli odlacze to mam "0"?
  • REKLAMA
  • #4 2731078
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 51
    Wybacz przyjacielu ;) , ale ten kod to "obraz nędzy i rozpaczy" i ma się nijak do Twoich założeń , a tym bardziej do zasad programowania 51-ek :(

    MooNTER napisał:

    
    CLR P1.3  ;zerujesz P1.3 ???
    LJMP PETLA_OTWARCIA
    PETLA_OTWARCIA:       ;SPRAWDZA CZY JEST SYGNAL ("0") NA P1.3   
    
    ;ano jest "0" , bo sam je tam wpisałeś
    
    JB P1.3,PETLA_OTWARCIA        ;JESLI 1 TO PETLA W KOLO
    ...
    
    LJMP TAJMERSTART
    TAJMERSTART:
    
    SETB TR1		;WLACZA T1
    
    ;teraz "włazisz z buciorami" , do procedury przerwania T1 
    
    
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;;TU JEST PRZERWANIE LICZNIKA CZASU ;;
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    
    
    
    PRZERW_T1:
    
    ;należało by zachować używane rejestry na stosie
    
    INC LICZNIK
    LJMP WKOLO                                                ; po co ??????
    ;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;;TU JEST GLOWNY PROGRAM;;
    ;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;;;;;;;;;;;;;;;;;;;;;;;;;;
    WKOLO:
    
    MOV A,#00H                    ;zapisujesz 0 do akumulatora , tylko po co ??
    MOV A,LICZNIK
    ...
    MOV A,00H   ; a tu zapisujesz do akumulatora zawartość komórki o adresie 0 - po co ??
    MOV A,LICZ_ALARM
    ...
    LJMP TAJMERSTART ;tu beztrosko "wyskakujesz" do "normalnego" programu !!!
    
    itd. itp.
    
    


    teraz pytanie: co w nim namieszalem???

    Zastanów się i napisz to od nowa :(

    Piotrek
  • REKLAMA
  • #5 2731849
    vedy1
    Poziom 15  
    Posty: 117
    Pomógł: 11
    Ocena: 41
    Cytat:
    w programie chodzi o to,ze:
    - powinien oczekiwac na zero logiczne na p1.3

    Nie lepiej podpiąć pod naóżke p3.2, p3.3 ze względu na przerwania??
    Cytat:

    - jesli pojawi sie to "0" powinien odmierzyc czas i po tym czasie wykonac procedure (***), chyba ze na /t0 zostana podane dwa impulsy,
    Czy aby na pewno masz programowo wyzwalać timer t0, czy może tak jak wyżej czyli przerwania na portach??
    Cytat:

    wtedy ma nic nie wlaczyc i czekac az na p1.3 pojawi sie "1" i od nowa program
    - przy 1 na p1.3 powinien sprawdzac, czy na /int nie pojawil sie impuls, jesli sie pojawil ma sie wlaczyc procedura (***)

    Reszte w miare zrozumiałem.
    Cytat:

    Rozumiem ze od technicznej strony jesli na nozke podam +5V to mam "1" logiczna, jesli odlacze to mam "0"?

    Jak podłączysz +5V to masz "1" ale jak odłączysz (czytaj nie masz nic wiecej podłączone) to masz w zależności czy ustawiałeś na porcie "1" czy "0" będziesz miał to co ustawiłeś.
    Sprecyzuj swoje pytanie.
  • #6 2731900
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 51
    vedy1 napisał:

    Jak podłączysz +5V to masz "1" ale jak odłączysz (czytaj nie masz nic wiecej podłączone) to masz w zależności czy ustawiałeś na porcie "1" czy "0" będziesz miał to co ustawiłeś...

    Nie polecam podłączać bezpośrednio +5V do pinu , na który procek wystawił "0" :D

    Piotrek
  • #7 2734813
    MooNTER
    Poziom 12  
    Posty: 107
    Ocena: 3
    vedy1 napisał:

    Nie lepiej podpiąć pod naóżke p3.2, p3.3 ze względu na przerwania??


    moze i lepiej by bylo

    Cytat:
    Czy aby na pewno masz programowo wyzwalać timer t0, czy może tak jak wyżej czyli przerwania na portach??


    chcialbym zeby tymer wyzwalal sie programowo, gdy zmieni sie stan na jednej z nozek

    Cytat:

    Jak podłączysz +5V to masz "1" ale jak odłączysz (czytaj nie masz nic wiecej podłączone) to masz w zależności czy ustawiałeś na porcie "1" czy "0" będziesz miał to co ustawiłeś.
    Sprecyzuj swoje pytanie.


    chodzi mi o wykrywanie zmiany stanu danego pinu. Chyba jednak faktycznie przerzuce sie na int0/int1 i obsluze to przerwaniem.

    Program napisalem od nowa i teraz mam pytanie: przy asemblacji wyskakuje "Zdublowany kod programu w obszarze 27..29 z obszarem 19..274" (asembler to Turbo) Czego to jest przyczyna? kursor zatrzymal sie na
    ORG 001BH 		      ;PRZERWANIE OD T1
    , ale w tym przerwaniu dalem LJMP gdzies dalej wiec nie wiem o co chodzi?? Czy to dlatego ze wybrany jest procesor 8051 i wystarczy wylaczyc sprawdzanie dublowania kodu czy moze jest jakis blad??
  • Pomocny post
    #8 2734891
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 51
    MooNTER napisał:

    ...
    Program napisalem od nowa i teraz mam pytanie: przy asemblacji wyskakuje "Zdublowany kod programu w obszarze 27..29 z obszarem 19..274" (asembler to Turbo) Czego to jest przyczyna?

    To przypatrz się coś napisał w 1-szym poście (komentarze usunąłem) :D
    
    ORG 000H
    000H,001H,002H  LJMP START            
    ORG 000BH           
    00BH,00CH,00DH LJMP PRZERW_T0
    ORG 001BH            
    01BH,01CH,01DH LJMP PRZERW_T1
    ORG 0013H           
    013H,014H,015H  LJMP PRZERW_INT1
    
    START:
    LICZNIK EQU 0
    LICZ_ALARM EQU 0
    016H   SETB ET0                  
    017H   SETB ET1                  
    018H   SETB EX1            
    019H   SETB EA              
    01AH   CLR P1.4             
    01BH   CLR P1.3   ;i tu już diabli wzięli LJMP PRZERW_T1
    
    01CH,01DH,01EH   LJMP PETLA_OTWARCIA
    
    PETLA_OTWARCIA:    
    01FH   JB P1.3,PETLA_OTWARCIA       
    ...
    

    Włazi czy nie :?:

    Piotrek

    PS
    Jak powyłączasz ostrzeżenia , to możesz do emerytury nie skończyć tego programiku :D
    Zamień miejscami 2 ostatnie ORG-i i będzie git ;)
  • #9 2735124
    MooNTER
    Poziom 12  
    Posty: 107
    Ocena: 3
    dzieki, czegos sie nauczylem, program jednak dalej nie dziala :/
    oto on:
    
    ORG 000H
    LJMP START	              ;IDZ DO START
    ORG 000BH		      ;PRZERWANIE OD T0
    LJMP PRZERW_T0
    ORG 0013H		      ;PRZERWANIE OD INT1
    LJMP PRZERW_INT1 
    ORG 001BH 		      ;PRZERWANIE OD T1
    LJMP PRZERW_T1
    ORG 003BH			;PRZERWANIE OD INT0
    LJMP PRZERW_INT0
    
    START:
    LICZNIK EQU 0 
    LICZNIK_JEDEN EQU 0
    LICZNIK_IMPULSOW EQU 0
    SETB ET0         	      ;ODBLOKUJ T0 
    SETB ET1       		      ;ODBLOKUJ T1 		
    SETB EX1		      ;ODBLOKUJ /INT1	
    SETB EA        		      ;ODBLOKUJ PRZERWANIA 
    CLR P1.4                      ;WYLACZ PIN 1.4
    SETB IT1
    SETB IT0
    PAUZA:
    LJMP PAUZA
    
    
    PRZERWANIE_INT0:
    
    MOV  TMOD,#00010110B	      ;USTAW T0 W TRYB ZLICZ IMP. 			;WEJSC,T1-ODMIERZA CZAS
    
    
    			;TERAZ WLACZAMY T1: 5)
    MOV TH1,#03CH		;DLA KWARCU 12MHz 				
    MOV TL1,#0B0H		; 1 PRZEPELNIENIE CO 0,05S
    SETB TR1		;WLACZA T1
    
    
    			;A TERAZ WLACZAMY T0:  6)
    MOV TH0,#0FEh  		      ;FEh=256-2=254 CZYLI ZLICZA 2 				;IMPULSY
    MOV TL0,TH0		      ;konieczne!
    SETB TR0		      ;WLACZA LICZNIK T0
    
    
    
    NIE:		             ;SPRAWDZA CZY JEST 1 NA 3.2 7)
    JB P3.2,LICZ_IMPULSOW       ;JESLI NIEZAMKNIETO IDZ DALEJ JESLI ZAMKNIETO SKOCZ
    TUTAJ:
    MOV A,#00H		; 8)
    MOV A,#LICZNIK
    CJNE A,#064h,NIE	;JESLI LICZNIK SIE NIE ZAPELNIL SKOCZ DO NIE
    			;JESLI SIE ZAPELNIL SPRAWDZ LICZNIK_IMPULSOW
    
    
    LICZ_IMPULSOW:		;ZAMKNIETO OBUDOWE W 7)
    MOV A,#00H		; 9)
    MOV A,#LICZNIK_IMPULSOW
    CJNE A,#01H,WLACZ_JEDEN	;JEZELI LICZNIK_IMPULSOW SIE ZAPELNIL IDZ DALEJ
    			
    
    KONCOWKA:
    MOV LICZNIK_JEDEN,#00H	;ZERUJ LICZ_JEDEN
    CLR TR1			;ZATRZYMAJ T1
    MOV LICZNIK,#00H
    CLR P1.4
    LJMP PAUZA
    
    
    
    
    
    WLACZ_JEDEN:		; 10) I 11)
    CLR TR1			;ZATRZYMAJ T1	
    MOV TH1,#03CH		;DLA KWARCU 12MHz 				
    MOV TL1,#0B0H		; 1 PRZEPELNIENIE CO 0,05S
    MOV LICZNIK,#00H
    INC LICZNIK_JEDEN
    
    MOV A,#00H
    MOV A,#LICZNIK_JEDEN
    CJNE A,#01H,DWA
    SETB P1.4		;URUCHOM PIN 1.4
    SETB TR1		;START LICZNIKA
    LJMP TUTAJ
    
    DWA:
    MOV A,#00H
    MOV A,#LICZNIK_JEDEN
    CJNE A,#02H,TRZY
    CLR P1.4
    SETB TR1
    LJMP TUTAJ
    
    TRZY:
    MOV A,#00H
    MOV A,#LICZNIK_JEDEN
    CJNE A,#03H,CZTERY
    SETB P1.4
    SETB TR1
    LJMP TUTAJ
    
    CZTERY:
    MOV A,#00H
    MOV A,#LICZNIK_JEDEN
    CJNE A,#04H,PIEC
    CLR P1.4
    SETB TR1
    LJMP TUTAJ
    
    PIEC:
    MOV A,#00H
    MOV A,#LICZNIK_JEDEN
    CJNE A,#05H,SZESC
    SETB P1.4
    SETB TR1
    LJMP TUTAJ
    
    SZESC:
    MOV A,#00H
    MOV A,#LICZNIK_JEDEN
    CJNE A,#06H,SIEDEM
    CLR P1.4
    SETB TR1
    LJMP TUTAJ
    		
    
    SIEDEM:
    MOV A,#00H
    MOV A,#LICZNIK_JEDEN
    CJNE A,#07H,OSIEM
    SETB P1.4
    SETB TR1
    LJMP TUTAJ
    
    OSIEM:
    MOV A,#00H
    MOV A,#LICZNIK_JEDEN
    CJNE A,#08H,DZIEWIEC
    CLR P1.4
    SETB TR1
    LJMP TUTAJ
    
    DZIEWIEC:
    MOV A,#00H
    MOV A,#LICZNIK_JEDEN
    CJNE A,#09H,DZIESIEC
    SETB P1.4
    SETB TR1
    LJMP TUTAJ
    
    DZIESIEC:
    MOV A,#00H
    MOV A,#LICZNIK_JEDEN
    CJNE A,#0AH,JEDENASCIE
    CLR P1.4
    SETB TR1
    LJMP TUTAJ
    
    JEDENASCIE:
    LJMP KONCOWKA
    RETI
    
    
    
    PRZERWANIE_T1:
    INC LICZNIK		;14)
    CLR TR1			;15)
    MOV TH1,#03CH		;DLA KWARCU 12MHz 				
    MOV TL1,#0B0H		; 1 PRZEPELNIENIE CO 0,05S
    SETB TR1		;15)
    LJMP TUTAJ		;16)
    RETI
    
    PRZERWANIE_T0:
    INC LICZNIK_IMPULSOW 	;18)
    LJMP TUTAJ		;19)
    RETI
    
    PRZERW_T1:		;13)
    LJMP PRZERWANIE_T1
    
    
    PRZERW_T0:		;17)
    LJMP PRZERWANIE_T0
    
    PRZERW_INT1:		; 20)
    LJMP WLACZ_JEDEN	;21)
    RETI
    
    PRZERW_INT0:
    LJMP PRZERWANIE_INT0
    
    END


    wiem ze te skoki na koncu sa niepotrzebne ale tez nic nie szkodza, to pozostalosci po kombinowaniu z dublowaniem...

    a oto algorytm pod jaki pisalem ten program:

    START
    ODBLOKUJ PRZERWANIA
    WYLACZ PIN 1.4
    PETLA W KOLO (NIC NIE ROBIACA)
    KONIEC


    PRZERWANIE OD T1:
    ZWIEKSZ LICZNIK O 1
    USTAW TH1 TL1
    IDZ DO TUTAJ
    RETI

    PRZERWANIE OD T0:
    ZWIEKSZ LICZNIK IMPULSOW O 1
    IDZ DO TUTAJ
    RETI

    PRZERWANIE OD INT0:
    URUCHOM TIMER1 NA CZAS, T0 NA IMPULSY
    SPRAWDZ CZY JEST 1 NA P3.2 JESLI NIE:
    SPRAWDZ CZY LICZNIK ODLICZYL CZAS
    JESLI TAK: SPRAWDZ CZY LICZNIK IMPULSOW ODLICZYL IMPULSY
    JESLI LICZNIK POWYZEJ ODLICZYL CZAS SKOCZDO SPRAWDZANIA LICZNIKA IMPULSOW JESLI NIE ZAPETL DO SPRAWDZANIA CZY JEST 1 NA P3.2
    JESLI LICZNIK IMPULSOW SIE ZAPELNIL IDZ DO POCZATKU PROGRAMU
    JESLI NIE (***) PODAWAJ NA WYJSCIE P1.4 RAZ 1 RAZ 0 (CO JAKIS CZAS OKRESLONY TIMEREM), PO 11 CYKLACH ZAKONCZ PROGRAM
    RETI

    PRZERWANIE OD INT1:
    IDZ DO (***)
    RETI

    Teraz wymyslilem ze nie moge (?) skoczyc z przerwania do procedury z innego przerwania?
    z gory dzieki wszystkim za pomoc!
  • REKLAMA
  • #10 2735424
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 51
    MooNTER napisał:
    dzieki, czegos sie nauczylem ...

    Chyba raczej nie :cry:
    Popełniasz szkolne błędy i chyba nie korzystasz z żadnej "pomocy".
    
    ORG 003BH			;PRZERWANIE OD INT0
    LJMP PRZERW_INT0
    

    To na pewno dobry adres :?:
    
    START:
    LICZNIK EQU 0    
    LICZNIK_JEDEN EQU 0 
    LICZNIK_IMPULSOW EQU 0 
    

    Trzy "zmienne" pod tym samym adresem :?:
    
    MOV A,#00H		;to jest raczej niepotrzebne
    MOV A,#LICZNIK  ;zapisz w akumulatorze adres zmiennej LICZNIK
    ;powinn być
    MOV A,LICZNIK  ;zapisz w akumulatorze zawartość zmiennej LICZNIK
    

    Przecież to 2 takie same instrukcje , gdyż LICZNIK EQU 0 :!:
    Popraw się , bo będzie źle :D

    Piotrek
  • #11 2735509
    MooNTER
    Poziom 12  
    Posty: 107
    Ocena: 3
    zumek napisał:

    ORG 003BH

    To na pewno dobry adres :?:


    NIE, juz sie poprawiam
    Cytat:

    
    START:
    LICZNIK EQU 0    
    LICZNIK_JEDEN EQU 0 
    LICZNIK_IMPULSOW EQU 0 
    

    Trzy "zmienne" pod tym samym adresem :?:


    ja to rozumialem tak, ze musze na poczatku zdefiniowac typ zmiennej i jej wartosc (zmienna EQU wartosc). Po equ mam podac adres gdzie ma siedziec ta zmienna ??
    Cytat:

    
    MOV A,#00H		;to jest raczej niepotrzebne[/quote]
    no w sumie tak
    [quote]
    MOV A,#LICZNIK  ;zapisz w akumulatorze adres zmiennej LICZNIK
    ;powinn być
    MOV A,LICZNIK  ;zapisz w akumulatorze zawartość zmiennej LICZNIK
    

    Piotrek


    ok dzieki :)[/quote]
  • #12 2736413
    MooNTER
    Poziom 12  
    Posty: 107
    Ocena: 3
    dobra, poszukalem lepszego wytlumaczenie, bo z tego co mialem niewiele mozna bylo sie dowiedziec...
    to tak: EQU to stala, ktorej nie mozna zmienic w programie
    jezeli zamienie EQU na DS i dam zmienna DS 1 to zarezerwuje 1 bajt dla tej zmiennej.
    nastepnie po deklaracji wpisalem zera do tych zmiennych:
    MOV LICZNIK,#00H  ;itd...
    


    powinno juz zadzialac? cos dalej nie chodzi...
  • #13 2737018
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 51
    MooNTER napisał:
    ...powinno juz zadzialac? cos dalej nie chodzi...

    Tak napisałeś program , że nie może działać.
    Np. jeśli procek dojdzie do tego miejsca (wykona obsługę INT0)...
    
    PAUZA:
    LJMP PAUZA
    ...
    PRZERWANIE_INT0:
    ...
    NIE:                   ;SPRAWDZA CZY JEST 1 NA 3.2 7)
    JB P3.2,LICZ_IMPULSOW       ;JESLI NIEZAMKNIETO IDZ DALEJ JESLI ZAMKNIETO SKOCZ
    ;tej pętli nie przerwie nic , poza ustawieniem P3.2 na "1"
    ;timery pracują pełną parą , ale nie wykonują sie przerwania od nich 
    ;bo procek nadal obsługuje przerwanie o najwyższym priorytecie i mimo ;przepełnień timera , LICZNIK nie zwiększa swojej wartości
    TUTAJ:
    MOV A,#00H      ; 8)
    MOV A,LICZNIK
    CJNE A,#064h,NIE   ;JESLI LICZNIK SIE NIE ZAPELNIL SKOCZ DO NIE
             ;JESLI SIE ZAPELNIL SPRAWDZ LICZNIK_IMPULSOW
    
    
    LICZ_IMPULSOW:      ;ZAMKNIETO OBUDOWE W 7)
    MOV A,#00H      ; 9)
    MOV A,#LICZNIK_IMPULSOW
    CJNE A,#01H,WLACZ_JEDEN   ;JEZELI LICZNIK_IMPULSOW SIE ZAPELNIL IDZ DALEJ
             
    
    KONCOWKA:
    MOV LICZNIK_JEDEN,#00H   ;ZERUJ LICZ_JEDEN
    CLR TR1         ;ZATRZYMAJ T1
    MOV LICZNIK,#00H
    CLR P1.4
    ;jeśli "dojdzie" do poniższego miejsca , to klapa na całej linii , wsystkie ;przerwania , łącznie z INT0 są zablokowane , przez brak rozkazu RETI. 
    LJMP PAUZA
    

    W Twoim kodzie takich "kwiatków" jest więcej :(

    Piotrek
  • #14 2739388
    MooNTER
    Poziom 12  
    Posty: 107
    Ocena: 3
    Troche poprawilem, nie wiem tylko czy jesli jest:
    1)przerwanie:
    .
    .
    .
    LJMP gdziestam
    RETI

    to czy procesor rozpozna ze jest tu koniec przerwania czy musze najpierw skoczyc a pozniej zakonczyc przerwanie?
    2) w jakims opisie znalazlem zeby wpisac PUSH i POP ale wlasciwie nie wiem co mi to da (bylo to w przypadku licznika czasu) i gdzie to uzyc? czy przez to program mi nie dziala?

    
    ORG 000H
    LJMP START	              ;IDZ DO START
    ORG 0003H			;PRZERWANIE OD INT0
    LJMP PRZERW_INT0
    ORG 000BH		      ;PRZERWANIE OD T0
    LJMP PRZERW_T0
    ORG 0013H		      ;PRZERWANIE OD INT1
    LJMP PRZERW_INT1 
    ORG 001BH 		      ;PRZERWANIE OD T1
    LJMP PRZERW_T1
    START:
    LICZNIK DS 1
    LICZNIK_JEDEN DS 1
    SETB ET0         	      ;ODBLOKUJ T0 1) 
    SETB ET1       		      ;ODBLOKUJ T1 	1)
    setb EX0	
    SETB EX1		      ;ODBLOKUJ /INT1	1)
    SETB EA        		      ;ODBLOKUJ PRZERWANIA 1)
    CLR P1.4                      ;WYLACZ COSTAM 2)
    SETB IT1		;PRIORYTETY PRZERWAN
    SETB IT0		;...
    SETB PT1
    CLR PT0
    CLR PX1
    CLR PX0
    MOV  TMOD,#00010110B	      ;USTAW T0 W TRYB ZLICZ IMP. 			;WEJSC,T1-ODMIERZA CZAS
    MOV TH0,#0FEh  		      ;FEh=256-2=254 CZYLI ZLICZA 2 				;IMPULSY
    MOV TL0,TH0		      ;konieczne!
    MOV TH1,#04CH		;DLA KWARCU 12MHz 				
    MOV TL1,#000H		; 1 PRZEPELNIENIE CO 0,05S
    PAUZA:
    LJMP PAUZA
    PRZERWANIE_INT0:
    			;TERAZ WLACZAMY T1: 5)
    SETB TR1		;WLACZA T1
    			;A TERAZ WLACZAMY T0:  6)
    SETB TR0		      ;WLACZA LICZNIK T0
    LJMP NIE
    RETI
    NIE:		           
    JB P3.2,WLACZ_JEDEN      ;JESLI NIEZAMKNIETO IDZ DALEJ JESLI ZAMKNIETO SKOCZ
    TUTAJ:
    MOV A,#00H		; 8)
    MOV A,LICZNIK
    CJNE A,#064h,NIE	;JESLI LICZNIK SIE NIE ZAPELNIL SKOCZ DO NIE
    			;JESLI SIE ZAPELNIL SPRAWDZ LICZNIK_IMPULSOW
    WLACZ_JEDEN:		;WLACZA JEDEN 10) I 11)
    CLR TR1			;ZATRZYMAJ T1	
    MOV TH1,#04CH		;DLA KWARCU 12MHz 				
    MOV TL1,#000H		; 1 PRZEPELNIENIE CO 0,05S
    MOV LICZNIK,#00H
    INC LICZNIK_JEDEN
    MOV A,#00H
    MOV A,LICZNIK_JEDEN
    CJNE A,#01H,DWA
    SETB P1.4		;URUCHOM 1.4
    SETB TR1		;START LICZNIKA
    LJMP TUTAJ
    DWA:
    MOV A,#00H
    MOV A,liczNIK_JEDEN
    CJNE A,#02H,TRZY
    CLR P1.4
    SETB TR1
    LJMP TUTAJ
    TRZY:
    MOV A,#00H
    MOV A,liczNIK_JEDEN
    CJNE A,#03H,CZTERY
    SETB P1.4
    SETB TR1
    LJMP TUTAJ
    CZTERY:
    MOV A,#00H
    MOV A,liczNIK_JEDEN
    CJNE A,#04H,PIEC
    CLR P1.4
    SETB TR1
    LJMP TUTAJ
    PIEC:
    MOV A,#00H
    MOV A,liczNIK_JEDEN
    CJNE A,#05H,SZESC
    SETB P1.4
    SETB TR1
    LJMP TUTAJ
    SZESC:
    MOV A,#00H
    MOV A,liczNIK_JEDEN
    CJNE A,#06H,SIEDEM
    CLR P1.4
    SETB TR1
    LJMP TUTAJ
    SIEDEM:
    MOV A,#00H
    MOV A,liczNIK_JEDEN
    CJNE A,#07H,OSIEM
    SETB P1.4
    SETB TR1
    LJMP TUTAJ
    OSIEM:
    MOV A,#00H
    MOV A,liczNIK_JEDEN
    CJNE A,#08H,DZIEWIEC
    CLR P1.4
    SETB TR1
    LJMP TUTAJ
    DZIEWIEC:
    MOV A,#00H
    MOV A,liczNIK_JEDEN
    CJNE A,#09H,DZIESIEC
    SETB P1.4
    SETB TR1
    LJMP TUTAJ
    DZIESIEC:
    MOV A,#00H
    MOV A,liczNIK_JEDEN
    CJNE A,#0AH,JEDENASCIE
    CLR P1.4
    SETB TR1
    LJMP TUTAJ
    JEDENASCIE:
    LJMP KONCOWKA
    PRZERWANIE_T1:
    INC LICZNIK		;14)
    CLR TR1			;15)
    MOV TH1,#03CH		;DLA KWARCU 12MHz 				
    MOV TL1,#0B0H		; 1 PRZEPELNIENIE CO 0,05S
    SETB TR1		;15)
    LJMP TUTAJ		;16)
    RETI
    PRZERWANIE_T0:	
    LJMP KONCOWKA		;19)
    RETI
    PRZERW_T1:		;13)
    LJMP PRZERWANIE_T1
    PRZERW_T0:		;17)
    LJMP PRZERWANIE_T0
    PRZERW_INT1:		; 20)
    LJMP WLACZ_JEDEN	;21)
    RETI
    PRZERW_INT0:
    LJMP PRZERWANIE_INT0
    KONCOWKA:
    CLR TR1			;ZATRZYMAJ T1
    MOV LICZNIK_JEDEN,#00H	;ZERUJ LICZ_JEDEN
    MOV LICZNIK,#00H
    CLR P1.4
    LJMP PAUZA
    END
  • #15 2739632
    GienekS
    Poziom 32  
    Posty: 1971
    Pomógł: 139
    Ocena: 15
    MooNTER napisał:
    Troche poprawilem, nie wiem tylko czy jesli jest:
    1)przerwanie:
    .
    .
    .
    LJMP gdziestam
    RETI
    Jeżeli takie coś wykonujesz to musisz to "gdziestam" zakończyć rozkazem RETI Lepiej to "gdziestam" wywołać LCALL ale to musisz pamiętać że musi się kończyć ta procedura rozkazem RET i wtedy będzie to OK!
  • #16 2739826
    MooNTER
    Poziom 12  
    Posty: 107
    Ocena: 3
    
    LICZNIK DS 1
    LICZNIK_JEDEN DS 1
    
    PRZERWANIE_T1:
    INC LICZNIK		;14)
    CLR TR1			;15)
    


    doszedlem do tego, ze INC LICZNIK nie zwieksza licznika - dlaczego?
    wlaczylem debuggera i przerwanie z t1 sie uruchamia przechodzi przez ta instrukcje ale nie zwieksza wartosci licznika

    i druga sprawa: normalnie po wykonaniu przerwania program wraca do nastepnego polecenia. Czy da sie zrobic tak, aby po wykonaniu przerwania skoczyl w konkretne miejsce? cos jak LJMP czy LCALL tyle ze one nie zakanczaja dzialania przerwania, ja chcialbym zakonczyc przerwanie (np RETI) ale nie przejsc do nastepnego polecenia w programie a do ustalonego miejsca

    Czy jesli dam tak:
    Przerwanie:
    .
    .
    LCALL gdziestam
    RETI
    
    gdziestam:
    ..
    RET
    nastepne instrukcje
    end
    

    to program wykona instrukcje do LCALL, przejdzie do gdziestam wykona instrukcje do RET, wroci do przerwania, zakonczy to przerwanie i a)Wroci do punktu w ktorym zostal przerwany program i uruchomione przerwanie b) uzna, ze ostatnia wykonywana instrukcja to ta przed RET i po zakonczeniu przerwania wykona nastepna instrukcje po RET ??
  • #17 2762110
    algebro
    Poziom 15  
    Posty: 118
    Pomógł: 8
    Ocena: 2
    MooNTER napisał:

    Czy da sie zrobic tak, aby po wykonaniu przerwania skoczyl w konkretne miejsce? cos jak LJMP czy LCALL tyle ze one nie zakanczaja dzialania przerwania, ja chcialbym zakonczyc przerwanie (np RETI) ale nie przejsc do nastepnego polecenia w programie a do ustalonego miejsca

    Jest to mozliwe, ale trzeba uwazać, aby odpowiednio poustawiać(wyzerować) znaczniki, zdjąć odpowiednia ilość danych ze stosu itd. Coś takiego kiedyś zastosowałem w mioim układzie. Najbezpieczniej jest zakończyć procedurę przerwania rozkazem RETI, ale tuż przed jej wykonaniem zmienić na stosie "oszukany" adres do którego powróci procesor. Ponieważ w czasie przyjecia przerwania, mikrokontroler odkłada adres, do którego ma powrócić, trzeba go zmienić, ale nie naruszjąc wskaźnika stosu:

    PRZERWANIE
    ...
    ...
    ...          ;to są wykonywane w czasie przerwania instrukcje)
    POP DANA     ;"DANA" to może być pamięć wewn lub rejestr specjalny
    POP DANA     ;który posłuży tutaj do zmniejszenia liczby danych na stosie
    PUSH NOWYL ;młodszy bajt adres nowego adresu skoku
    PUSH NOWYH ;starszy bajt nowego adresu skoku
    RETI


    Rozkazem POP po prostu sciągamy ze stosu prawdziwy adres powrotu i tracimy go, a w jego miejsce kładziemy nowy adres, którego wartość niestety możemy otrzymać czasem dopiero po kompilacji programu :!:
    Trzeba później uważać na zmiany w długości programu przy dopisywaniu linijek, które mogą przesunąć ten adres :!:
    Nowa wartość licznika (adres) musi znajdować się w komórkach NOWY L i H.
  • #18 2762879
    MooNTER
    Poziom 12  
    Posty: 107
    Ocena: 3
    Udalo mi sie w ten sposob (skacze do miejsce po zakonczeniu przerwania):
    
    przerwanie:
    .
    .
    .
    POP ACC
    POP ACC
    MOV A,#MIEJSCE
    PUSH ACC
    MOV A,#00H
    PUSH ACC
    RETI
    
  • #19 2763023
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 51
    MooNTER napisał:
    Udalo mi sie ...

    Ale tylko połowicznie :D
    
    POP ACC
    POP ACC
    MOV A,#MIEJSCE
    PUSH ACC
    MOV A,#00H ; nie zawsze to będzie pierwsze 256 bajtów
    PUSH ACC
    RETI 
    

    Tak można załadować dowolną 16-to bitową daną czy adres , do 8-io bitowych rejestrów , komórek itp.
    
    ...
    mov a,#miejsce-((miejsce/256)*256)
    push acc
    mov a,#miejsce/256
    push acc
    ...
    


    Piotrek

Podsumowanie tematu

✨ Dyskusja dotyczy programowania mikrokontrolera 89cxx51 w asemblerze, z zadaniem oczekiwania na sygnały logiczne na pinie P1.3 oraz sterowania pinem P1.4 w oparciu o przerwania i timery. Autor próbuje zaimplementować procedurę, która reaguje na stan logiczny "0" na P1.3, odmierza czas i wykonuje cykliczne włączanie/wyłączanie pinu P1.4, z uwzględnieniem impulsów na timerze T0 oraz przerwania INT1. W trakcie dyskusji pojawiły się problemy z poprawnym ustawieniem adresów przerwań (ORG), definiowaniem zmiennych (różnica między EQU a DS), obsługą przerwań (konieczność stosowania RETI na końcu procedury), a także zrozumieniem działania stosu i możliwości zmiany adresu powrotu z przerwania poprzez manipulację stosu (POP/PUSH). Zwrócono uwagę na błędy w kodzie, takie jak dublowanie adresów przerwań, niepoprawne użycie EQU do zmiennych, oraz blokowanie działania timerów podczas długich pętli w obsłudze przerwań. Zaproponowano użycie przerwań INT0/INT1 do wykrywania zmian stanów pinów zamiast programowego wyzwalania timerów. Omówiono także technikę zmiany adresu powrotu z przerwania przez modyfikację stosu, co pozwala na skok do wybranego miejsca po zakończeniu obsługi przerwania. Wskazano na konieczność poprawnego ustawienia priorytetów przerwań i właściwego zarządzania rejestrami w procedurach przerwań.
Wygenerowane przez model językowy.
REKLAMA