;--------------------------------Konfiguration--------------------------------------------- list p=16f877 ;Prozessortyp angeben #include ;Iclude Datei für Controllervariablen einfügen ;Config-Bits __CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _XT_OSC & _CPD_OFF & _LVP_OFF Errorlevel -302 ;BANKSEL-Meldungen abschalten ;------------------------------------------------------------------------------------------ ;-----------------------------------Belegung des PICs (PIC 16F877)------------------------- ; ; ________________ ; MCLR 5V--------1| |-------Rel 16 RB7 ; RA0 Kanalsw1------2| |-------Rel 15 RB6 ; RA1 Kanalsw2------3| |-------Rel 14 RB5 ; RA2 Kanalsw3------4| |-------Rel 13 RB4 ; RA3 Kanalsw4------5| |-------Rel 12 RB3 ; RA4 EDIT-sw-------6| |-------Rel 11 RB2 ; RA5 EDIT-Mode Out-----7| |-------Rel 10 RB1 ; RE0 BCD-Cathode1------8| PIC16F877 |-------Rel 9 RB0 ; RE1 BCD-Cathode2------9| |-------VDD(5V) VDD ; RE2 BCD-Cathode3-----10| |-------VSS(0V) VSS ; VDD VDD(5V)------11| |-------Rel 8 RD7 ; VSS VSS(0V)------12| |-------Rel 7 RD6 ; OSC1 OSC1---------13| |-------Rel 6 RD5 ; OSC2 OSC2---------14| |-------Rel 5 RD4 ; RC0 BCD8---------15| |-------RX(MIDI-IN) RC7 ; RC1 BCD4---------16| |-------TX(RS-OUT) RC6 ; RC2 BCD2---------17| |-------Frei RC5 ; RC3 BCD1---------18| |-------Frei RC4 ; RD0 Rel1---------19| |-------Rel 4 RD3 ; RD1 Rel2---------20|________________|-------Rel 3 RD2 ; ; ; ;------------------------------------------------------------------------------------------ ;-------------------Variablen------------------------ loops EQU 0x20 ; Variable loops für Zählschleife preset EQU 0x21 ; Variable für die aktuelle Nummer preseth EQU 0x22 ; Hilfsvariable für preset Einer EQU 0x23 ; Rechte Ziffer der Anzeige Zehner EQU 0x24 ; Mittlere Ziffer der Anzeige Hunderter EQU 0x25 ; Linke Ziffer der Anzeige durchg EQU 0x26 ; durchgaenge der Schleife presetAnz EQU 0x27 ;presetanzeigevariable org 0x00 ; Sprungziel bei reset goto STARTUP ;-------------------------------------------ISR---------------------------------------------------- org 0x04 ; Sprungziel bei Aufruf ISR goto ISR ISR btfss PIR1, RCIF ; Pruefen ob Interupt durch Receive ausgeloest wurde goto ISREND ; Wenn nein, gehe zu Ende von ISR movfw RCREG ; Empfangsregister auslesen movwf preset ; nach preset schreiben call RS232Send bcf PIR1, RCIF ; Receive-Interupt-Bit wieder loeschen ISREND retfie ; Zurückkehren aus Interuptroutine ;------------------------------------Hauptprogrammschleife------------------------------------- STARTUP BCF CCP1CON, CCP1M3 ; Abschalten der 2 Capture- BCF CCP1CON, CCP1M2 ; Compare-Module BCF CCP1CON, CCP1M1 BCF CCP1CON, CCP1M0 BCF CCP2CON, CCP2M3 BCF CCP2CON, CCP2M2 BCF CCP2CON, CCP2M1 BCF CCP2CON, CCP2M0 BSF STATUS, RP0 ; auf Bank 1 Umschalten MOVLW B'00000110' ; PCFG0-3 aus ; =Analog-Digital-Wandler aus MOVwf ADCON1 ; nach AD-Register schreiben ;---------------------Ports------------------------ MOVLW B'11011111' ; Konfiguration Port A. 6+7 nicht vorhanden MOVWF TRISA ; RA5 Output. RA4-RA0 inputs MOVLW B'00000000' ; Konfiguration Port B MOVWF TRISB ; Port B komplett Outputs (Rel 9-16) MOVLW B'10000000' ; Konfiguration Port C. 7= RX = Input | 6= TX = Output MOVWF TRISC ; 4+5 unbenutzt= Output | 3-0 = BCD-Ausgänge = Outputs MOVLW B'00000000' ; Konfiguration Port D MOVWF TRISD ; PORT D Komplett Outputs (Rel 1-8) MOVLW B'00000000' ; Konfiguration Port E MOVWF TRISE ; RE0-RE2 = Cathode Outs für BCD; 4 muss 0 sein, sonst ; Wären Port E und Port D Paralel Slave Port ;---------------------RS232------------------------ clrf PIE2 ; Interuptarten Rücksetzen bsf PIE1, RCIE ; Receive Interupts Enable movlw D'25' ; Ergibt zusammen mit BRGH='0' 31.250 kbaud/s movwf SPBRG ; und mit SPBRG='25' 2400 baud/s movlw B'00100010' ; Sender Einstellen: 8 Bit-Modus, Transmit Enable movwf TXSTA ; asynchrone mode, Tranmit Shift Register Leer (=1) bcf STATUS, RP0 ; zurück in Bank 0 movlw B'10010000' ; Empfänger Einstellen: Pins RX und TX aktivieren movwf RCSTA ; 8 Bit-Empfang, Continous Receive clrf INTCON ; Interupterlaubnis Ruecksetzen bsf INTCON, GIE ; Interupts generell erlauben (Global Interupt Enable) bsf INTCON, PEIE ; Peripheral Equipment Interupt Enable ;--------------------Ports auf Null---------------- clrf PORTA ; Alle Ausgänge Low clrf PORTB clrf PORTC clrf PORTD clrf PORTE ;--------------------Ausgangszustand--------------- movlw D'0' movwf preset ; 0 als Grundwert Definieren call RS232Send ;----------------------------MAIN------------------------------------ MAIN call Presettabelle M2 call Anzeigeschleife goto MAIN ;-------------------------------------BCD-Tabelle----------------------------------------------- ; BCD-Zuordnungen für 7-Segment-Anzeige BCD addwf PCL,f ; addiert den Wert aus W mit dem Programmcounter ; Es folgen die Zuordnungen für den Port C in BCD ; retlw kehrt zurück mit dem Wert im Akku ; ACHTUNG! Aufgrund der Portbelegung ist RC3 die 1er-Stelle ; und RC0 die 8er-Stelle! Nach dem ersten Nipple Also ; "Digital, aber von links nach rechts! LSB links, MSB rechts! retlw B'00000000' ; 0 retlw B'00001000' ; 1 retlw B'00000100' ; 2 retlw B'00001100' ; 3 retlw B'00000010' ; 4 retlw B'00001010' ; 5 retlw B'00000110' ; 6 retlw B'00001110' ; 7 retlw B'00000001' ; 8 retlw B'00001001' ; 9 ;------------------------------------------------------------------------------------------------- ;-------------------------------------Presettabelle--------------------------------------------- Presettabelle Anzeigeberechnung clrf Einer ; Ziffernwerte löschen clrf Zehner clrf Hunderter movfw preset ; Presetnummer in Akku laden movwf presetAnz HunAuswertung movlw d'100' ; Hundert von PresetH abziehen subwf presetAnz btfss STATUS, C ; Oder wurde ein Carry-Bit geloescht? goto Unterhundert ; Dann wars weniger als Hundert! incf Hunderter goto HunAuswertung Unterhundert movlw d'100' addwf presetAnz ZehnerAuswertung movlw D'10' subwf presetAnz ; ziehe Zehn ab btfss STATUS, C ; Oder gabs gar schon einen Überlauf? goto UnterZehn ; Dann gehe auch zu den Einern! incf Zehner ; erhöhe Zehner um eins goto ZehnerAuswertung ; Und mach weiter mit der Auswertung der Zehnerstelle UnterZehn movlw D'10' addwf presetAnz ; Wieder 10 addieren EinerAuswertung movfw presetAnz ; Schreibe den Rest in Einer movwf Einer Return ; Und gehe zurück! ; Das wars mit Anzeigeberechnung ;----------------------------------------------------------------------------------------------- Anzeigeschleife clrf PORTE clrf PORTC A1 bsf PORTE, 0 ; Segment eins aktiv movf Einer, 0 ; Wert Ziffer 1 laden call BCD ; BCD-Auswertung movwf PORTC ; 7-Segmentanzeige beschreiben call WAIT ; 1ms Warten bcf PORTE, 0 bsf PORTE, 1 movf Zehner, 0 call BCD movwf PORTC call WAIT bcf PORTE, 1 bsf PORTE, 2 movf Hunderter, 0 call BCD movwf PORTC call WAIT bcf PORTE, 2 ; movlw D'128' ; Lade Grenzwert in Akku ; subwf zahl, 0 ; Subtrahiere W von Zahl und Speichere in W ; btfsc STATUS, Z ; Überspringe nächsten Befehl wenn nicht null ; goto MAIN ; wieder von ganz vorne beginnen retlw D'0' ; wenn ja, gehe wieder zu M1 ;----------------------------------------------------------------------------------------------- ;------------------------------------RS232 Sendeprogramm---------------------------------------- RS232Send bsf STATUS, RP0 ; auf Bank eins umschalten Sendwait btfss TXSTA, TRMT ; Abfragen des Transmit Register Status-Bit, wenn gesetzt ist ; Senden moeglich goto Sendwait ; Wenn nicht, gehe zu Sendwait bcf STATUS, RP0 ; gehe wieder auf Bank 0 movfw preset ; Lade preset addlw D'1' ; Addiert eins zum preset dazu movwf TXREG ; Schreibt das Ergebnis (Preset Inkrementiert mit 1) in ; den Sender retlw D'0' ;------------------------------------Warteschleife 1 Millisekunde--------------------------------- ; Die Größe der Variablen "Sekunden" gibt die Durchläufe an. ; Ein Gesamtdurchlauf ist ca 1 Sekunde WAIT movlw D'255'; ; 110mal wird die Schleife durchlaufen um movwf loops; ; 1ms zu ergeben W2 nop nop nop nop nop nop decfsz loops, F ; Überprüfung ob 1 ms vorbei goto W2 ; noch nicht? dann nochmal ab W2 retlw d'0' ; gehe zurück ins Programm mit '0' im Akku END