-
        

Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 17

Thema: PIC16F84A - CALL Problem - Programm Counter schuld?

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    07.01.2007
    Beiträge
    27

    PIC16F84A - CALL Problem - Programm Counter schuld?

    Anzeige

    Hey !

    hab gerade ein riesiges Problem. Mein PIC springt ab einer bestimmten Stelle nicht in ein Unterprogramm. Wenn ich an die gleiche Stelle ein anderes Unterprogramm CALLEN möchte tut er es auch nicht - als könne er von der Programmzeile aus nicht in ein Unterprogramm springen.


    Jetzt hab ich in auf der Sprut-Seite PIC fallen gefunden. Und bin auf das Problem mit dem PCL - Programmcounter gestoßen. Kann es sein, das bei mir das gleiche Problem besteht? Wenn ja, wie kann ich es lösen ?

    http://www.sprut.de/electronic/pic/f....html#tabellen

  2. #2
    Erfahrener Benutzer Roboter Genie Avatar von BMS
    Registriert seit
    21.06.2006
    Ort
    TT,KA
    Alter
    26
    Beiträge
    1.192
    Hi

    Ganz nützlich wäre vielleicht ein Codeschnipsel. Könnte sein, dass du irgendeine Bedingung (btfss etc.) eingebaut hast, die nie/immer erfüllt wird und er den call-befehl überspringt
    ansonsten - zu call:
    Spruts Kommentar zu Call
    Call arbeitet 11bittig -> 2^11 Adressen möglich =2048-> reicht für 2k speicher;
    erstze mal den call-befehl durch irgendeinen bsf/bcf-Befehl und schalte damit z.B. eine Led an. Wenn sich nichts tut, liegts eindeutig an der Logik des Programms. Du schreibst schon in assembler, oder?
    obwohl der call-befehl 11bittig-arbeitet, könntest du probeweise mal mit dem org-befehl den programcounter manipulieren...vielleicht bringts was (wenn man was sucht, ist es immer an der stelle, wo man es am wenigsten vermutet...)

    Mfg
    BMS

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    07.01.2007
    Beiträge
    27
    Ah danke!
    Am CALL dürfte es dann aber allerding nicht liegen, da ich 1. nicht so viel Befehle habe und 2. mein PIC nur max 1024 Befehle aufnehmen kann.

    Hier is mal der Code:

    UP_Show_btns wird nicht aufgerufen!
    Ich vermute es liegt an der Tabelle tab_Joy, hab aber anstatt der Register auch schon konstante Werte in die Tabelle geschrieben... trotzdem Fehlanzeige.

    Code:
    main	
    	BSF	a_ATT		; ATT auf HIGH, Controller wird abgewählt
    				; (ignoriert alle Daten)
    	CALL	UP_wait_25us
    	BSF	a_CLOCK		; Clock HIGH
    	BSF	a_COMMAND	; Command HIGH
    	
    	BCF	a_ATT		; ATT auf LOW das der Controller
    				; die Daten annimmt
    					
    	CALL	UP_wait_50us	; Warteschlange bis Controller bereit ist
    									
    	CALL	UP_Start		;Senden:		H'01' Startbefehl
    	
    	CALL	UP_Get_Type	;Senden:		H'42' Datenanfrage
     				;------------------------------------
    				;Empfangen:	H'41'=Digital
     				;ODER		H'23'=NegCon
    				;ODER		H'73'=Analogue Red LED
    				;ODER		H'53'=Analogue Green LED
    
    	CALL	UP_Get_Status	;Empfangen:  H'5A' - Status:READY
    				;------------------------------------
    				;Senden:     H'00' - Idle-Modus
    
    	CALL	UP_Get_L_btns	;Empfangen:  H'xx' - Status der linken Btns
    				;------------------------------------
    				;Senden:     H'00' - Idle-Modus
    
    	CALL	UP_Get_R_btns	;Empfangen:  H'xx' - Status der rechten Btns
    				;------------------------------------
    				;Senden:     H'00' - Idle-Modus
    
    	CALL	UP_Get_R_Joy_X	;Empfangen:  H'xx' - rechtes Joystick, X-Achse
    				;------------------------------------
    				;Senden:     H'00' - Idle-Modus
    
    	CALL	UP_Get_R_Joy_Y	;Empfangen:  H'xx' - rechtes Joystick, Y-Achse
    				;------------------------------------
    				;Senden:     H'00' - Idle-Modus
    
    	CALL	UP_Get_L_Joy_X	;Empfangen:  H'xx' - linkes Joystick, X-Achse
    				;------------------------------------
    				;Senden:     H'00' - Idle-Modus
    
    	CALL	UP_Get_L_Joy_Y	;Empfangen:  H'xx' - linkes Joystick, Y-Achse
    				;------------------------------------
    				;Senden:     H'00' - Idle-Modus
    
    	CALL	UP_Show_btns	;Ausgabe der gXXXX (g=> GET) Register
    	
    GOTO	main			;Springe wieder an den Anfang zurück

    Code:
    ;###############################################################################
    UP_Show_btns
             MOVLW	D'1'
    	MOVWF	zaehler		;Zaehler auf 1 setzten
    	
    Show_1	CLRF	PORTB		;PORTB (Anzeige löschen)
             MOVF	zaehler,W	;Zaehler ins Wreg. um mit PCL zu addieren
    	CALL	tab_Joy		;Wert aus Tabelle... 	
             MOVWF	PORTB		;... an PORTB anzeigen...
             
    	CALL	UP_wait_05s	;...(eine halbe Sekunde)
    	
    	INCF	zaehler		;Zaehler erhöhen (+1)
    	MOVLW	D'5'		;Zaehler mit der Zahl 5
    	SUBWF	zaehler,W	;subtrahieren (Ergebnis ins Wreg.) um
    	BTFSC	STATUS,C		;Zaehler auf 5 zu prüfen
    	RETURN			;<--- Zaehler = 5
    	GOTO	Show_1		;<--- Zaehler < 5
    ;###############################################################################
    Code:
    ;#########################    L/R Joystick Tabelle    ##########################
    
    tab_Joy	;zaehler maximal bis 5
    	ADDWF	PCL,F		; Anzeigen der Position des  
    	DT	gRJoyX,gRJoyY	; des rechten [x-Achse,y-Achse]...
    	DT	gLJoyX,gLJoyY	; und linken [x-Achse,y-Achse] Joysticks
    Achso ja.... wenn ich keine Tabellen in meinem Programm habe und UP_Show_btns aus "Spagetti-Code" besteht... funktioniert es!

    Code:
    UP_Show_btns
    ;Ausgabe der Register in denen der Status und die einzelnen Zustände der Buttons stehen 
             CLRF	PORTB
             BSF	PORTB,0		;Register LED (STATUS) [DEBUGGING]
             CALL	UP_wait_05s
             CLRF	PORTB
    ;#########         
    	MOVFW	gSTATUS		;Status Register
             MOVWF	PORTB		;an PORTB anzeigen
             CALL	UP_wait_05s
    ;##################         
             
             CLRF	PORTB
             BSF	PORTB,1		;Register LED (LINKS) [DEBUGGING]
             CALL	UP_wait_05s
             CLRF	PORTB
    ;#########         
    	MOVFW	gLEFT		;LINKS Register
             MOVWF	PORTB		;an PORTB anzeigen
             CALL	UP_wait_05s
    ;##################         
             
             CLRF	PORTB
             BSF	PORTB,2		;Register LED (RECHTS) [DEBUGGING]
             CALL	UP_wait_05s
             CLRF	PORTB
    ;#########         
             MOVFW	gRIGHT		;RIGHT Register
             MOVWF	PORTB		;an PORTB anzeigen
             CALL	UP_wait_05s
    ;##################         
             
             CLRF	PORTB
             BSF	PORTB,3		;Register LED (rechtes Joxstick x-Achse) [DEBUGGING]
             CALL	UP_wait_05s
             CLRF	PORTB
    ;#########         
             MOVFW	gRJoyX		;RJoyX Register
             MOVWF	PORTB		;an PORTB anzeigen
             CALL	UP_wait_05s
    ;##################
             
             CLRF	PORTB
             BSF	PORTB,4		;Register LED (rechtes Joxstick y-Achse) [DEBUGGING]
             CALL	UP_wait_05s
             CLRF	PORTB
    ;#########
             MOVFW	gRJoyY		;RJoyY Register
             MOVWF	PORTB		;an PORTB anzeigen
             CALL	UP_wait_05s
    ;##################
             
             CLRF	PORTB
             BSF	PORTB,5		;Register LED (linkes Joxstick x-Achse) [DEBUGGING]
             CALL	UP_wait_05s
             CLRF	PORTB
    ;#########
             MOVFW	gLJoyX		;LJoyX Register
             MOVWF	PORTB		;an PORTB anzeigen
             CALL	UP_wait_05s
    ;##################
             
             CLRF	PORTB
             BSF	PORTB,6		;Register LED (linkes Joxstick x-Achse) [DEBUGGING]
             CALL	UP_wait_05s
             CLRF	PORTB
    ;#########
             MOVFW	gLJoyY		;LJoyY Register
             MOVWF	PORTB		;an PORTB anzeigen
             CALL	UP_wait_05s
             
    RETURN

  4. #4
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    07.12.2005
    Ort
    Euskirchen-Großbüllesheim
    Alter
    67
    Beiträge
    2.063
    Der Fehler liegt an der Tabelle:
    Code:
    	MOVF	zaehler,W	;Zaehler ins Wreg. um mit PCL zu addieren
    	CALL	tab_Joy		;Wert aus Tabelle...
    	.....
    
    
    tab_Joy		;zaehler maximal bis 5
    	ADDWF	PCL,F		; Anzeigen der Position des
    	DT	gRJoyX,gRJoyY	; des rechten [x-Achse,y-Achse]...
    	DT	gLJoyX,gLJoyY	; und linken [x-Achse,y-Achse] Joysticks
    Du rufst mit CALL die Tabelle auf; der ProgrammCounter steht dann auf der Adresse des 1. Tabelleneintrags.
    Dort addierst Du zum PCL einen Wert aus dem W-Register; was steht im PCLATH ?
    Wenn zum PCL ein Wert addiert wird, springt der µC zu der errechneten Adresse; was sind das für Befehle in der Tabelle ? Und wo kommt ein RETURN für den Rücksprung ?
    Wenn Du nur einen 8-Bit-Wert aus der Tabelle laden möchtest, dann trage in die Tabelle 'RETLW Rückgabewert' ein, damit geht es.
    Benötigst Du mehrere Bytes, springe mit GOTO an Stellen, wo Bytes in Speicherstellen abgelegt werden.
    Alternativ kannst Du eine Tabelle mit Daten erstellen und diese über indirekte Adressierung auslesen.
    Eine Tabelle muß für 'Computed GOTO' Befehle enthalten, wobei eigentlich nur GOTO xxx oder RETLW zzz sinnvoll ist.
    Schau Dir mal dieses Beispiel an.
    MfG Karl-Heinz
    HobbyElektronik hier klicken ....

  5. #5
    Neuer Benutzer Öfters hier
    Registriert seit
    07.01.2007
    Beiträge
    27
    hey,

    danke für die schnelle Antwort!

    Ich denk ja auch das es an der Tabelle liegt, aber das
    mit RETLW kann ich nicht ganz nachvollziehen da ich
    folgendes gelernt habe:

    Mit DT lässt sich eine Wertetabelle aufbauen. Dabei steht
    jeder Wert für die Anweisung 'RETLW <wert>'. Die Tabelle
    lässt sich also alternativ auch mit einer Liste von
    'RETLW'-Anweisungen aufbauen.
    Ich denk eher das meine "dynamische" Tabelle falsch ist
    bzw. das in Assembler keine dyn. Tabellen möglich sind.
    RETLW heißt ja das er aus dem Unterprogramm rausgehen
    soll und dabei ins W-Reg. eine KONSTANTE läd. In meiner Tabelle
    sollen ja aber ein Register zurückgegeben werden, keine KONSTANTEN!

  6. #6
    Erfahrener Benutzer Lebende Robotik Legende Avatar von PICture
    Registriert seit
    10.10.2005
    Ort
    Freyung bei Passau in Bayern
    Alter
    66
    Beiträge
    10.970
    Hallo t0b4d!

    Ich vermute, dass bei Dir vor dem Sprung in die Tabelle, der PCH nicht den richtigen Wert hat. Schau mal, bitte, :

    http://www.roboternetz.de/phpBB2/viewtopic.php?t=19714

    MfG

  7. #7
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    07.12.2005
    Ort
    Euskirchen-Großbüllesheim
    Alter
    67
    Beiträge
    2.063
    Hallo t0b4d,
    was Du bezüglich 'DT' gelernt hast, ist richtig, mir war es entfallen, weil ich 'DT' nicht benutze; ich mußte erst wieder nachschlagen.
    Für mich ist es einfacher 'RETLW' zu lesen, als DA, DB, DE, DT, DW; das sieht nach Daten aus.
    Und wie Du siehst, bin ich prompt wieder drauf reingefallen.

    Ich hatte ja schon gefragt, was in PCLATH steht und denke auch, daß der Fehler dort liegt.

    Edit:
    Zitat Zitat von t0b4d
    In meiner Tabelle sollen ja aber ein Register zurückgegeben werden, keine KONSTANTEN!
    Eine Register-Adresse ist auch eine Konstante. Adressen kannst Du in einer RETLW-Tabelle ablegen und anschließend durch indirekte Adressierung den Inhalt des Registers laden.
    Alternativ kannst Du in der Tabelle auch 'GOTO' benutzen und bei den Sprungzielen den Inhalt der Register laden ('RETURN' nicht vergessen).
    MfG Karl-Heinz
    HobbyElektronik hier klicken ....

  8. #8
    Neuer Benutzer Öfters hier
    Registriert seit
    07.01.2007
    Beiträge
    27
    Zitat Zitat von PICture
    Hallo t0b4d!

    Ich vermute, dass bei Dir vor dem Sprung in die Tabelle, der PCH nicht den richtigen Wert hat. Schau mal, bitte, :

    http://www.roboternetz.de/phpBB2/zei...ag.php?t=19714

    MfG
    Zitat Zitat von kalledom
    ...
    Ich hatte ja schon gefragt, was in PCLATH steht und denke auch, daß der Fehler dort liegt. ....

    Ich wollt mich eigentlich vor diesem Problem drücken (weil ich das nicht so ganz verstanden hab),
    da es jetzt aber anscheinend nicht mehr anders geht muss ich mir die Funktionsweise des PCLATH genauer anschaun.

    Das was ich bis jetzt verstanden hab ist:

    Programmcounter besteht aus: PCLATH,PCL
    Der PCL deckt folgenden Bereich ab -> 2^0 - 2^7
    Der PCLATH deckt folgenden Bereich ab -> 2^8 - 2^10 (mein PIC kann max. 1024 Befehle speichern)

    Mit dem 8. stelligen PCL kann ich also nur im Bereich von 0 bis Programmzeile 2^7 (12 springen.
    Da mein Code bzw meine Tabelle nicht in diesem Bereich liegt
    muss ich jetzt mit dem höherwertigen Byte des Programmzählers arbeiten (PCLATH).

    Jetzt stelle ich mir aber die Frage (ohne vorher mich informiert zu haben) wenn ich den PCLATH verändere, wird er nach dem Zeilenaufruf der Tabelle (zb. RETLW gStatus) wieder durch das RETURN zurückgestellt ?

    Edit:
    Ich hab auf google folgendes gefunden:
    http://www.staff.uni-bayreuth.de/~bt...rtechniken.pdf
    kann es aber erst heute abend testen wenn ich wieder zuhause bin.

  9. #9
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    07.12.2005
    Ort
    Euskirchen-Großbüllesheim
    Alter
    67
    Beiträge
    2.063
    Zitat Zitat von t0b4d
    Programmcounter besteht aus: PCLATH,PCL
    Nein; der Programmcounter besteht aus PCH und PCL.
    Bei "Instruction with PCL as Destination" wird der Inhalt von PCLATH an PCH übergeben, bei Aufrufen in andere ROM-Pages werden die Bits 3...x von PCLATH an PCH übergeben.
    Vor der Veränderung von PCL oder bei GOTO / CALL in eine andere Rom-Page mußt Du unbedingt PCLATH bedienen.
    Einen Link zu einem Beispiel hatte ich Dir ja schon gegeben.

    Edit1: PCL ist 8 Bit breit, also von 0....255 / 0x??00...0x??FF, PCH je nach PIC, maximal 8 Bit.
    Edit2: Was in dem Link steht, steht auch im Datenblatt (in englisch).
    Das Beispiel setzt für eine 256-Byte-Tabelle voraus, daß diese bei Adresse 0x??00 beginnt, in meinem Beispiel ist das egal.
    Edit3: PCLATH = Programm-Counter-LATch-High
    MfG Karl-Heinz
    HobbyElektronik hier klicken ....

  10. #10
    Neuer Benutzer Öfters hier
    Registriert seit
    07.01.2007
    Beiträge
    27
    Danke für die Verbesserung!

    Das das Beispiel im Datenblatt steht hab ich versäumt was kein wunder ist weil ich es mir wirklich nicht ganz angeschaut habe. Wir sind in der Schule die wichtigsten Seiten durchgegangen, was nicht viele waren!

    Das Beispiel ist ja aber wie auch beschrieben nur möglich wenn ich die Tabelle an eine konstante Stelle im Speicher schreibe. Ich denk das is bei mir kein Problem ich werde trotzdem auf dein Vorschlag eingehen, wenn ich das andere hinbekommen habe.

    Jetzt bleibt mir bisher noch eine Frage offen (kann es zZ. nicht testen).

    Kann man mit ...

    Code:
    	CBLOCK	H'20'
    	...
    		gLEFT		;Linke Tasten
    	...
    	ENDC
    
    	...
    	...
    
    	main
    	...
    	MOVLW	gLEFT		; Linke Tasten
    	MOVWF	PORTB		; auf PORTB ausgeben
    	...
    ... ein Register an PORTB anzeigen lassen? Ich dachte LW steht für konstanter Wert ins Workregister. Ein Register kann sich ja aber aendern (was es bei mir auch macht) und es dafür ja extra den Befehl gibt MOVFW gLEFT ?

    wenn es mit MOVLW gehen sollte, dann kann ich in der Tabelle ja weiterhin mit RETLW <register> arbeiten, wenn nicht muss ich wie vorhin gesagt wurde ein GOTO verwenden und darin das Register in das Arbeitsregister kopieren.

    Code:
    MOVFW gLEFT 
    RETURN           ;<---- weil Tabelle mit CALL aufgerufen wurde

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •