Fehlerliste / Programmbeispiel
Hallo Beahr,
bitte sei mir nicht böse, aber wenn ich mir Deinen Quelltext ansehe, kommt mir das Grausen weil er so unübersichtlich und wirr ist.
Nun, ich habe folgende Fehler in Deinem Quellcode gefunden:
1.) wie andere schon festgestellt haben, musst Du da, wo Dein Hauptprogramm beginnt ein „org 0x00“ hinsetzen. Gleich danach schreibst Du: „goto init“, wobei Du unter dem Label „init“ alle erforderlichen Special-Funktion-Register mit den gewünschten Startwerten initialisierst.
2.) Im Register „CMCON“ setzt Du Bits, ohne dass Du es zuvor unter „Register benennen“ deklariert hast.
3.) unter „internen Taktgenerator kalibrieren“ rufst Du mit „call“ einen hex-Wert auf. Mit „call“ kannst Du nur ein Unterprogramm aufrufen. Um einen Wert (Konstante) in den Akku zu laden, verwendet man den Befehl „movlw 0xFF“. Du verstehst aber besser was Du tust, wenn Du statt eines Hex-Wertes einen Dezimalwert oder eine 8 Bit-Konstante in den Akku lädst:
a) Dezimalwert (100) in Akku laden: movlw d’100’
b) Die Zahl „7“ als Binärwert in Akku laden: movlw b’00000111’
4.) Das OSCCAL-Register hast Du auch nicht deklariert.
5.) Die Variable „Zähler4“ hast Du in einem nicht vorhandenen RAM-Bereich (4fh) deklariert.
6.) Um einem Register einen selbstgewählten Namen zu geben, musst Du die „#Define“-Anweisung verwenden, und nicht die equ-Anweisung.
Beispiel: #Define Tris_Reg trisio ;mit dieser Anweisung erhält das Register „trisio“ den Namen „Tris_Reg“. Zuvor muss aber das „trisio“-Register deklariert werden mit „trisio equ 0x85“.
7.) Du löscht das Trisio-Register im Deklarationsteil: das geht nicht!
Prozessorbefehle kannst Du nur im Hauptprogramm ausführen, d. h. nach der Startadresse des RESET-Vektors „org 0x00“. Wie oben erwähnt gehst Du nach der Anweisung „org“ erst einmal zur Initialisierung (Label: „init“), um dann dort jedem deklarierten Register den gewünschten Startwert zu geben. Beachte, dass Du vor dem Label „init“ schreibst: org 0x06!
8.)Du möchtest den Pin 3 (GP4) als Eingang deklarieren, verwendest aber einen Befehl mit dem Du ihn als Ausgang setzt. Richtig muss es heissen: „bsf Tris_Reg,4“
9.) Im Hauptprogramm lädst Du die Zahl „24“ in den Akku, wobei weder Du noch der Prozessor erkennt, welches Zahlenformat Du dieser Zahl gegeben hast. Wenn Du eine Dezimalzahl meinst, verwende den Befehl: „movlw d’24’“.
10.) Die Unterprogramme setzt man in der Regel oberhalb des Hauptprogramms weil dies der besseren Übersicht dient.
Hier ein Beispiel für einen übersichtlichen Programmkopf:
;----------------------------------------------------
; Projektname: LED-Zeitschalter
; Datum : 22.10.2006 Name:_ _ _ _ _ _ _
; Prozessor: PIC12F629-I/SN
;----------------------------------------------------
;--------- Konstanten-Deklarationen -----------------
#Define Millisek d’10’ ;Dezimalwert für 1ms
#Define _1_Sek d’100’ ;Dezimalwert für 1 Sek
;--------- Portregister-Initialisierungs-Konstanten -
#Define TrisA_init b’11101100’ ;
#Define TrisB_init b’11000000’ ;
#Define PortA_init b’00010000’ ;
#Define PortB_init b’00000000’ ;
;--------- Tris-Deklarationen -----------------------
#Define Tr_LED_1 TrisA,0 ;
#Define Tr_Eingang TrisB,1 ;
#Define Tr_LED_rot TrisC,1 ;
;--------- Port-Deklarationen -----------------------
#Define LED_1 PortA,0 ;Alles OK-LED
#Define Eingang PortA,1
rüfeingang
#Define LED_rot PortA,2 ;Fehler-LED
;--------- Port-Register ----------------------------
PortA equ 0x05 ;B0
PortB equ 0x06 ;B0
PortC equ 0x07 ;B0
;--------- Tris-Register ----------------------------
TrisA equ 0x85 ;B1 (Bank_1)
TrisB equ 0x86 ;B1
TrisC equ 0x87 ;B1
;--------- SPECIAL-Function-Register ----------------
status equ 0x03 ;B0/B1 Status-Register
option_reg equ 0x81 ;B1 Option Register
wpub equ 0x95 ;B1 Weak-Pull-up-Register
osccon equ 0x8F ;B1 Oszillator Steuerregister
cmcon equ 0x19 ;B0 int. Comparator
;--------- Timer-Register ---------------------------
tmr0 equ 0x01 ;B0 Timer0-Register
t1con equ 0x10 ;B0 Timer 1
tmr1_L equ 0x0E ;B0 Timer1 LOW -BYTE
tmr1_H equ 0x0F ;B0 Timer1 HIGH-BYTE
;--------- RAM - Variablen --------------------------
zähler_1 equ 0x20 ;Zählvariable für 1 Millisek
zähler_2 equ 0x21 ;Zähler für 1 Minute
zähler_3 equ 0x22 ;Zähler für 1 Stunde
;----------------------------------------------------
;Unterprogramme
;----------------------------------------------------
;UP 1: LED1_on (LED1 einschalten)
;-----------------------------
LED1: bsf GPIO, 0
return
;-----------------------------
;UP 2: LED1_off (LED1 ausschalten)
;-----------------------------
LED1: bcf GPIO, 0
return
;-----------------------------
;XXXXXXXXXXXXXXXXX Hauptprogramm XXXXXXXXXXXXXXXXXXX
reset: org 00
osition des Reset-Vektors
goto init
org 06 ;Start Programmcode
;----------------------------------------------------------
;initialisiere Register und Variablen mit Startwerten
init: bsf status,5 ;Bank_1
movlw TrisA_init ;lade Init-Wert in Akku
movwf TrisA ;schreibe in TRIS-Register
movlw b’00000111’ ;lade Bitmaske für CMCON
bcf status,5 ;Bank_0
movwf cmcon ;deaktiviere internen Comparator
movlw PortA_init ;lade Init-Wert in Akku
movwf PortA ;schreibe Anfangswerte in Port A
clrf zähler_1 ;lösche Zähler_1
clrf zähler_2 ;lösche Zähler_2
movlw Millisek ;lade INIT-Wert für Zähler_3
movwf zähler_3 ;schreibe Startwert in Zähler_3
goto start ;Initialisierung fertig --> geh zum HP
;----------------------------------------------------------
;frage PIN3 in Abständen von 0,125 Sek. ab
start: btfss Eingang ;prüfe ob Eingang = HIGH
goto weiter ;Eingang ist LOW --> mach weiter
call LED_1_an ;Eingang ist HIGH --> LED_1 einschalten
goto pause_1 ;LED wurde eingeschaltet --> mach Pause
weiter: decfsz Zähler_3 ;warte 1 Millisekunde
goto weiter ;1ms noch nicht vorbei --> dec zähl_3
call LED_1_aus ;Zeit abgelaufen --> schalte LED_1 aus
goto start ;wiederhole Hauptschleife
pause_1:nop ;warte
nop ;
nop ;
goto start ;geh zurück zu Hauptschleife
end
rogrammende
So, dies mal als kleines Beispiel dazu was Übersicht bedeutet.
Ich hoffe Du kommst mit diesen Tips etwas weiter.
Gruß, Alexander