Hallo RoboHolIc

Danke für deine Antwort.
Das hier war mein erstes richtiges Programm.

Voltmeter bis 15 Volt

Code:
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Dateiname:	Voltmeter ( Lernprogramm )
; Autor:		Schlapfi
; Datum:  		Sept. 2013			
; Kontroller:   16F676  
; Das Programm kann mit wenigen veränderungen auch für andere PIC's verwendet werden.
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Funktionsbeschreibung des Programms:
; Spannungsmessung bis 15.0 Volt. 3 stellige LED-anzeige mit Multiplex betrieb. 
; An RA0 wird eine spannung gemessen und an RC0 - RC3 im BCD code ausgegeben 
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;         10K                10K               10K
;  - 0 V  ____               ____              ____       + 15V
;  ------|____|-----+-------|____|------------|____|------
;                   | 
;  ----------- || --+--- RA0 ->
;             C 1µF
;
; Bordspsnnung ( Auto ) wird durch 3 geteilt, 
; durch 3 Widerstände a,10 K Ohm.
; Von RA0 ( AD-Eingang ) einen Kondensator 1µF nach Masse stabilisiert
; die Anzeige. ( verhindert laufen )
; Der 5 Volt Messbereich des PIC entspricht dann 15 Volt.
; Das Ergebnis der Messung wird mit dem Faktor 3 Multipliziert
; und an RC1 bis RC4 im BCD code ausgegeben.
; Katoden sind RA5 = hundert ( 10 V ) , 
; RA1 / RA4 = zehner ( einerstelle ) und Dp.,
; RA2 = einer.( nachkommastelle )
; Die Katoden werden über Transistoren gesteuert der Dp. kann direkt gesteuert werden.
; BCD ausgänge sind: RC4 = 1 , RC1 = 2 , RC2 = 4 , RC3 = 8
; diese steuern einen CMOS-4511 7-Segment-Dekoder.
; Es können auch andere BCD zu 7 Segment decoder verwendet werden.( zb. 4513 oä.) 
; Die Pinbelegung des PIC wurde wegen der Pinanordnung des 4511 so gewählt.	
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	list      	p=16F676
	#include 	<p16f676.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
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;	
schleife	EQU	H'0020'				; Anzahl der "schleifen"
help		EQU	H'0021'				; Hilfsvariable für verschiedene Aufgaben.
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
ADC_L       EQU H'0026'				; -----------------""---------------------
ADC_H       EQU H'0027'             ; Variablen 
ADC_L1      EQU H'0028'				; weden für rechenoperationen gebraucht
ADC_H1      EQU H'0029'				; -----------------""---------------------
count       EQU H'002C'				; -----------------""---------------------
	
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

; Masken für das Einschalten der LEDs
; Masken sind wegen der Eingänge des C-MOS 4511 so gwählt,
; und können für andere zwecke leicht verändert werden.

#define D0_AN   B'00000000'         ; 0						
#define D1_AN	B'00010000'         ; 1 
#define D2_AN	B'00000010'		   	; 2
#define D3_AN	B'00010010'			; 3
#define D4_AN	B'00000100'			; 4
#define D5_AN	B'00010100'			; 5
#define D6_AN	B'00000110'			; 6
#define D7_AN	B'00010110'	 		; 7
#define D8_AN	B'00001000'			; 8
#define D9_AN	B'00011000'			; 9

;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

w		equ	 0		; w ist Zielregister
f		equ	 1		; f ist Zielregister

		org	0		; Start bei Adresse 0

		goto	START

		org	04		; feste Interrupt-Service-Adresse

START	
		bsf     STATUS,RP0			; Auswahl Bank 1 
		call 	0x3FF				; Laden des Kalibrierungswertes 
		movwf   OSCCAL				; Schreiben des Kalibrierungswertes für den internen Takt
		
		movlw	B'00010001'			; FOCS 8 und AN0
		movwf	ANSEL

    	movlw   b'00000001'	       	;setze RA0 als Eingang und den Rest als Ausgang
    	movwf   TRISA

    	movlw   b'00000000'		    ;alle Pins von Port C sind Ausgänge
    	movwf	TRISC

   		movlw  	B'00000011'  		; Pull-ups abschalten, interne clock, Teiler 1:16
  		movwf  	OPTION_REG 			; Schreiben des OPTION-Registers	 					
						
		bcf     STATUS,RP0			; Zurück zu Bank 0 
		
	   	movlw   B'10000001'     	; Rechtsbündig, AN 0, AD an
		movwf   ADCON0   
		
		clrf	PORTA				; Löschen aller Ausgänge 
		clrf	PORTC				; Löschen aller Ausgänge 
		 
    	clrf	einer
		clrf	zehner
		clrf	hundert

		movlw	d'20'
		movwf	count 


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Hauptprogramm
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Hier wird der AD-Wandler 25 X abgefragt und zu ADC_L und ADC_H addiert.
; Entspricht einer multiplikation mit 25
			
Haupt
		clrf	ADC_L
		clrf	ADC_L1
		clrf	ADC_H
		clrf	ADC_H1
        clrf    help
        movlw   d'25'               ; 25 in W laden
        movwf   help				; W in help laden
Prog	call	ADMess				; gehe zu unterprogramm ADMess
        decfsz  help,f				; 1 von help abziehen, prüfen ob null
        goto    Prog				; nicht null gehe zu Prog
    	bcf     STATUS,C			; null erreicht lösche C bit
		movfw	ADC_L				; ADC_L in W laden
		movwf	ADC_L1				; W in ADC_L1 kopieren
		movfw	ADC_H				; -"-
		movwf	ADC_H1
		goto	ADAD
ADMess
		bsf     STATUS,RP0			; Auswahl Bank 1 
    	clrf    ADRESL			    ; niederwertigen Teil des AD-Ergebnisses löschen
		bcf     STATUS,RP0			; Auswahl Bank 0 

    	clrf    ADRESH			    ; höherwertigen Teil des AD-Ergebnisses löschen
		bsf    	ADCON0,GO    		; A/D-Wandler starten

       	btfsc  	ADCON0,GO    		; Ist der A/D-Wandler fertig?
       	goto   	$-1         		; Nein, weiter warten ( eine Zeile zurück )
			
		movf	ADRESH,w			; Dezimalwert aus ADH-Register in W schreiben
;        movlw   d'3'      ; wird mit " NOP " überschrieben dient nur zur überprüfung
		addwf	ADC_H,f				; addiere W zu ADC_H und schreibe in F
		bsf     STATUS,RP0			; Auswahl Bank 1
		movf 	ADRESL,w			; Dezimalwert aus ADL-Register in W schreiben
		bcf     STATUS,RP0			; Auswahl Bank 0
;        movlw   d'70'     ; wird mit " NOP " überschrieben dient nur zur überprüfung
						  ; ADC_H + ADC_L ergeben 12,3 Volt
    	bcf     STATUS,C			; C löschen
		addwf	ADC_L,f				; addiere W zu ADC_L und schreibe in F
    	btfsc   STATUS,C			; übertrag erfolgt ?
	    incf    ADC_H,f				; addiere eins
		return

;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; ADC_L und ADC_H Werden mit 3 multipliziert
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

ADAD    clrf    schleife			; lösche schleife
        movlw   d'2'				; 2 in W laden, einmal steht es schon im Speicher
        movwf   schleife			; wert aus W in schleife

ADD_3	bcf     STATUS,C			; C löschen
		movf	ADC_L1,w			; ADC_L1 in W laden
		addwf	ADC_L,f				; addiere W zu ADC_L
    	btfsc   STATUS,C			; überlauf erfolgt ? kein überlauf überspringe
	    incf    ADC_H,F				; bei überlauf addiere 1 zu ADC_H
		movf	ADC_H1,w			; lade ADC_H1 in W
		addwf	ADC_H,f				; addiere W zu ADC_H und schreibe nach F
        decfsz  schleife,f			; eins von schleife abziehen bis null, 
									; wenn null überspringe nächsten befehl.
        goto    ADD_3				; gehe zu

; normalerweise wird ADC_H und ADC_L jetzt durch 256 dividiert = 9 X durch 2 dividieren
; ADC_H ein mahl rechts ADC_L wird nicht mehr gebraucht.Das Messergebnis steht in ADC_H

        rrf     ADC_H,w         	; dividiere durch 2 und schreibe nach W
                                	; in ADC_H steht jetzt das endergebnis
        movwf   help				; gemessene Spannung ( ADC_H ) in help schreiben

;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; auswertung des endergebnis von Hexa in Dezimahl
; help wird zerlegt in einer , zehner und hunderter
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

        clrf    schleife
    	bcf     STATUS,C
	    movlw   d'100'	       		; lade 100 in W Register 
sub_H
        subwf	help,F         		; 100 von help abziehen und in F schreiben
    	btfsc   STATUS,C       		; übertrag erfolgt ?
    	goto    ergeb_Pos_H	   		; kein übertrag gehe zu ergeb_Pos_H	
        addwf   help,f         		; addiere W ( 100 ) zu help
        movfw   schleife	   		; schleife in W Register laden
        movwf   hundert        		; anzahl der durchläufe ist jetzt hundert
        clrf    schleife       		; lösche schleife
    	bcf     STATUS,C	   		; Carryflag löschen
	    movlw   d'10'	       		; lade 10 in W Register 
        goto    sub_Z
ergeb_Pos_H	
    	incf    schleife,F     		; schleife + 1
	    goto    sub_H          		; und noch einmal
sub_Z
        subwf	help,F         		; 10 von help abziehen
    	btfsc   STATUS,C       		; übertrag erfolgt ?
    	goto    ergeb_Pos_Z	   		; kein übertrag gehe zu ergeb_Pos_Z 
        addwf   help,f         		; addiere W ( 10 ) zu help
        movfw   schleife	   		; schleife in W Register laden
        movwf   zehner         		; anzahl der durchläufe ist jetzt zehner
        movfw   help           		; der rest
        movwf   einer          		; ist einer
    	bcf     STATUS,C
		goto	Anz

ergeb_Pos_Z	
    	incf    schleife,F			; schleife + 1
	    goto    sub_Z
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Ansteuerung einer 3 X 7 Segment Anzeige ( Multiplex )
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Anz
		clrf	PORTA				; 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	An2					; wenn null, 6 Zeilen nach unten
		movlw	B'00100000'			; hunderter Katode
	    movwf	PORTA				; und auf PORTA ausgeben
		movf	hundert,w			; Laden der Variable "hundert" in das W-Register
		call	LED				    ; Sprung zum Laden der LED-Variablen
		movwf	PORTC				; und auf PORTC ausgeben
		call	PAUSE				; Pause 4 mSek.
An2
	  	clrf	PORTA				; Löschen aller Ausgänge 
		clrf	PORTC
    	movlw	B'00010010'			; zehner Katode
		movwf	PORTA
		movf	zehner,w			; Laden der Variablen "zehner" in das W-Register
		call	LED					; Sprung zum Laden der LED-Variablen
		movwf	PORTC
		call	PAUSE

		clrf	PORTA				; Löschen aller Ausgänge 
		clrf	PORTC
    	movlw	B'00000100'
		movwf	PORTA
		movf	einer,w				; Laden der Variablen "einer" in das W-Register
		call	LED					; Sprung zum Laden der LED-Variablen
		movwf	PORTC
		call	PAUSE
	    decfsz  count				; count minus 1 bis 0
        goto    Anz					; count nicht 0
		movlw	d'20'
		movwf	count 
		goto	Haupt				; count = 0, neue AD-Messung

;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Ab hier folgen die Unterprogramme
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;Warteschleife Pause 

PAUSE								; 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-Eeinstellungen für "PAUSE1ms"

PAUSEE								; Einsprungstelle für Pausenschleife
		nop
		nop										 	
		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





;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

LED
		addwf	PCL,1
		retlw	D0_AN	
		retlw	D1_AN	
		retlw	D2_AN	
		retlw	D3_AN
		retlw	D4_AN
		retlw	D5_AN	
		retlw	D6_AN	
		retlw	D7_AN
		retlw	D8_AN
		retlw	D9_AN

;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

		END

Dieses arbeitet seit über einem Jahr zuverlässig.
Ich dachte ich brauch org 0x00 und org 0x04 nur dann,
wenn ich die ISR verwende. Möchte meine Programme
nicht unnötig verkomplizieren.
Der PIC fängt ja immer bei 0x00 an,
oder sehe ich da etwas falsch.
Wie kann ich das mit den Tabellen besser machen ?

Grüsse Schlapfi

Klicke auf die Grafik für eine größere Ansicht

Name:	Voltmeter.jpg
Hits:	6
Größe:	24,3 KB
ID:	30101