PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Assemblerbefehl: bcf kann ich nur einmal verwenden



pointhi
30.05.2009, 14:41
Ich bin noch kein so erfahrener Programmierer und arbeite darum noch viel mit der Ansteuerung von LEDs in bestimten Reihenfolgen, damit ich mein Wissen über Assembler verbessere, und die Fehlerquote beim Programmieren sinkt.
Also habe ich wieder einmal ein Programm geschrieben, dass auf eiem neuem selbstgelötetes Board als Positionsleuchtensteuerung für Modellfahrzeuge eingesetzt werden soll.
Das erste Programm lief Fehlerlos, weil ich dabei alle ausgänge nur auf 1 setzte. Alle LEDs Leuchteten.
Beim Zweiten Programm, wollte ich 3 LEDs einschalten, nach 250ms ausschalten, noch einmal 250ms warterten, und dann auch den dritten Led asuschalten. Dass solte sich dann nach 750ms wiederholen. Also schrieb ich dass Programm, und wollte einen neue Methode benützen. Sie war Länger, man konnte aber auch andere LEDs eingeschaltet haben. Dieses Mal schrieb ich aslo nicht in Binärwärten in dass W Register, und kopierte es an PORTA, sondern schrieb an diese Stelle

bsf PORTA,0
bsf PORTA,1
bsf PORTA,2

Ich probierte dass Programm, und ich wunderte mich, dass nur der LED leuchtete, der als letztes auf 1 gestellt wurde. Ich musste das Programm wieder auf die Alte Methode umschreiben, aber ich frage mich noch immer, warum die anderen 2 LEDs nicht geleuchtet haben. Ich habe nämlich die 5 LEDs, die noch von dem 1. Test darin steckten, nicht herausgezogen. Ich hoffe ich hab dass nicht zu kompliziert beschrieben, und ihr könnt mir helfen.

:-s

Vielleicht hilft es, ich hab dass Programm auf den PIC 16F630 gebrannt

PICVB
30.05.2009, 14:48
wenn man das ganze Programm sieht ist es leichter einen Fehler zu finden. so kann man nur raten.
Aber die Methode mit bsf sollte funktionieren. Ich hab das auch am Anfang so gemacht.

Gruß Carsten

pointhi
30.05.2009, 14:52
ES könnte etwas Dauern, aber wenn ich zeit habe, kopiere ich dass komplette Programm in dass Forum

theborg
30.05.2009, 16:25
hi haste die Analogen PIns auf digital geschaltet ?

phaidros
30.05.2009, 17:16
BSF sollte man möglichst nicht direkt mit PORTs verwenden.
BSF ist nämlich ein "Read-Modify-Write" Befehl, d. h. es wird erst der aktuelle Wert von PortA gelesen, dann entsprechend modifiziert und dann zurückgeschrieben. Das Dumme ist, es wird nicht immer das gelesen, was man zuletzt in den Port reingeschrieben hat, sondern das, was gerade an den Pins an Spannung anliegt. Funktioniert zwar unter bestimmten Umständen trotzdem, aber sicherer ist es, ein sogenanntes Shadow-Register zu benutzen. Der gewünschte Zustand des Ports wird in dieses Schatten-Register geschrieben und kann dann auch gefahrlos mit BSF, BCF usw. geändert werden. Dann wird der gesamte Inhalt des Shadow-Registers in einem Rutsch auf den Port gelegt mit MOVF shadow,PORTA.

theborg
30.05.2009, 18:56
beim 16f gibs des nicht erst bei den 18ern

OB per movf oder bsf,bcf ist wurst bei bsf,bcf ist nur der unterschid das das Reg, PORTB nach W geschrieben wird und da verändert und dann zurück zu PORTB geschrieben.

bei Movf schiebst die 8bit nach W und von da nach PORTB also ein par takte weniger bei leds aber unwichtig und du musst immer die kompletten 8bit schreiben.

Ansonsten würde ich noch tipen das du entweder die pins nicht auf digital geschaltet hast oder das du in der falschen bank bist.

pointhi
03.06.2009, 11:49
Danke für die Hilfe. Ich hab es mir schon ein wenig angeschaut. Dass Datenblatt werde ich schon Bald reinstellen. Ich habe ein paar Probleme, es kompakt anzuzeigen.

pointhi
03.06.2009, 11:51
Hier ist dass versprochene Programm. Vielleicht kommt ihr damit ja weiter. Nach meinem wissen, ist der PIC 16F630 mit keinem Anologausgang ausgestadtet.


************************************************** ****************************
; Dateiname: Positionsbeleuchtung ohne Landebeleuchtung
; Autor: Thomas Pointhuber
; Datum: 25.05.09
; Version: 1.00
;
; Letzte Änderung: keine
;
;************************************************* *****************************
; Funktionsbeschreibung des Programms: Erstellt ein Blinklicht auf dem PORTA (0,1,2)
;
; RA,0 Positionsleuchte rechts
; RA,1 Positionsleuchte links
; RA,2 Positionsleuchte unten
; RC,1 Landeleuchte Flügel
; RC,2 Landeleuchte Propeller, Höhenruder, Seitenruder
;
;************************************************* *****************************
list p=16F630 ; "list" Anweisung zur Definition des Prozessors
#include <p16f630.inc> ; Einbinden von speziellen zum Controller gehörenden Variablen über die Datei *.inc

__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _CPD_OFF
;
; '__CONFIG' Diese Anweisung wird benutzt, um das Configurations-Word innerhalb des *.asm Datei einzubinden.
; Weitere Informationen zum Configurations-Word können auch dem Datenblatt entnommen werden.
; Die mit einem Sternchen * markierten Optionen sind ausgewählt worden.
;
; CP: Code Protection bit
; * OFF = Program Memory code protection is disabled
; ON = Program Memory code protection is enabled
; WDT: Watchdog Timer Enable bit
; ON = WDT enabled
; * OFF = WDT disabled
; BODEN: Brown-out Detect Enable bit
; * ON = BOD enabled
; OFF = BOD disabled
; PWRTE: Power-up Timer Enable bit
; OFF = PWRT disabled
; * ON = PWRT enabled
; MCLRE: GP3/MCLR pin function select
; ON = GP3/MCLR pin function is MCLR
; * OFF = GP3/MCLR pin function is digital I/O
; CPD: Data Code Protection bit
; * OFF = Data memory code protection is disabled
; ON = Data memory code protection is enabled
; Oscillator Variationen:
; LP_OSC = Low power crystal on GPIO4 and GPIO5
; XT_OSC = Crystal/resonator on GPIO4 and GPIO5
; HS_OSC = High speed crystal/resonator on GPIO4 and GPIO5
; EC_OSC = I/O function on GPIO4 pin, CLKIN on GPIO5
; * INTRC_OSC_NOCLKOUT = I/O function on GPIO4 pin, I/O function on GPIO5
; INTRC_OSC_CLKOUT = CLKOUT function on GPIO4 pin, I/O function on GPIO5
; EXTRC_OSC_NOCLKOUT = I/O function on GPIO4 pin, RC on GPIO5
; EXTRC_OSC_CLKOUT = CLKOUT function on GPIO4 pin, RC on GPIO5
;
;
ERRORLEVEL -302 ; Unterdrücken BANK SELECTION MESSAGES, dazu das ; Semikolon links entfernen
; ; Dies unterdrückt im Compiler die Nachricht "Register in operand not in bank 0. Ensure that bank bits are correct"
;
;************************************************* ****************************
; Deklaration der Variablen und Konstanten
;************************************************* *****************************
;
schleife EQU H'0020' ; Anzahl der "schleifen"
help EQU H'0021' ; Hilfsvariable für verschiedene Aufgaben. Achtung der Inhalt wird nie gerettet!
sekunde EQU H'0022' ; Variable für die Einerstelle der Zahl
leuchten1 EQU H'0023' ; Variable für die Tabelle LED_PORTA
leuchten2 EQU H'0024' ; Variable für die Tabelle LED_PORTC
;************************************************* *****************************

org 0x000 ; Startadresse des PICs
goto EINSTELLUNGEN
;************************************************* *****************************
; INTERRUPT
org 0X004 ; Startadresse der ISR
retfie ; Beenden der ISR, zurück zum Programm

;************************************************* *****************************
; PIC***** Einstellungen
EINSTELLUNGEN
bsf STATUS,RP0 ; Auswahl Bank 1
movwf OSCCAL ; Neuladen der Kalibrirungswerte für den internen Takt

movlw B'00111000' ; 1=Eingang, 0=Ausgang
movwf TRISA

movlw B'00100000' ; 1=Eingang, 0=Ausgang
movwf TRISC

bcf STATUS,RP0 ; Zurück zu Bank 0

clrf PORTA ; Löschen aller Ausgänge
clrf PORTC ; Löschen aller Ausgänge
clrf INTCON ; Dekavieren eines Interuptes


;************************************************* ************************
; HAUPTPROGRAMM
START
movlw B'11000111' ; Setzt alle Ausgänge von PORTA auf 1
movwf PORTA

movlw B'11011111' ; Setzt alle Ausgänge von PORTC auf 1
movwf PORTC

call PAUSE1s ; Macht 1 Sekunde Pause

clrf PORTA ; Löscht PORT A & C
clrf PORTC

call PAUSE1s ; Macht 1 Sekunde Pause

ABARBETUNG

bsf PORTA,0 ; Schaltet die Positoinsleuchten ein
bsf PORTA,1
bsf PORTA,2

call PAUSE250ms ; Macht 250ms Pause

bcf PORTA,0 ; Schaltet die Positionsleuchten der Flügel aus
bcf PORTA,1

call PAUSE250ms ; Macht 250ms Pause

bcf PORTA,2 ; Schaltet die Positionsleuchte unten aus

call PAUSE750ms ; Macht 750ms Pause

goto ABARBETUNG ; Geht zum Anfang der abarbeitung

;************************************************* ************************
; UNTERPROGRAMM

PAUSE1ms ; Label, wo die Standardwarteschleife beginnt
movlw D'199' ; Dezimalwert für die Zeitkonstante damit PAUSE = 1ms ist
movwf schleife ; Schieben des Wertes 199 in die Variable "schleife"
; Ende der Start-Einstellungen für "PAUSE1ms"

PAUSEE ; Einsprungstelle für Pausenschleifen
nop
nop ; Taste nicht gedrückt, springe zur Marke "HAUPT" DECFSZ schleife,1
decfsz schleife,1 ; Dekrementiere die Variable "schleife" um 1 und schreibe das Ergebnis zurück in "schleife"
goto PAUSEE ; Ist die Zeit verstrichen? Nein, dann springe zurück zu "PAUSEE"
; Neuer Durchlauf bis "schleife" = 0
return

; Mögliche Standardwarteschleife für Zeiten zwischen ~ 2 und 256 ms
;
PAUSE100ms
movlw D'100'
movwf help
PAUSE100
call PAUSE1ms
decfsz help,1 ; Dekrementiere die Variable "help" um 1 und schreibe das Ergebnis zurück in "schleife"
goto PAUSE100 ; Ist die Zeit verstrichen? Nein, dann springe zurück zu "PAUSE250ms"
; Neuer Durchlauf bis "schleife" = 0
return

; Mögliche Standardwarteschleife für Zeiten zwischen ~ 2 und 256 ms
;
PAUSE250ms
movlw D'250'
movwf help
PAUSE250
call PAUSE1ms
decfsz help,1 ; Dekrementiere die Variable "help" um 1 und schreibe das Ergebnis zurück in "schleife"
goto PAUSE250 ; Ist die Zeit verstrichen? Nein, dann springe zurück zu "PAUSE250ms"
; Neuer Durchlauf bis "schleife" = 0
return

; Mögliche Standardwarteschleife für Zeiten zwischen ~ 250ms und 20 s
;
PAUSE500ms
movlw D'2'
movwf sekunde
PAUSE500
call PAUSE250ms
decfsz sekunde,1 ; Dekrementiere die Variable "help" um 1 und schreibe das Ergebnis zurück in "schleife"
goto PAUSE500 ; Ist die Zeit verstrichen? Nein, dann springe zurück zu "PAUSE250ms"
; Neuer Durchlauf bis "schleife" = 0
return

; Mögliche Standardwarteschleife für Zeiten zwischen ~ 250ms und 20 s
;
PAUSE750ms
movlw D'3'
movwf sekunde
PAUSE750
call PAUSE250ms
decfsz sekunde,1 ; Dekrementiere die Variable "help" um 1 und schreibe das Ergebnis zurück in "schleife"
goto PAUSE750 ; Ist die Zeit verstrichen? Nein, dann springe zurück zu "PAUSE250ms"
; Neuer Durchlauf bis "schleife" = 0
return

; Mögliche Standardwarteschleife für Zeiten zwischen ~ 250ms und 20 s
;
PAUSE1s
movlw D'4'
movwf sekunde
PAUSE1
call PAUSE250ms
decfsz sekunde,1 ; Dekrementiere die Variable "help" um 1 und schreibe das Ergebnis zurück in "schleife"
goto PAUSE1 ; Ist die Zeit verstrichen? Nein, dann springe zurück zu "PAUSE250ms"
; Neuer Durchlauf bis "schleife" = 0
return

; Mögliche Standardwarteschleife für Zeiten zwischen ~ 250ms und 20 s
;
PAUSE2s
movlw D'8'
movwf sekunde
PAUSE2
call PAUSE250ms
decfsz sekunde,1 ; Dekrementiere die Variable "help" um 1 und schreibe das Ergebnis zurück in "schleife"
goto PAUSE2 ; Ist die Zeit verstrichen? Nein, dann springe zurück zu "PAUSE250ms"
; Neuer Durchlauf bis "schleife" = 0
return

; Mögliche Standardwarteschleife für Zeiten zwischen ~ 250ms und 20 s
;
PAUSE3s
movlw D'12'
movwf sekunde
PAUSE3
call PAUSE250ms
decfsz sekunde,1 ; Dekrementiere die Variable "help" um 1 und schreibe das Ergebnis zurück in "schleife"
goto PAUSE3 ; Ist die Zeit verstrichen? Nein, dann springe zurück zu "PAUSE250ms"
; Neuer Durchlauf bis "schleife" = 0
return

end ; Ende des Programmes

phaidros
03.06.2009, 13:25
Du hast das Register CMCON nicht initialisiert. Dadurch sind die Pins RA0 und RA1 als analoge Eingänge für den Comparator konfiguriert und werden als 0 gelesen (und mithin beim letzten BSF auch als 0 geschrieben.

pointhi
07.06.2009, 13:44
Danke erstmal, ich werde es ausprobieren. Ich schreib dann ins Forum wenn es geklappt hat