;********************************************************************** ; This file is a basic code template for object module code * ; generation on the PIC16F648A. This file contains the * ; basic code building blocks to build upon. * ; * ; Refer to the MPASM User's Guide for additional information on * ; features of the assembler and linker (Document DS33014). * ; * ; Refer to the respective PIC data sheet for additional * ; information on the instruction set. * ; * ;********************************************************************** ; * ; Filename: xxx.asm * ; Date: * ; File Version: * ; * ; Author: * ; Company: * ; * ; * ;********************************************************************** ; * ; Files required: P16F648A.INC * ; * ; * ; * ;********************************************************************** ; * ; Notes: * ; * ; * ; * ; * ;********************************************************************** list p=16F648A ; list directive to define processor ;************************************************************** ;* ;* Pinbelegung ;* ---------------------------------- ;* PORTB: ;* 0 "NC" ;* 1 Muendnungsfeuer ;* 4 Status LED ;* 5 Reset ;* 6 Lichtschranke ;* 7 "NC" ;* ;* 3 Ziffer1 -----------------+ ;* 2 Ziffer2 -----+ I ;* I I ;* PORTA: 0 Segment B AAAAA AAAAA ;* 1 Segment G F B F B ;* 2 Segment C F B F B ;* 3 Segment D GGGGG GGGGG ;* 4 Segment E E C E C ;* 5 Segment "NC" E C E C ;* 6 Segment A DDDDD DDDDD ;* 7 Segment F ;* ;************************************************************** ; 2-stellige LED-Anzeige ; ; Tektquelle: 4 MHz ; es wird probehalber die Zahl "12" angezeigt ; ;************************************************************** #include ; processor specific variable definitions errorlevel -302 ; suppress message 302 from list file __CONFIG _CP_OFF & _DATA_CP_OFF & _LVP_OFF & _BOREN_OFF & _MCLRE_OFF & _WDT_OFF & _PWRTE_OFF & _INTOSC_OSC_NOCLKOUT ; '__CONFIG' directive is used to embed configuration word within .asm file. ; The lables following the directive are located in the respective .inc file. ; See data sheet for additional information on configuration word settings. ;***** VARIABLE DEFINITIONS (examples) ; example of using Shared Uninitialized Data Section INT_VAR UDATA_SHR w_temp RES 1 ; variable used for context saving status_temp RES 1 ; variable used for context saving pclath_temp RES 1 ; variable used for context saving w_copy EQU H'0020' ; Backup für Akkuregister s_copy EQU H'0021' ; Backup für Statusregister Ziffer1 EQU H'0022' Ziffer2 EQU H'0023' Digit EQU H'0024' ar EQU H'0025' schleife EQU H'0026' help EQU H'0027' help2 EQU H'0028' help3 EQU H'0029' help4 EQU H'002A' help5 EQU H'002B' carry EQU H'002C' ;new ;********************************************************************** RESET_VECTOR CODE 0x0000 ; processor reset vector goto start ; go to beginning of program INT_VECTOR CODE 0x0004 ; interrupt vector location intvec bcf INTCON, GIE ; disable Interupt movwf w_copy ; w retten swapf STATUS, w ; STATUS retten movwf s_copy ; movlw D'131' ; 256-125=131 ((1MHz : 32 ): 125 = 250 Hz) movwf TMR0 ; Intrupt servic routine Int_serv bcf PORTB, 3 ; Ziffer1 aus bcf PORTB, 2 ; Ziffer2 aus decf Digit,f ; Ziffernzähler verringern btfsc STATUS, Z goto Int_0 ; Z-Flag=1 ergo Digit=0 movfw Digit movwf ar decf ar, f btfsc STATUS, Z goto Int_1 ; Digit=1 goto Int_2 ; Digit=2 Int_0 movlw 3 movwf Digit goto Int_end ; Stop-Taste gedrückt Int_1 movfw Ziffer1 ; Wert der 1. Ziffer call Segmente movwf PORTA ; Segmente einschalten bsf PORTB, 3 ; 1. Ziffer einschalten goto Int_end Int_2 movfw Ziffer2 ; Wert der 2. Ziffer bsf STATUS,RP0 ; Statusregister setze PR0 -> Auswahl Bank 1 call Segmente2 bcf STATUS,RP0 ; Statusregister lösche PR0 -> Auswahl Bank 0 movwf PORTA ; Segmente einschalten bsf PORTB, 2 ; 2. Ziffer einschalten goto Int_end Int_end swapf s_copy, w ; STATUS zurück movwf STATUS swapf w_copy, f ; w zurück mit flags swapf w_copy, w bcf INTCON, T0IF ; Interupt-Flag löschen bsf INTCON, GIE ; enable Interupt retfie ; 7-Segment-Tabelle Segmente addwf PCL, f retlw B'11011101' ; 0 retlw B'00000101' ; 1 retlw B'01011011' ; 2 retlw B'01001111' ; 3 retlw B'10000111' ; 4 retlw B'11001110' ; 5 retlw B'10011110' ; 6 retlw B'01000101' ; 7 retlw B'11011111' ; 8 retlw B'11000111' ; 9 Segmente2 addwf PCL, f retlw B'11011101' ; 0 retlw B'00000101' ; 1 retlw B'01011011' ; 2 retlw B'01001111' ; 3 retlw B'10000111' ; 4 retlw B'11001110' ; 5 retlw B'10011110' ; 6 retlw B'01000101' ; 7 retlw B'11011111' ; 8 retlw B'11000111' ; 9 ;******************************************************************************* ;MAIN_PROG CODE start ; remaining code goes here ;****************************************************************************** ; PIC Einstellungen ;****************************************************************************** ; Initialisierung des Controllers bsf STATUS,RP0 ; Statusregister setze PR0 -> Auswahl Bank 1 movlw B'01100001' ; Konfigurieren der Ports zur Steuerung von D0 movwf TRISB ; Schieben des geladenen Wertes in das Register TRISIO movlw B'00100000' ; Konfigurieren der Ports zur Steuerung von D0 movwf TRISA ; Schieben des geladenen Wertes in das Register TRISIO bcf STATUS,RP0 ; Statusregister lösche PR0 -> Auswahl Bank 0 clrf PORTB ; Löschen aller Ausgänge ; 250 Hz-Timer-Interupt einstellen bsf STATUS, RP0 ; auf Bank 1 umschalten movlw B'10000100' ; internen Takt zählen, Vorteiler zum Timer0, 32:1 movwf OPTION_REG movlw D'131' ; 256-125=131 ((1MHz : 32 ): 125 = 250 Hz) bcf STATUS, RP0 ; auf Bank 0 zurückschalten movwf TMR0 bsf INTCON, T0IE ; Timer0 interupt erlauben bsf INTCON, GIE ; Interupt erlauben ; Programmstart begin bsf PORTB,7 ; Status-LED an nop nop nop nop bsf PORTB,4 movlw D'100' ;200ms movwf help3 call PAUSE250ms movlw 8 movwf Ziffer1 movlw 1 movwf Ziffer2 movfw Ziffer1 movwf help4 movfw Ziffer2 movwf help5 movlw 3 movwf Digit loop btfss PORTB,0 ;Auf Objekt in Lichtschranke warten call checkit2 btfsc PORTA,5 ;Auf Objekt in Lichtschranke warten call checkit btfsc PORTB,5 ;Auf Objekt in Lichtschranke warten goto checkit3 btfsc PORTB,6 ;Auf Objekt in Lichtschranke warten goto loop movlw D'50' ;10ms Entprellen movwf help3 call PAUSE250ms loop2 btfss PORTB,6 ;Warten, dass Objekt Lichtschranke wieder verläßt goto loop2 bcf PORTB,7 ;Status LED aus bsf PORTB,1 ;Mündungsfeuer an movlw D'100' ;100ms movwf help3 call PAUSE250ms bsf PORTB,7 ;Status-LED wieder an bcf PORTB,1 ;Mündungsfeuer aus decf Ziffer1, f ;Ziffer1 dekrementieren movlw D'10' subwf Ziffer1, w btfss STATUS, C ;Prüfen ob 10 voll goto loop movlw 9 movwf Ziffer1 decfsz Ziffer2, f ;Ziffer2 dekrementieren, wenn null, dann gehe zu nullo call nullo goto loop ;********************************************************************************************* ; Ab hier folgen die UnterprogrammePAUSE250ms ;********************************************************************************************* nullo movlw D'10' subwf Ziffer2, w btfss STATUS, C ;Prüfen ob 10 voll goto ende2 movlw 9 ;99 auf Anzeige movwf Ziffer1 movlw 9 movwf Ziffer2 ende2 return ;********************************************************************************************* checkit movlw D'200' ;200ms movwf help3 call PAUSE250ms btfss PORTA,5 ;wenn schalter noch gedrückt, dann los goto ende movlw 8 ;36 auf Anzeige movwf Ziffer1 movlw 1 movwf Ziffer2 movlw D'200' ;200ms movwf help3 call PAUSE250ms movlw D'200' ;200ms movwf help3 call PAUSE250ms movlw D'200' ;200ms movwf help3 call PAUSE250ms movlw D'200' ;200ms movwf help3 call PAUSE250ms btfss PORTA,5 ;wenn schalter noch gedrückt, dann weiter goto ende movlw 6 ;18 auf Anzeige movwf Ziffer1 movlw 3 movwf Ziffer2 movlw D'200' ;200ms movwf help3 call PAUSE250ms movlw D'200' ;200ms movwf help3 call PAUSE250ms movlw D'200' ;200ms movwf help3 call PAUSE250ms movlw D'200' ;200ms movwf help3 call PAUSE250ms btfss PORTA,5 ;wenn schalter noch gedrückt, dann weiter goto ende movlw 6 movwf Ziffer1 movlw 0 movwf Ziffer2 movlw D'200' ;200ms movwf help3 call PAUSE250ms movlw D'200' ;200ms movwf help3 call PAUSE250ms movlw D'200' ;200ms movwf help3 call PAUSE250ms btfss PORTA,5 ;wenn schalter noch gedrückt, dann von vorne goto ende goto checkit ende movfw Ziffer1 ;Anzeigewert sichern movwf help4 movfw Ziffer2 movwf help5 return ;********************************************************************************************* checkit2 movlw D'50' ;200ms movwf help3 call PAUSE250ms btfsc PORTB,0 ;wenn schalter noch gedrückt, dann los goto out clrf Ziffer1 ; Anzeige nullen clrf Ziffer2 btfss PORTB,0 ;Auf Clip warten goto checkit2 movfw help4 ;Anzeigewert ausgeben movwf Ziffer1 movfw help5 movwf Ziffer2 out return ;********************************************************************************************* checkit3 movlw D'50' ;10ms Entprellen movwf help3 call PAUSE250ms btfss PORTB,0 ;Auf Objekt in Lichtschranke warten goto over bcf PORTB,4 bcf PORTB,7 ;Status LED aus clrf Ziffer1 ; Anzeige nullen clrf Ziffer2 movlw D'200' ;200ms movwf help3 call PAUSE250ms bsf PORTB,7 movlw 8 movwf Ziffer1 movlw 8 movwf Ziffer2 btfss PORTB,5 ;Auf Clip warten goto over movlw D'200' ;200ms movwf help3 call PAUSE250ms btfsc PORTB,5 ;Auf Clip warten goto checkit3 over movlw 8 ;36 auf Anzeige movwf Ziffer1 movlw 1 movwf Ziffer2 bsf PORTB,4 return ;********************************************************************************************* ; Mögliche Standardwarteschleife für Zeiten zwischen ~ 2 und 256 ms PAUSE250ms call PAUSE1ms decfsz help3,1 ; Dekrementiere die Variable "help" um 1 und schreibe das Ergebnis zurück in "schleife" goto PAUSE250ms ; Ist die Zeit verstrichen? Nein, dann springe zurück zu "PAUSE250ms" ; Neuer Durchlauf bis "schleife" = 0 return ;********************************************************************************************* 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" PAUSEE2 ; 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 PAUSEE2 ; Ist die Zeit verstrichen? Nein, dann springe zurück zu "PAUSEE" ; Neuer Durchlauf bis "schleife" = 0 return ;********************************************************************************************* end ;********************************************************************************************* ;********************************************************************************************* ; goto $ ; loop forever, remove this instruction, for test only ; ; initialize eeprom locations EE CODE 0x2100 DE 0x00, 0x01, 0x02, 0x03 END ; directive 'end of program'