Mit nur 2 CALL befehle habe ich ein lernprogramm geschrieben.
Ich hoffe es hilft auch jemanden.
lg
Schlapfi
Code:
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Dateiname: Eieruhr ( Lernprogramm )
; LED mit 3 x 7 Segment Multiplex betrieb
; Autor: Schlapfi
; Datum: Dez. 2013
; PIC 16F631
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Funktionsbeschreibung des Programms:
; Prozessor-Takt 8 MHz Intern
; Mit PAUSE wird gewartet bis Timer-0 überleuft, über ZAEHL wird diese Zeit erweitert
; auf 1,000999 Sec.( für Eierkochen ausreichend, Fehlmessung 0,6 Sec. in 10 Min.)
; und "einer" wird mit diesem Takt hochgezählt.
; Anoden sind RB6 = hundert , RB5 = zehner, RB4 = einer
; einer = Sekunde-einer
; zehner = Sekunde-zehner
; hundert = Minute
; 7-Segment mit gemeinsamer Anode.
; Katoden ausgänge sind: PORT-C
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
list p=16F631
#include <p16f631.inc>
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _CPD_OFF
ERRORLEVEL -302 ; Unterdrücken BANK SELECTION MESSAGES
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Deklaration der Variablen und Konstanten
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
einer EQU H'0022' ; Variable für die Einerstelle der Zahl
zehner EQU H'0023' ; Variable für die Zehnerstelle der Zahl
hundert EQU H'0024' ; Variable für die Hunderterstelle der Zahl
ZAEHL EQU H'0025' ; Zähler für Sekunde
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Masken für das Einschalten der LEDs
; Masken sind wegen besserer beschaltung so gwählt
; und können leicht verändert werden.
; gfedcba
#define D0 B'01000000' ; 0
#define D1 B'01111001' ; 1
#define D2 B'00100100' ; 2
#define D3 B'00110000' ; 3
#define D4 B'00011001' ; 4
#define D5 B'00010010' ; 5
#define D6 B'00000010' ; 6
#define D7 B'01111000' ; 7
#define D8 B'00000000' ; 8
#define D9 B'00010000' ; 9
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Startadresse des PIC-Controllers nach einem RESET oder Neustart
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
org 0x000 ; Startadresse des PICs
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; PIC Einstellungen
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
START
bsf STATUS,RP0 ; Auswahl Bank 1
movlw B'01110000' ; Int-Oszilator 8 MHz,
movwf OSCCON
movlw b'00000100' ; TMR0 vorbereiten (intern, Vorteiler 32,)
movwf OPTION_REG
movlw b'00000000' ; TRISC = Ausgang
movwf TRISC ; damit ist Port C = Ausgang
movwf TRISB ; und Port B
movwf TRISA ; und Port A
bcf STATUS,RP0 ; Auswahl Bank 0
; Interrupt
movlw b'10000000' ; alle
movwf INTCON ; Interrupts freigeben
movlw .250
movwf ZAEHL
clrf PORTA ; Löschen aller Ausgänge
clrf PORTB
clrf PORTC ; Löschen aller Ausgänge
clrf einer
clrf zehner ; Löschen
clrf hundert
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Hauptprogramm: LED Anzeigen 3x7 Segmente
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
LEDAnz
clrf PORTB ; Löschen aller Ausgänge
clrf PORTC
; führende null unterdrücken. ZEROPIT abfragen ob gesetzt.
movlw d'0' ; 0 nach " W " laden
addwf hundert,w ; inhalt von hundert dazu addieren, schreibe in " W "
btfsc STATUS,Z ; ist nicht null ? : überspringe nächste Zeile
goto $+9 ; wenn null, 9 Zeilen nach unten
movlw B'01000000' ; hunderter Katode
movwf PORTB ; und an PORTB ausgeben
movf hundert,w ; Laden der Variable "hundert" in das W-Register
call LED ; Sprung zum Laden der LED-Variablen
movwf PORTC ; und an PORTC ausgeben
call PAUSE
clrf PORTB ; Löschen aller Ausgänge
clrf PORTC
movlw B'00100000'
movwf PORTB
movf zehner,w ; Laden der Variablen "zehner" in das W-Register
call LED ; Sprung zum Laden der LED-Variablen
movwf PORTC
call PAUSE
clrf PORTB ; Löschen aller Ausgänge
clrf PORTC
movlw B'00010000'
movwf PORTB
movf einer,w ; Laden der Variablen "einer" in das W-Register
call LED ; Sprung zum Laden der LED-Variablen
movwf PORTC
call PAUSE
goto LEDAnz ; und wieder zu Anzeige
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Ab hier folgen die Unterprogramme
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; PAUSE:
; wartet bis Timer0 überleuft ( alle 4 mSec. ) und verringert ZAEHL bis null,
; 4 mSec ( Timer0 ) X 250 ( ZAEHL ) = Eine Sekunde
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
PAUSE
btfss INTCON,T0IF ; Pause von 4 ms Dauer
goto $-1 ; warten bis Interruptflag gesetzt ist
movlw 06 ; Timer-0 auf 250 stellen
movwf TMR0 ; W -> Timer-0
bcf INTCON,T0IF ; TMR0-Flag löschen
decfsz ZAEHL ; ZAEHL minus 1 bis 0
return ; ZAEHL > 0
movlw .250 ; ZAEHL = 0
movwf ZAEHL ; und wird neu geladen
; erhöht "einer" um 1 und alle weiteren stellen bei überlauf
incf einer,1 ; Erhöhen der Variablen "einer" um +1
movfw einer ; Laden der Variablen "einer" ins W-Register
sublw D'10' ; 10 in W laden und abziehen.
btfss STATUS,Z ; ergebnis = 0 : überspringe nächste Zeile
return ; rechenergebnis nicht 0 = return
; Ja, dann
incf zehner,1 ; Zählervariable für die zweite Stelle erhöhen
clrf einer ; einer löschen
movfw zehner ; Laden der Variablen "zehner" ins W-Register
sublw D'6' ; Maximaler Zählwert erreicht?
btfss STATUS,Z ; erreicht : überspringe nächste Zeile
return ; nicht 0 = return
; Ja, dann
incf hundert,1 ; Zhundert um 1 erhöhen
clrf zehner ; zehner löschen
movfw hundert ; Laden der Variablen "hundert" ins W-Register
sublw D'10' ; Maximaler Zählwert erreicht?
btfss STATUS,Z ; erreicht : überspringe nächste Zeile
return ; nicht 0 = return
clrf hundert ; Zählervariable löschen
return ; Rücksprung
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
LED
addwf PCL,1
retlw D0
retlw D1
retlw D2
retlw D3
retlw D4
retlw D5
retlw D6
retlw D7
retlw D8
retlw D9
END
Lesezeichen