;********************************************************** ;* meter.ASM ;********************************************************** ;* Nammen der Gruppenmitglieder ;* Datum ;********************************************************** ;* ;* Firmware für Digitalvoltmeter Demonstration ;* ;* ICD OPTIONEN: ;* Configurationsbits: ;* Oscillator: RC ;* Watchdog: Off ;* Power Up: ON ;* Brown Out: Off ;* Low Voltage: OFF ;* Code Protection Data EE: Off ;* Flash Mem. Write: ON ;* Code Protect: Off ;* ;* Program Options: ;* Programm Memory :On ;* Configuratins Bits: ON ;* ID Locations: ON ;* EEPROM Data: OFF ;* Erase All before Program: ON ;* Enable Debug Mode: OFF ;********************************************************** ;* ;* Beschreibung der Funktion ;* ;* Dies ist ein digitales Voltmeter. ;* ;* ;* Ein Spannungswert wird eingelesen und mit einem ;* ;* Analog-Digital-Konverter umwandelt. Zur genaueren ;* ;* Messung wird ein Mittelwert über 8 Werte gebildet. ;* ;* Damit werden Oberschwingungen und Aehnliches ;* ;* unterdrueckt. ;* ;* Dieser Wert wird danach in 3 BDC-Zahlen und ;* ;* anschlieszend in 3 binaere Zahlen umgewandelt. ;* ;* Ein Interrupt wird dazu verwendet, um in kurzen ;* ;* Zeitabstaenden die verschiedenen 7-Segmentanzeigen ;* ;* einzuschalten und somit alle Werte sichtbar zu machen. ;* ;**************************************************************************** TITLE "meter" list p=16f877 ;Prozessortyp include "p16f877.inc" ;Registerdefinitionen ;**************************************************************************** ; Definition der verwendeten Variablen ;**************************************************************************** intCount EQU 0x20 ergH EQU 0x21 ergL EQU 0x22 mittelCount EQU 0x23 bitSave EQU 0x24 byte0bin EQU 0x29 byte1bin EQU 0x2A byte2bin EQU 0x2B zwi EQU 0x2C W_STACK EQU 0x2D S_STACK EQU 0x2E FSR_STACK EQU 0x30 TAUSEND EQU 0x31 HUNDERT EQU 0x32 ZEHN EQU 0x33 EINS EQU 0x34 ZAEHLERH EQU 0x35 ZAEHLERL EQU 0x36 ;**************************************************************************** ; MAKRODEFINITIONEN ;**************************************************************************** BANK_0 macro ;Schaltet auf Bank 0 um bcf STATUS, 5 bcf STATUS, 6 endm BANK_1 macro ;Schaltet auf Bank 1 um bsf STATUS, 5 bcf STATUS, 6 endm BANK_2 macro ;Schaltet auf Bank 2 um bcf STATUS, 5 bsf STATUS, 6 endm BANK_3 macro ;Schaltet auf Bank 3 um bsf STATUS, 5 bsf STATUS, 6 endm ;**************************************************************************** ; Programmbeginn ;**************************************************************************** org 0 ;Startadresse nach Reset nop ; notwendig, damit Debugger funktioniert goto Start ;Sprung zum Hauptprogramm ;**************************************************************************** ; Interruptbearbeitung ; ; Dieses Interrupt schaltet alle 7-Segment-Anzeigen an und aus, ; damit alle einmal leuchten ; ;**************************************************************************** org 4 ; Startadresse nach Interrupt int bcf intcon, gie ; alle Interrups abschalten movwf w_stack ; W retten movf status, w movwf s_stack ; Status retten movf fsr, w movwf fsr_stack ; fsr retten BANK_0 btfss PIR1,0 ; Richtiger Interrupt? goto int_end movf PORTB,W ; Alle 7-Segs abschalten andlw b'11110001' movwf PORTB movf intCount,W ; Counter auf Wert pruefen und richtige 7-Seg anschalten movwf zwi decf zwi btfsc STATUS,Z goto intC0 decf zwi btfsc STATUS,Z goto intC1 goto intC2 intC0 movf byte2bin,W ; Linke 7-Seg anschalten movwf PORTD movf PORTB,W iorlw b'00001000' movwf PORTB movlw b'00000011' ; Zaehler zuruecksetzen movwf intCount goto int_end intC1 movf byte1bin,W ; Mittlere 7-Seg anschalten movwf PORTD movf PORTB,W iorlw b'00000100' movwf PORTB goto intCA intC2 movf byte0bin,W ; Rechte 7-Seg anschalten movwf PORTD movf PORTB,W iorlw b'00000010' movwf PORTB intCA decf intCount ; Zaehler erniedrigen int_end bcf PIR1,0 ; Timer1 zuruecksetzen movlw b'11111100' movwf TMR1H movlw b'00010111' movwf TMR1L movf fsr_stack, w movwf fsr ; fsr wiederherstellen movf s_stack, w movwf status ; Statusregister wiederherstellen swapf w_stack, 1 swapf w_stack, w ; W-Register wiederherstellen bsf intcon, gie ; Interrups einschalten retfie ; END Interruptservice ;**************************************************************************** ; UNTERPROGRAMME ;**************************************************************************** ;**************************************************************************** ; 1) 2) Unterprogramm adcUMittel ; ; Dieses Programm fuehrt eine ADC durch und bildet den Mittelwert ; ueber mehrere Messwerte. ; ;**************************************************************************** adcUMittel movlw b'00001000' ; Zaehler auf default setzen movwf mittelCount clrf ergH clrf ergL adcStart bsf ADCON0,2 ; ADC starten adcWait btfsc ADCON0,2 goto adcWait movf ergH,W ; Wert addieren addwf ADRESH,W movwf ergH movf ergL,W BANK_1 addwf ADRESL,W BANK_0 movwf ergL btfsc STATUS,C incf ergH decf mittelCount ; Zaehler dekrementieren btfss STATUS,Z goto adcStart ; Zurueckspringen bcf STATUS,C ; Wert durch 8 dividieren rrf ergH rrf ergL bcf STATUS,C rrf ergH rrf ergL bcf STATUS,C rrf ergH rrf ergL return ;**************************************************************************** ; 3) BCD ; ; UMWANDLUNG VON MESSWERT AUF 4 BCD ZIFFERN ; ; Wandelt den Mittelwert, der vorher aus den Messwerten gebildet wurde, ; auf 4 BCD-Ziffern um. ; ; EINGABE: ; - Mittelwert ; AUSGANG: ; - 4 BCD Ziffern ; byte3bcd ; byte2bcd ; byte1bcd ; byte0bcd ; ;**************************************************************************** mittel2bcd clrf tausend clrf hundert clrf zehn clrf eins clrf zaehlerH clrf ZaehlerL ask movf ergH, w ; Ist zählerH gleich ergH ??? subwf zaehlerH, w btfss status, z goto ZungleichE ; wenn zaehlerH ungleich ergH... movf ergL, w ; Ist zählerL gleich ergL ??? subwf zaehlerL, w btfss status, z goto ZungleichE return ZungleichE incf zaehlerL, f ; eins hochzählen btfsc status, Z incf zaehlerH, f incf eins, f isteins10 movf eins, w ; ist eins schon 10? sublw b'00001010' btfsc status, z goto eins10 istzehn10 movf zehn, w ; ist zehn schon 10? sublw b'00001010' btfsc status, z goto zehn10 isthundert10 movf hundert, w ; ist hundert schon 10? sublw b'00001010' btfsc status, z goto hundert10 goto ask eins10 clrf eins incf zehn, f goto istzehn10 zehn10 clrf zehn incf hundert, f goto isthundert10 hundert10 clrf hundert incf tausend, f goto ask ;**************************************************************************** ; 4) Unterprogramm bcd2segment ; ; UMWANDLUNG AUF DARSTELLUNG ; ; Wandelt 4 BCD Werte so um, dass sie auf 3 7-Segment-Anzeigen angezeigt ; werden können. Außerdem wird ein Dezimalpunkt gesetzt. ; ; EINGABE: ; - BCD-Werte: ; byte0bcd ; byte1bcd ; byte2bcd ; byte3bcd ; AUSGANG: ; - Binäre Werte für 7-Segment Anzeige, mit gesetztem Komma ; byte0bin ; byte1bin ; byte2bin ; ;**************************************************************************** bcd2segment movf tausend,F btfsc STATUS,Z goto stellen4 ; Zahl ist 4-stellig movf tausend, w ; byte3 decoden call decode movwf byte2bin movf hundert, w ; byte2 decoden call decode movwf byte1bin movf zehn, w ; byte1 decoden call decode movwf byte0bin bsf byte1bin, 7 ; Komma setzen return stellen4 movf hundert, w ; byte2 decoden call decode movwf byte2bin movf zehn, w ; byte1 decoden call decode movwf byte1bin movf eins, w ; byte0 decoden call decode movwf byte0bin bsf byte2bin, 7 ; Komma setzen return ;**************************************************************************** ; Unterprogramm decode ; ; Dieses Programm decodiert eine binaere Zahl zu einer 7-Segment-Anzeige ; ;**************************************************************************** decode addwf PCL,F retlw b'00111111' ; 0 retlw b'00000110' ; 1 retlw b'01011011' ; 2 retlw b'01001111' ; 3 retlw b'01100110' ; 4 retlw b'01101101' ; 5 retlw b'01111101' ; 6 retlw b'00000111' ; 7 retlw b'01111111' ; 8 retlw b'01101111' ; 9 return ;END ;**************************************************************************** ; Hauptprogramm ;**************************************************************************** ;**************************************************************************** ; Initialisierungen ;**************************************************************************** Start BANK_1 ; Register konfigurieren movlw b'00001001' movwf TRISA movlw b'00000000' movwf TRISB movwf TRISC movwf TRISD movlw b'10000001' movwf ADCON1 movlw b'00000001' movwf PIE1 movlw b'11000000' movwf INTCON BANK_0 movlw b'01000001' movwf ADCON0 movlw b'00000001' movwf T1CON movlw b'00000001' ; Variablen auf 1 setzen movwf intCount movlw b'00000000' ; Variablen auf 0 setzen movwf ergH movwf ergL movwf mittelCount movwf byte0bin movwf byte1bin movwf byte2bin ;*************************************************************************** ; Hauptschleife ;**************************************************************************** main call adcUMittel call mittel2bcd call bcd2segment goto main ;**************************************************************************** ; Programmende ;**************************************************************************** END