====== Assembler Code V26 ====== ; ******************************************************************* ; Programm PATermV2.6.asm ; Dieses PA-Terminalprogrammes: Es beinhaltet einen 8 stelligen (4 Byte) ; Dekadischen Zähler zum zählen der Hübe eines Pressluftantriebes. Nach ; dem Aufzählen wird der BCD Stelleninhalt für die Siebensegmentanzeige ; codiert und anschliessend seriell an die Anzeige versandt. ; Das PA-Terminal ist Teilnehmer eines halbduplex RS485-Buses. An diesem ; ist es in der Lage mit einem Master seriell zu über km-Distanzen zu ; kommunizieren. Implementiert sind Befehle zur Hubzählauslese bzw. ; Korrektur, Seriennummernauslese und Korrektur, sowie Fehlerstandauslese ; und Löschung dessens. ; ******************************************************************* ; Seriennummer Antrieb: SN equ d'00000137' ; Terminal Nr. 1 ; Register ; Namen-Registeradressen (Festwert): ; Bank 0: ; Bank 1: INDF equ 0x00 ; <- TMR0 equ 0x01 ; Option Register PLC equ 0x02 ; <- STATUS equ 0x03 ; <- FSR equ 0x04 ; <- PORTA set 0x05 ; TRISA PORTB set 0x06 ; TRISB EEDATA equ 0x08 ; ECON1 EEADR equ 0x09 ; ECON2 PCLATH equ 0x0A ; <- INTCON equ 0x0B ; <- ; Bank 1: TRISA set 0x05 TRISB set 0x06 EECON1 equ 0x08 EECON2 equ 0x09 ; Variablen ByteNr set 0x0C Anzeige set 0x0D Anzeigewert set 0x0E Testwert set 0x0F B3 set 0x10 ; Höchste Doppelstelle Anzeige: Mio. und Zehnmio. B2 set 0x11 ; dritte Doppelstelle Anzeige: Zehntausender und Hundertaus. B1 set 0x12 ; zweite Doppelstelle Anzeige: Hunderter und Tausender B0 set 0x13 ; niedrigstes Doppelstelle Anzeige: Einer und Zehner B3? set 0x14 ; Redundanzstellen B2? set 0x15 B1? set 0x16 B0? set 0x17 B3?? set 0x18 B2?? set 0x19 B1?? set 0x1A B0?? set 0x1B ESpeicherA set 0x1C PWMa set 0x1D Buffer set 0x1E ; Speichert schon gesendet Status PWMs set 0x1F A0 set 0x20 ; Adressspeicher MSB (ID PA-Terminal) A1 set 0x21 ; Adressspeicher LSB F0 set 0x22 ; Fehlerbyte MSB F1 set 0x23 ; Fehlerbyte LSB A0? set 0x24 ; Redundanzstellen A1? set 0x25 ; F0? set 0x26 ; F1? set 0x27 ; A0?? set 0x28 ; A1?? set 0x29 ; F0?? set 0x2A ; F1?? set 0x2B ; Schleife1 set 0x2C Schleife2 set 0x2D Schleife3 set 0x2E Schleife4 set 0x2F B3??? set 0x30 B2??? set 0x31 B1??? set 0x32 B0??? set 0x33 Telnr set 0x34 SERBUF set 0x35 Bitindex set 0x36 Schleife5 set 0x3C Schleife6 set 0x3D RAM1 set 0x3E RAM2 set 0x3F Steuer set 0x40 Adresse0 set 0x41 Adresse1 set 0x42 D1 set 0x43 D2 set 0x44 D3 set 0x45 D4 set 0x46 identisch set 0x47 Fehler set 0x48 Fehlkont set 0x49 ; Fehlerkontrollbyte korrekt set 0x4A TS set 0x4B Sprung set 0x4C RAM set 0x4D Vorgabe set 0x4E ; Vergleich set 0x4F ; ; Konstanten PWMF equ 0x50 ; Pulsweitenschwelle ( aus) PWMm equ 0x7F ; Pulsweitenzyklusmaximalwert uSchwelle equ D'16' ; oSchwelle equ D'111' ; ;Bitnamen c equ 0 ; (STATUS) z equ 2 ; (STATUS) RP0 equ 5 ; (STATUS) RP1 equ 6 ; (STATUS) IRP equ 7 ; (STATUS) GIE equ 7 ; (INTCON) RBIF equ 0 ; (INTCON) INTE equ 4 ; (INTCON) WR equ 1 ; (EECON1) WREN equ 2 ; (EECON1) RD equ 0 ; (EECON1) EEIF equ 4 ; (EECON1) ; PORTA ClockLED equ 2 ; Pin1: Anzeige Clock (Bit 2 Port A) serLED equ 3 ; Pin2: Serielle Daten zur Anzeige (Bit 3 Port A) Strobe equ 4 ; Pin3: Strobe zur Anzeige Übernahme (Bit 4 Port A) OutEnabl equ 1 ; Pin18: Anzeige an/aus (Bit 1 Port A) ; PortB Moved equ 0 ; Pin6: Moved (inside) Signal ; Hardware (Jumper) Sperre Nullung Zählerstand: ZeroReset equ 1 ; Pin07: Low = Nullsetzen gesperrt, ; high Nullsetzen möglich ReportTrans equ 2 ; PIN08: Serielle Daten Ausgabe Direction equ 3 ; Pin09: Richtung der Halbduplex RS485: ; low = receive, ; high = send iniDataSave equ 4 ; Pin10: veranlassse Datensicherung : ; high = on power, ; low = Datensicherung ausführen! Commands equ 5 ; Pin11: Received Remote Commands Program equ 6 ; Pin12: In Curcuit Programm Data ProClock equ 7 ; Pin13: Inserie-Programmierclock ; Makrodefinitionen bank0 macro bcf STATUS, RP0 endm bank1 macro bsf STATUS, RP0 endm org 0x00 goto main ; hier potetielle Interrups main NOP ; (Wg. Einsprung Interlock an h'04'!) NOP goto Start ; Interruptrutine DATASAVE an H'04' ; vvvvv hier Interrupt-Einsprungpunkt vvvv Call Interrupt ; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Bei Powerdown: Stop in Interrupetrutine ; Bei Fernbefehlsempfang: mache nun weiter! goto Zyklus ; springe an Anfang Konsistenztest return Start ; Initialisierung bank1 ; Disable Interupts ! BCF INTCON, GIE ; IO-Port Einrichtung bank0 ; adressiere Bank0 CLRF PORTA bank1 ; adressiere Bank1 MOVLW B'00000000' ; 8x Ausgang MOVWF TRISA ; Setze Richtung bank0 ; adressiere Bank0 CLRF PORTB bank1 ; adressiere Bank1 ; Datasave 4-vv-3 Direction ; Command 5-v v-2 SerData ; Pro1 6-v v-1 ZeroReset ; Pro2 7-v v-0 frei MOVLW B'00110011' ; 4x Ausgang, 4x Eingang MOVWF TRISB ; Setze Richtung bank0 ; adressiere Bank0 BCF PORTB, Direction ; Initialisiere auf Empfang BCF PORTB, ReportTrans ; Ini. ausgabe Null BCF PORTB, 6 ; Ini Programmmierport Null BCF PORTB, 7 ; Ini. Programmierport Null MOVLW H'00' MOVWF ESpeicherA ; Lade EEpromstartwert MOVLW D'1' ; "Moved"-Spikebuffer MOVWF Buffer CLRF Fehler ; Ini. Pulsweitenmodulation: PWMm >>>>>>>>>>>> PWMa >>>> PWMs >>> 0 MOVLW PWMm ; (In der "Delay"-Rutine ist die Wiederholfrequenz hoch! MOVWF PWMa ; wird in aktuellen Laufwert geladen. MOVLW h'40' ; Starte bei Powerup mit Anzeige an! MOVWF PWMs ; wenn diese Schwelle erreicht, dann schalte ein, ; hier Daueraus, da PWMa nie gleich 0, da PWMA wieder orher wieder ; auf PWMm gesetzt wird! Normalschwelle sonst gleich 1 und somit ; PWM-Faktor gleich : 1/PWMm= 64/127 = 0,5 ; ************************** BTFSS PORTB, 1 ; Wenn Inijumper offen: ZeroReset = H (EE-> Null), goto LeseEE ; sonst, wenn gesetzt: ZeroReset = L: EEprom>RAM Call Nullsetzen ; Nullsetzen EEPROM 1,3ms ; goto SCHLUSS ; hier evtl. warten auf Traffic zur SN-Erstvergabe LeseEE Call HoleEE ; hole Zählerstand (4Byte=8Stellen), SN(2Byte=4Stellen) ; sowie Fehlerstand (2Byte=4Stellen) ; Dauer: 0,9 ms (-> 2,4ms) ; Anzeige Seriennummer ; (Missbraucht Zählerstandstellen, aber Konsistenz korigiert das!) MOVF B3, 0 ; Temporäre Auslagerung MOVWF B3??? MOVF B2, 0 MOVWF B2??? MOVF B1, 0 MOVWF B1??? MOVF B0, 0 MOVWF B0??? ; **** Anzeige 1x Start **** ; Anzeige "Start !" MOVLW H'DE' ; " !" MOVWF B0 MOVLW H'BD' ; "t "-120 MOVWF B1 MOVLW H'AC' ; "ar"- MOVWF B2 MOVLW H'5B' ; "St"-80 MOVWF B3 Call IniStream Call STREAM ; Zeige "Start !" Call Delay ; ca. 1,5s Verzögerung (incl. PWM !). MOVF A0, 0 ; lade LSB Adresse = Seriennummer (Dekadisch) MOVWF B0 MOVF A1, 0 ; lade MSB Adresse MOVWF B1 MOVF Fehler, 0 ; Zeichen " " (Test EESCHreibfehler) MOVWF B3 MOVLW H'5F' ; Zeichen "Sn" MOVWF B2 ; Sn#-Anzeige Call IniStream Call STREAM ; Zeige "Sn xxxx" Call Delay ; ca. 1,5s Verzögerung. MOVF B3???, 0 ; Rückverlagerung MOVWF B3 MOVF B2???, 0 MOVWF B2 MOVF B1???, 0 MOVWF B1 MOVF B0???, 0 MOVWF B0 Call IniStream Call STREAM ; Zeige Hubzählerstand Call Delay ; ca. 1,5s Verzögerung. ; Achtung: Delayrutine nutzt Zähler, deswegen Zählwert wiederherstellung danach: MOVF B3???, 0 ; Rückverlagerung .. MOVWF B3 ; in drei Redundanzstellen ... MOVWF B3? MOVWF B3?? MOVF B2???, 0 MOVWF B2 MOVWF B2? MOVWF B2?? MOVF B1???, 0 MOVWF B1 MOVWF B1? MOVWF B1?? MOVF B0???, 0 MOVWF B0 MOVWF B0? MOVWF B0?? Frei ; Freigabe der Interlocks !!! BSF STATUS, RP0 ; Bank1 ; v- Global Interlock ; v- RB0 (B3): "Moved" (alt V1: RA0, neu V2: an RB0) ; v- RB4-7 (B4): z.B. Commannds MOVLW B'10001000' ; Enable (B0) global interlock, ; and special: RB0 (B3), RB4-7 (B4) MOVWF INTCON ; Schreibe ins Inerlockkontrollregister BCF STATUS, RP0 ; Bank0 ; Ini. Pulsweitenmodulation für Normalzyklus (geringer Frequenz wg. Konsist.) ; an |-> aus ; PWMm >>>>>>>>>>>> PWMa >>>> PWMs >>> 0 MOVLW PWMm ; (In der "Delay"-Rutine ist die Wiederholfrequenz hoch! MOVWF PWMa ; wird in aktuellen Laufwert geladen. MOVLW h'0' ; Starte mit Anzeige aus! MOVWF PWMs ; wenn diese Schwelle unterschritten, dann schalte ein, ; hier Daueraus, da PWMa nie gleich Null, da PWMA vorher wieder ; auf PWMm gesetztwird! Normalschwelle sonst gleich 1 und somit ; PWM-Faktor gleich : 1/PWMm= 1/16. MOVLW D'1' ; Clear des Filterbuffers! MOVWF Buffer ; ab dort wieder 16 High zum Senden nötig! ; ************************************************************************************** ; ****************************** Der Zyklus ******************************************** Zyklus MOVF PORTB, 0 ; Signal "Moved" MOVWF B3??? ; PORTB Sicherung (gg.f. Vergleich mit Vorzustand) Call Konsistenz ; 0,6 ms ->1,8 ms (1,2 ms) ; Eingefahren: zählen und senden BTFSS PORTB, Moved ; wenn Moved high wird und ... goto NSenden BUF ;Ausgef.: ,->127----------/------127 ; uS(16) oS(111) ;Eingef.: 1-------/-------------<1-' MOVlW d'127' SUBWF Buffer, 0 ; wenn voll (127), dann... BTFSS STATUS, z ; ... nicht erhöhen. INCF Buffer, 1 ; sonst erhöhe Spikepuffer MOVLW uSchwelle SUBWF Buffer, 0 ; wenn untere Schwelle überschritten BTFSS STATUS, z ; Nach 16x High gesehen: latsche (1. Schwellwert) goto hatschon ; genau einmal nach 16 Highs Latchzaehlen ; 11111111111111111111111111111111111111111111111 CALL IniByte CALL EinByte ; Springe in dek. Aufzählrutine senden CALL IniStream ; Initialisierung Straeming CAll STREAM ; Acht Byte an Anzeige shiften MOVF B3, 0 ; neuen Zählerstand ... MOVWF B3? ; in restliche Redundanzstellen ... MOVWF B3?? MOVF B2, 0 MOVWF B2? MOVWF B2?? MOVF B1, 0 MOVWF B1? MOVWF B1?? MOVF B0, 0 MOVWF B0? MOVWF B0?? MOVLW D'127' MOVWF Buffer ; ansonsten wenn bereits gefahren, goto hatschon ; halte gesendet und mach weiter NSenden ; 22222222222222222222222222222222222222222222222 DECF Buffer, 0 ; Test dekrementieren in W BTFSC STATUS, z ; wenn schon 1 nicht weiter dekrementieren! goto hatschon ; noch im Bereich < uSchwelle MOVF Buffer, 0 ; z.B d'112' SUBLW oSchwelle ; Teste auf Erreichen oSchwelle BTFSS STATUS, z ; Rücksetzen, wenn Schwelle (z.B. D'111') goto w4 ; unterschritten! MOVLW D'1' ; Clear des Sendebuffers! MOVWF Buffer ; ab dort wieder 16 High zum Senden nötig! goto hatschon w4 DECF Buffer, ; reduziere Spikebuffer (bei Low-INSIDE) ; hatschon ;Call Pulsweitenmodulation ; (nun im Konsistenztest intergriert wg. höherer Frequenz) MOVLW H'99' ; Bei 99 Mio ist ganz Schluss SUBWF B3, 0 ; Subtrahiere ByteNr-4 BTFSS STATUS, z ; Checke ob am Ende goto Zyklus ; Bei 99 Mio. beginne bei Null! goto SCHLUSS ; ************************************************************************************** ; ************************************************************************************** Interrupt ; !!!!!!! an PORTB,4 (iniDatasave, kann Prellen) !!!!!!!! ; !!!!!!! oder PORTB,5 (Command line changed) !!!!!!!! ; !!!!!!! tritt eine Änderung auf !!!!!!!! BSF PORTB, 7 ; Triggertestpunkt MOVF Buffer, 0 ; Prellfilter "Move"-Signal MOVWF B2??? ; Sichere Filterbuffer für "Move" zwischen. MOVLW d'1' ; Startwert Filterbuffer "inidatasave" MOVWF Buffer StartBit? ; war es nur ein Startbit ? (RS485 ist vorgespannt stabil) BTFSS PORTB, Commands ; Polle auf Startbit(L) ... goto NurBefehl BUF2 ; ******** Entprellfilter ******************************************** ; Wenn Interrupt nicht durch Remote Befehl (Start= Low), ; dann Entprellen vor Datensicherung! ; AUS: ,->127-----------/------127 ; uS(16) oS(111) ; AN: 1-----/------------1<--' BTFSC PORTB, iniDataSave ; wenn iniDataSave low ist erhöhe Zähler, ... goto AN ; ... sonst wenn wieder high: Trigger abwärts, reduziere Zähler aufwärtsZ COMF Buffer, 0 ; wenn voll (255), dann nicht erhöhen:... BTFSC STATUS, z ; ... voll? goto BUF2 ; nächste Prellprüfung. INCF Buffer, 1 ; .. nicht voll: Zähler erhöhen! MOVLW uSchwelle SUBWF Buffer, 0 ; wenn untere Schwelle überschritten BTFSS STATUS, z goto BUF2 ; nächste Prellprüfung. AUS ;(Zustand): Nach 16x Low: Daten sichern (1.Schwellwert) -> AUS! Call SchreibeEE ; 0-> Shut down, Datensicherung! GOTO SCHLUSS ; Da gibt's kein Zurück! AN ;(Zustand): noch weiter an falls nur Prellensolange MOVLW D'1' SUBWF Buffer, 0 ; zunächst nur testweise in W dekrementieren BTFSC STATUS, z ; wenn schon 1 raus aus Filter und Interrupt! goto w7 MOVF B2???, 0 ; hole zwischengespeicherten Filterbuffer "Move" MOVWF Buffer ; übernehme wieder Filterbuffer "Mov" (im Zyklus relevant!) BCF PORTB, 7 ; Nur f. Test: Lösche Interuped-status bcf INTCON, 0 ; lösche RBchange-Interuppt (Spike IniDatasave) ; Global Interuped wird by Return gelöscht retfie ; war nur Stöhrung: Ausgang aus Interrupt ... w7 MOVLW oSchwelle ; Buffer weiter reduzieren SUBWF Buffer, 0 ; Teste auf Erreichen oSchwelle BTFSS STATUS, z ; Rücksetzen, wenn Schwelle (d'127' h'80') unterschritten goto reduziere MOVLW D'2' ; Clear des Filterbuffers! MOVWF Buffer ; ab dort wieder 16 High zum Senden nötig! reduziere DECF Buffer, 1 ; reduziere Buffer, aber weiter im Filter! goto BUF2 NurBefehl ; 22222222222222222222222222222222222222222222 Call traffic ; 1-> Power da, aber Befehleingang! BCF PORTB, 7 ; Nur f. Test: Lösche Interuped-status bcf INTCON, 0 ; lösche RBchange-Interupped (Datenverker) ; Global Interuped wird by Return gelöscht BCF PORTB, 3 ; Ändere Halfduplex-Richtung: Mache RS485- ; Sender wieder zum Empfänger! MOVLW d'1' ; Totzeit nach aktuellem Befehl für neue Befehle: MOVWF Schleife3 ; (gibt externem Master Zeit zum Rückschalten von Totzeit Call ByteZeit ; Empfang auf Senden, Umschaltprozess kann sonst Decfsz Schleife3, 1 ; erneut Interupped auslösen! goto Totzeit ; Sperrzeit f. Master retfie ; Beende Interupt ; (nur nach Remotebefehl Abarbeitung) ;*************** Schreibe Datensicherung (Power down) RAM -> EEPROM ************ SchreibeEE BSF PORTB, 6 ; Test: Zeige Schreiben an RB6 an! MOVLW h'2' ; 1->0 zwei Zeilen MOVWF Schleife1 ; Zeilenindex (vom EEPROM aus) SS1 ; Start Schleife 1 MOVLW h'0C' ; 0B->....->0 (12x) MOVWF Schleife2 ; Spaltenindex SS2 ; Start Schleife2 Schreiben ; *** Bestimme Ursprung (RAM) und Zieladresse (EESpeicher) *** MOVF Schleife1, 0 ; Lade Zeilenwert in W MOVWF ESpeicherA ; Füge Zeilenwert in ESpeicherA ein DECF ESpeicherA, 1 ; (muss um eins kleiner sein als Schleife) SWAPF ESpeicherA, 1 ; Übernehme Wert in höheres Nibble: Zeilenindex MOVF Schleife2, 0 ; Lade Spaltenwert in W ADDLW h'FF' ; -1 ! (Muss um eins kleiner sein als Schleife) ADDWF ESpeicherA, 0 ; Addiere Spaltenwert zur Zeile in W MOVWF ESpeicherA ; Füge komplette Ursprungsadresse in ESpeicherA MOVLW h'10' ; ADDWF ESpeicherA, 0 ; W: Erhöhe Zielbereich RAM um eine Zeile ; gegenüber EEPROM! RAM = ESpeicherA + h'10' MOVWF FSR ; Pointer auf RAM-Adresse MOVF INDF, 0 ; Rufe gepointeten Inhalt ab! MOVWF EEDATA ; Übergebe RAM-Wert an EE-Übergabeadresse MOVF ESpeicherA, 0 ; Ziel ins EEPROM MOVWF EEADR ; Ziele auf EE_Adresse Ziel ; ************ Einschreiberutine ************ BSF STATUS, RP0 ; Wahl Bank1 BSF EECON1, WREN ; Enable Write Bit MOVLW h'55' MOVWF EECON2 MOVLW h'AA' MOVWF EECON2 BSF EECON1, WR KontrolleSi BTFSS EECON1, EEIF ; warte auf Flag Schreiberfolg! goto KontrolleSi BCF EECON1, EEIF ; Flag f. erfolgreiches EE-Schreiben rücksetzten BCF STATUS, RP0 ; wieder Bank0 wählen ; >>> Verrify: <<<< MOVF EEDATA, 0 ; Hole letzten Schreibwert in W! BSF STATUS, RP0 ; Wahl Bank1 BSF EECON1, RD ; Lese eingeschriebenes Byte BCF STATUS, RP0 ; wieder Bank0 wählen SUBWF EEDATA, 0 ; BTFSS STATUS, z ; Wenn Soll und ist gleich weiter ... INCF Fehler, 1 ; sonst Schreibfehler erhöhen! DECFSZ ESpeicherA, 1 ; zeige auf nächstes Byte BCF EECON1, WREN ; disable Write Bit ; ************ Ende Einschreiberutine *********** DECFSZ Schleife2, 1 ; Spalten abgearbeitet? goto SS2 ESchleifeSS1 DECFSZ Schleife1, 1 ; Zeilen abgearbeitet? goto SS1 BCF PORTB, 6 ; Test: Zeige Fertig Schreiben! RETURN ; To Befehl9 oder Interrupt und dann zum SCHLUSS mit ; Warten auf Powerdown. ; ********************* Remote-commands and Respond ************************************** ; Das PA-Terminal soll im Augenblick sechs Fernbefehle erkennen und gegebenfalls richtig ; beantworten. ; Dazu wird über einen RS485-Feldbus im Halpduplexbetrieb ein 7 Byte langes ; Mastertelegramm verschickt. ; Nach dem Versenden der sieben Byte geht der Master für eine ; gewisse Zeit auf Empfang um ebenfalls ; bis zu sieben Byte vom angesprochenen PA-Terminal ; zu erhalten. Da die Signalübertragung auf einem Bus, ; also mit mehreren Teilnehmern ; statt findet, sehen auch nich angesprochene Terminals sowohl Mastertelegramm wie auch ggf. ; die Antwort. Ein fälschliche Reaktion von anderen Teilnehmern darauf muss vermieden ; werden, ; da zu einem Zeitpunkt nur jeweils ein Sender auf dem Bus aktiv sein darf! ; Es gibt Adrressierte und Unadressierte Befehle (Mastertelegramme) ; ***************************************************************************************** traffic BTFSC PORTB, 3 ; Empfange Fernbefehle ... Return movlw h'7' movwf Schleife1 ; BCF PORTB, ReportTrans ; Bereite Ruhezustandsausgabe vor: ; bestimmt Pegel sobald auf Senden umgestell wird! Zeichenein ; ***************************************************************** ; Synchronisation auf Startbit (0) BTFSC PORTB, 5 ; übergehe bei Startbit erstes Mal gleich 0! goto Zeichenein ; suche weiter Startbit call half_Baud ; 14µS vorher bis hier: nun Warte halbe Baudrate btfsc PORTB, 5 ; 1µs (2µS) Wenn weiteres mal gleich Null: ; synchronisiert mit eingehendem Telegram! goto Zeichenein ; 2µS warte weiter wenn Startbit immer noch nicht da ; (Erstes war Spike)! ; einmal synchronisiert werden sieben Zeichen genommen, ob die da sind nicht! ; Startadresse vom Mastertelegramm ( Steuerbyte als Erstes: 40,41,...,47) movlw h'3F' ; 1µS movwf Telnr ; 1µS Zieladresse Telegram -1 Tele7 ; (10 µS Summe Befehle um Einlese SUB) movlw 8 ; 1 µS Beginne serielle Eingangssequenz movwf Schleife6 ; 1 µS erfasse 8 Datenbits clrf SERBUF ; 1 µS Lösche Buffer! incf Telnr, 0 ; 1 µS erhöhe Zieladresse und ... movwf Telnr ; 1 µS speichere in Variable zurück ... movwf FSR ; 1 µS wie auch in Pointer Call inch_n1 ; empfange einen Rahmen 104 µS ; (Start-Bit, 8x Daten-Bit, Stop-Bit) movwf INDF ; 1 µS Speichere Zeichen in Telegrammstellen! DECFSZ Schleife1, 1 ; 1µs (2µS) goto Tele7 ; 2µS erfasse sieben Zeichen wasnun ; Unadressierter Befehle Befehl5? ; Unadressierter Befehle movlw 5 ; Befehl Display einschalten ; (an allen PA-Terminal) subwf Steuer, 0 ; Vergleiche mit Steuerbyte BTFSS STATUS, z ; goto Befehl10? ; Display EINSCHALTEN movlw PWMF ; lade konstanten Schwellwert ... movwf PWMs ; in Schwellwertvariable ! goto fertigT ; Schwellwertvariable Befehl10? ; Unadressierter Befehle movlw d'10' ; Befehl Display einschalten ; (an allen PA-Terminal) subwf Steuer, 0 ; Vergleiche mit Steuerbyte BTFSS STATUS, z ; goto Befehl7? ; Display AUSSCHALTEN movlw 0 ; lade konstanten Schwellwert ... movwf PWMs ; in Schwellwertvariable ! goto fertigT ; Schwellwertvariable Befehl7? ; >>> Befehl Fehler nullsetzen (an allen PA-Terminal) movlw 7 subwf Steuer, 0 ; Vergleiche mit Steuerbyte BTFSS STATUS, z goto aBefehle clrf F1 ; Setze Fehlerzähler Konsistenz auf Null clrf F1? clrf F1?? clrf F0 clrf F0? clrf F0?? goto fertigT aBefehle ; Identifizierung, bin ich angesprochen? clrf Vergleich ; Bereite Adressvergleich vor movf Adresse0, 0 ; Lade Adresswert aus Telegram in W subwf A0, 0 ; Vergleiche mit LSB RAM-Adresse (reduntant) BTFSC STATUS, z INCF Vergleich, 1 movf Adresse1, 0 ; Lade Adresswert aus Telegram in W subwf A1, 0 ; Vergleiche mit MSB RAM-Adresse (reduntant) BTFSC STATUS, z INCF Vergleich, 1 BTFSS Vergleich, 1 ; Wenn beide Adressbytes übereinstimmen... goto fertigT ; *************************************** BSF PORTB, 3 ; Ändere Halfduplex-Richtung: ; Mache RS485 Transmitter Slave zum Sender! ;MOVLW h'FF' ; 2xh'FF' kommt weder in Daten noch in Adress- bzw. ; Steuerkode vor! ;MOVWF identisch ; Schreibe erstes Endzeichen in erw. Ausgabestelle. ;MOVWF Fehler ; Schreibe zweite Endzeichen in erw. Ausgabestelle. ;Call ByteZeit ; Gibt Zeit f. Umstellung Empfang/Senden Befehl1? ; >>> Befehl: "Request Counter value" movlw 1 ; Befehl Display einschalten (an allen PA-Terminal) subwf Steuer, 0 ; Vergleiche mit Steuerbyte BTFSS STATUS, z goto Befehl2? MOVF B3, 0 ; Schreibe Zählerstand in Transferregister: MOVWF D1 ; höchstwertiges zuerst! MOVF B2, 0 ; ( Adresse steht bei korrekter Identifizierung MOVWF D2 ; schon drin) MOVF B1, 0 MOVWF D3 MOVF B0, 0 MOVWF D4 Call Datenaus ; Gibt sieben Byte aus: h40-47 goto fertigT ; Transmitter als Slave wieder empfangsbereit! Befehl2? ; >>> Befehl: Set Countervalue: Kopiere Zählerstand in drei ; Sicherungsstellen! movlw 2 ; Befehl Display einschalten (an allen PA-Terminal) subwf Steuer, 0 ; Vergleiche mit Steuerbyte BTFSS STATUS, z goto Befehl3? MOVF D4, 0 ; Schreibe MSB in Stelle ganz "links" MOVWF B0 MOVWF B0? MOVWF B0?? MOVF D3, 0 ; Schreibe Zweithöchstes Byte in Stelle ganz MOVWF B1 ; "halb links" MOVWF B1? MOVWF B1?? MOVF D2, 0 ; Schreibe dritthöchstes Byte in Stelle MOVWF B2 ; "halb rechts"! MOVWF B2? MOVWF B2?? MOVF D1, 0 ; Schreibe letztes Byte in Stelle ganz "rechts" MOVWF B3 MOVWF B3? MOVWF B3?? Call IniStream Call STREAM ; Zeige gesetzten Hubzählerstand! Call Datenaus ; Gibt sieben Byte aus: h40-47 goto fertigT ; Slave zum Sender! Befehl3? ; >>> Befehl: Request SN# movlw 3 subwf Steuer, 0 ; Vergleiche mit Steuerbyte BTFSS STATUS, z goto Befehl4? MOVF Adresse0, 0 ; Kopiere Adresse zusätzlich zu Byte1,2 MOVWF D1 ; (A0,A1) noch in Datenstellen (D1,D2). MOVF Adresse1, 0 MOVWF D2 CLRF D3 CLRF D4 Call Datenaus ; Gibt sieben Byte aus: h40-47 goto fertigT ; Slave wieder empfangsbereit! Befehl4? ; >>> Befehl: "Set Serial Number": Kopiere SN in drei Sicherungsstellen ; falls Strahlungsereignisszähler korrumpiert hat. movlw 4 subwf Steuer, 0 ; Vergleiche mit Steuerbyte BTFSS STATUS, z goto Befehl6? MOVF D1, 0 MOVWF A0 MOVWF A0? MOVWF A0?? MOVF D2, 0 MOVWF A1 MOVWF A1? MOVWF A1? Call Datenaus ; Gibt sieben Byte aus: h40-47 goto fertigT ; Slave wieder empfangsbereit! Befehl6? ; >>> Befehl: Request number of consistency failures movlw 6 subwf Steuer, 0 ; Vergleiche mit Steuerbyte BTFSS STATUS, z goto Befehl8? MOVF F0, 0 ; Übergebe zwei Stellen Fehlerzähler mit LSB zuerst! MOVWF D1 MOVF F1, 0 MOVWF D2 CLRF D3 CLRF D4 Call Datenaus ; Gibt sieben Byte aus: h40-47 goto fertigT ; empfangsbereit! Befehl8? ; >>> Befehl: Stream out EE-Bytes (24x) movlw 8 subwf Steuer, 0 ; Vergleiche mit Steuerbyte BTFSS STATUS, z goto Befehl9? Call HoleEE ; liest EEProm und gibt es an Remote ; aus da Steuer=8 ist ! goto fertigT Befehl9? ; >>> Befehl: Write willingly to EE-Bytes (24x) movlw 9 subwf Steuer, 0 ; Vergleiche mit Steuerbyte BTFSS STATUS, z goto fertigT Call SchreibeEE ; Nur für Test: Ins EE-Schreiben ; (sonst nur automatisch bei Power-Down!) fertigT return ; ********************* Schreibe Nullen ein ->EEPROM (->RAM) ************************* Nullsetzen MOVLW h'40' ; ...sonst Nullen ins EEPROM MOVWF ESpeicherA ; Lösche von hinten ; Interlock vorher schon disabled ! nullen ; Begin ESpeicherA-Schleife MOVF ESpeicherA, 0 ; Ziel in W ADDLW H'FF' ; -1: h40 Werte (d64): von 3F..00 MOVWF EEADR ; Ziele auf EE_Adresse Ziel MOVLW h'00' ; Lade Nullwert ; Test gebe Adresse in Data (obere auskommentieren!) MOVWF EEDATA ; Übergebe Nullwert an Übergabeadresse ; ************ Einschreiberutine ************ BSF STATUS, RP0 ; Wahl Bank1 ; Interlock vorher schon disabled ! BSF EECON1, WREN ; Enable Write Bit MOVLW h'55' MOVWF EECON2 MOVLW h'AA' MOVWF EECON2 BSF EECON1, WR ; BCF EECON1, WREN ; Disable Write Bit ; BCF EECON1, WR ; (soll eigentlich HW machen) Kontrolle BTFSS EECON1, EEIF ; warte auf Flag Schreiberfolg! goto Kontrolle BCF EECON1, EEIF ; Flag f. erfolgreiches EE-Schreiben rücksetzten BCF STATUS, RP0 ; wieder Bank0 wählen ; >>> Verrify: <<<< MOVF EEDATA, 0 ; Hole letzten Schreibwert in W! BSF STATUS, RP0 ; Wahl Bank1 BSF EECON1, RD ; Lese eingeschriebenes Byte BCF STATUS, RP0 ; wieder Bank0 wählen SUBWF EEDATA, 0 ; BTFSS STATUS, z ; Wenn Soll und ist gleich weiter ... INCF Fehler, 1 ; sonst Schreibfehler erhöhen! DECFSZ ESpeicherA, 1 ; zeige auf nächstes Byte goto nullen ; ************ Ende Einschreiberutine *********** BSF STATUS, RP0 ; Wahl Bank1 BCF EECON1, WREN ; Disable Write Bit BCF STATUS, RP0 ; wieder Bank0 wählen ; Interlocks später aktiviert! RETURN ; Fertig mit Nullsetzen! ;********************* Lese EEPROM und kopiere in das RAM *************************** HoleEE ; EEPROM auslesen und in den Arbeitsspeicher ;BSF PORTB, 7 ; Zu Testzwecken mache High wärend EE-lesen ; Ini. S1 MOVLW h'2' ; 2->1->0: Durchlaufzahl + 1 MOVWF Schleife1 ; = Zeilenindex + 1 (sonst 0 nicht mehr ausgeführt!) S1 ; Start Schleife1 ; Ini für S2 MOVLW h'0C' ; ->0B->....->1 (12x) MOVWF Schleife2 ; = Spaltenindex + 1 ; (sonst 0 nicht mehr ausgeführt!) S2 ; *** Bestimme Ursprung (ESpeicherA) und Zieladresse (RAM) *** DECF Schleife1, 0 ; Schleife1 -1 = Zeilenwert MOVWF ESpeicherA ; Lade korr. Zeilenwert in W SWAPF ESpeicherA, 1 ; Übernehme Wert in höheres Nibble: Zeilenindex MOVLW h'1' SUBWF Schleife2, 0 ; Schleifenwert2 - 1 = Spaltenwert => W (Bytestelle) ADDWF ESpeicherA, 1 ; Addiere Bytestelle zur Zeile MOVLW h'10' ; erhöhe Zielbereich RAM ADDWF ESpeicherA, 0 ; um eine Zeile gegeüber EEPROM MOVWF RAM ; RAM = ESpeicherA + h'10' ; *********** Begin Leserutine EEPROM->RAM (Zählerstand, SN, Fehler) MOVF RAM, 0 MOVWF FSR BCF STATUS, RP0 MOVF ESpeicherA, 0 MOVWF EEADR BSF STATUS, RP0 ; wähle Bank 1 BSF EECON1, RD ; Lese EEprom aus (zurück per HW) BCF STATUS, RP0 ; zurück Bank 0 MOVF EEDATA, 0 ; übernehme EE-Datum MOVWF INDF ; schreibe EEprom-Datum in ; RAM-Adresse durch FSR gepointed. ; *********** Ende Leserutine ; Versende an Remote-Master (LANTRONIX) MOVLW h'8' ; XORWF Steuer, 0 ; BTFSS STATUS, z ; wenn Ausgabeorder... goto go_on ; ... sonst weiter! MOVF EEDATA, 0 ; ...lade aktuell geholten EE-Wert Call outch_n ; gib Wert auf Sender! Call baud ; gebe länger Zeit f. Synchronisierung MOVF EEDATA, 0 ; ...lade aktuell geholten EE-Wert nochmal! BTFSC D1, 0 ; Wenn in Datum1 = 1, dann auch >> Display! Call EEtoDisplay ; ggf. EE-Lesekontrolle go_on DECFSZ Schleife2, 1; dekrementiere Spalte goto S2 ; weiter in Schleife 2... DECFSZ Schleife1, 1; dekrementiere Zeile wenn nicht Null! goto S1 ; Weiter in Schleife1... ;BCF PORTB, 7 ; Zu Testzwecken: rücksetzen! RETURN ; Ende HoleEE >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Konsistenz ; ********** Konsistenztest ********************************** MOVF PORTB, 0 ; XORLW b'10000000' ; wenn 0 mach 1 sonst wenn 1 mach 0 MOVWF PORTB ; toggle Testsignal für Konsistenzintervall MOVLW h'3' MOVWF Schleife3 ; Untersuchungssache (Zeile 1->0) MOVLW h'C' MOVWF TS ; Untersuchungsstelle MOVLW h'FC' ; entspricht -4 MOVWF Sprung MOVLW h'0' MOVWF identisch ; ini. Gleich MOVWF Fehler ; ini. Fehler ; je drei Sicherungsstellen für Zählerwert, Seriennummer und Fehler ; h0x: 1xxx.2xxx.3xxx (Zähler) x = Bytestelle ; h1x: 1xxx.2xxx.3xxx (2SN/2F#) S3 MOVLW h'05' ; Ini Schleife 4 MOVWF Schleife4 ; Untersuchungsstelle Byte 1-4 (<- B,A,9,8) DECFSZ Schleife3, 1 ; Zeilenschleife goto S4 goto hinterS3 S4 MOVLW h'06' ADDWF Schleife4, 0 ; Teststelle aus Schleife4: 4,3,2,1 -> B,A,9,8 MOVWF TS MOVLW h'3' ; IniSchleife 5 & 6 MOVWF Schleife5 ; Index Teststelle, innerhalb einer Zeile MOVLW h'3' MOVWF Schleife6 ; Index Vergleichstelle (erst zwei stufen, dann nur eine) DECFSZ Schleife4, 1 ; Byteschleife goto S5 goto hinterS4 S5 DECFSZ Schleife5, 1 ; reduziere solange Schleife1 2>1>0 nicht schon Null goto S6 goto hinterS5 S6 DECFSZ Schleife6, 1 goto EEPROMRAM goto hinterS6 EEPROMRAM MOVF Schleife3, 0 ; MOVWF RAM1 ; Lade Zeile in RAM1 SWAPF RAM1, 1 ; Übernehme Wert in höheres Nibble: Zeilenindex MOVF TS, 0 ; Lade Teststelle in W (Bytestelle) ADDWF RAM1, 0 ; Addiere Bytestelle zur Zeile MOVWF RAM1 MOVWF RAM2 MOVF Sprung, 0 ADDWF RAM2, 0 ; reduziere auf Redundanzstelle vier darunter: RAM2 = RAM1 - 4 MOVWF RAM2 MOVWF FSR MOVF INDF, 0 ; Erfasse Wert an RAM1 MOVWF Vergleich ; Lade Wert in "Vergleich" MOVF RAM1, 0 MOVWF FSR MOVF INDF, 0 ; Erfasse Wert an RAM2 MOVWF Vorgabe ; Lade Wert an Stelle Vorgabe XORWF Vergleich, 0 ; Checke ob "Vergleich" und "Vorgabe" (in W) BTFSS STATUS, z ; identisch sind. goto ungleich gleich INCF identisch, 1 MOVF Vorgabe, 0 MOVWF korrekt ; Setze Korrekt = Vorgabewert goto naechste ungleich BSF Fehlkont, 7 ; Setze Fehlerflag für Stelle! INCF Fehler, 1 ; erhöhe Fehlerzähler MOVF identisch, 1 ; wenn identisch gleich Null, BTFSS STATUS, z ; also drei Vergleichswerte verschieden ... goto naechste MOVF Vorgabe, 0 MOVWF korrekt ; ... nehme letzten Vorgabewert! naechste MOVLW h'FC' ; entspricht -4 ADDWF Sprung, 1 ; Subtrahiere Sprung -4 -> -8 Call Pulsweitenmodulation goto S6 ; Ende Schleife6 hinterS6 MOVLW h'2' MOVWF Schleife6 MOVLW h'FC' ; entspricht -4 MOVWF Sprung ADDWF TS, 1 ; Reduziere Teststelle um vier Positionen goto S5 ; Ende Schleife5 hinterS5 MOVLW h'3' ; Index Vergleichstelle (erst zwei Stufen, MOVWF Schleife6 ; dann nur eine!) BTFSS Fehlkont, 7 ; Fehlerkorrektur wenn es Fehler gab. goto S4 ; Ende Schleife4 ; Drei RAMwerte korrigieren: BCF Fehlkont, 7 ; Setze Fehlerflag zurück MOVLW h'4' MOVWF Fehlkont Skorrekt DECFSZ Fehlkont, 1 goto KorrW goto S4 KorrW MOVF RAM2, 0 MOVWF FSR MOVF korrekt, 0 ; Lade Korrekturwert... MOVWF INDF ; ...in erste Korrekturstelle MOVLW h'4' ADDWF RAM2, 1 goto Skorrekt hinterS4 goto S3 ; Ende Schleife3 hinterS3 RETURN inch_n1 ; Aufsynchronisation erfolgt! call baud ; nach 1/2 Baut übergehe Startbit -> 1 1/2 Baud bcf STATUS, c ; Lösche Übertragsbit rrf SERBUF, 1 ; Rotiere MSB nach rechts! btfsc PORTB, 5 ; Datum eine 0? bsf SERBUF, 7 ; wenn ja übergehe, sonst setze MSB = 1! bsf PORTB, 6 ; Tastpunktausgabe (nur Simulationszwecke) bcf PORTB, 6 decfsz Schleife6, 1 ; Acht Bits abgearbeitet? goto inch_n1 ; nein: hole noch ein Bit call baud ; zeige auf Stopbit (1) call baud ; zeige auf Startbit (0) movf SERBUF, 0 ; Lege Zeichen ins Arbeitsregister return outch_n ; movwf SERBUF ; Schreib in W übergebenes Byte in SERBUF movlw 8 movwf Schleife6 bcf PORTB, 2 ; erzeuge Start-Bit (L) call baud ; Schiebe auf erstes Byte outch_n1 rrf SERBUF, 1 ; rotiere erstes Bit ins Carrybit BTFSS STATUS, c ; Teste Carrybit bcf PORTB, 2 ; wenn 0 gebe auch 0 aus! btfsc STATUS, c ; Teste nochmal Carrybit bsf PORTB, 2 ; wenn 1 gebe auch 1 aus! bsf PORTB, 6 ; nur zu Simulationszwecken bcf PORTB, 6 call baud ; verögere eine Baudperiode decfsz Schleife6, 1 ; wenn alle Bits durch, sende noch Stopbit... goto outch_n1 ; sonst nächstes Zeichen rrf SERBUF, 1 ; MSB aus Carry zurück ins bit7! bsf PORTB, 2 ; Setze Stopbit (1) call baud ; lasse dies eine Baudperiode stehen retlw 0 ; ********************************************************** ; BAUD Routine @4 Mhz ; Baut Rate: Konstante: ; 1200 Baud ; 2400 Baud ; 4800 Baud ; 9600 Baud 104,15 µS ; 19200 Baud ; variables used: Reg 'Schleife2' ; *********************************************************** baud ; Intervall Baudrate Vorlauf 10µS movlw D'30' ; Ein Takt: 1µS movwf Schleife4 ; ein Takt: 1µs baud1 decfsz Schleife4, 1 ; 1 µs (+1 µs mehr bei Null) goto baud1 ; 2 µS retlw 0 ; 2 µS , weiter nach 10+2+3x30+2 µS = 104µS half_Baud ; Intervall halbe Baudrate (3µs Vorlauf) movlw D'11' ; 1µS movwf Schleife4 ; 1µS hbaud1 decfsz Schleife4, 1 ; 1 µs (+1 µs mehr bei Null) goto hbaud1 ; 2 µS nop ; 1 µS retlw 0 ; nach weiteren 3+2+3x14+2+2 µS = 52 µS ByteZeit ; Definiert Zeit eines Byterahmens (10Bit) f. Umschalten Empfangen/Senden movlw D'10' ; 1µS movwf Schleife5 ByteZeitS Call baud decfsz Schleife5, 1 goto ByteZeitS retlw 0 Datenaus movlw h'3F' movwf Telnr movlw h'7' ; Steuerbyte als Erstes: 40,41,...,47,48 EOF, 49 EOF movwf Schleife1 ; 7-7x->0 SSSS1 incf Telnr, 0 movwf Telnr movwf FSR movf INDF, 0 ; Hole Telegrammstellen ins W zur Übergabe! Call outch_n ; sende einen Rahmen 104 µS mit LSB voraus ; (Start-Bit, 8x Daten-Bit, Stop-Bit) DECFSZ Schleife1, 1 ; erfasse sieben Zeichen goto SSSS1 Return ; verlasse "traffic" STREAM ; 8 stellige Anzeige seriell streamen (Clearschleife ???) ; Reihenfolge der Abarbeitung der vier Zählstellen bestimmt ; Ausgabe auf die acht Stellen: LSB zuerst -> Traillingzero ; Führende Nullen nicht anzeigen... MOVlW B'11111111' ; Stellen mit 1 werden später angezeigt, 0 nicht! MOVWF Vorgabe ; temporär Speicher für vorangende Nullen MOVLW d'8' ; ini. Bitzaehler beim Streamen MOVWF Bitindex BCF STATUS, c ; Leere Carrybit MOVF B3, 0 ; MS-Nibble noch Null? ADDLW H'F0' ; h'F0'+ B3 > h'FF'? => Carry = 1 BTFSC STATUS, c ; ja: carry = (Nibble genutzt)=shiftend / nein= weiter GOTO shiftend ; Nibble belegt = nicht Null: ab hier anzeigen! RLF Vorgabe, 1 ; DECF Bitindex, 1 MOVF B3, 1 BTFSS STATUS, z ; LS-Nibble auch noch Null GOTO shiftend ; Nibble belegt = nicht Null: ab hier anzeigen! BCF STATUS, c ; Leere Carrybit RLF Vorgabe, 1 ; Schiebe c-Ergebniss (Stelle genutzt) in LSBit DECF Bitindex, 1 MOVF B2, 0 ; MS-Nibble noch Null? ADDLW H'F0' ; h'F0'+ B3 > h'FF'? => Carry = 1 BTFSC STATUS, c ; ja= (Nibble genutzt)=shiftend / nein= weiter GOTO shiftend ; Nibble belegt = nicht Null: ab hier anzeigen! RLF Vorgabe, 1 ; Schiebe c-Ergebniss (Stelle genutzt) in LSBit DECF Bitindex, 1 MOVF B2, 1 BTFSS STATUS, z ; LS-Nibble auch noch Null GOTO shiftend ; Nibble belegt = nicht Null: ab hier anzeigen! BCF STATUS, c ; Leere Carrybit RLF Vorgabe, 1 ; Schiebe c-Ergebniss (Stelle genutzt) in LSBit DECF Bitindex, 1 MOVF B1, 0 ; MS-Nibble noch Null? ADDLW H'F0' ; h'F0'+ B3 > h'FF'? => Carry = 1 BTFSC STATUS, c ; ja= (Nibble genutzt)=shiftend / nein= weiter GOTO shiftend ; Nibble belegt = nicht Null: ab hier anzeigen! RLF Vorgabe, 1 ; Schiebe c-Ergebniss (Stelle genutzt) in LSBit DECF Bitindex, 1 MOVF B1, 1 BTFSS STATUS, z ; LS-Nibble auch noch Null GOTO shiftend ; Nibble belegt = nicht Null: ab hier anzeigen! BCF STATUS, c ; Leere Carrybit RLF Vorgabe, 1 ; Schiebe c-Ergebniss (Stelle genutzt) in LSBit DECF Bitindex, 1 MOVF B0, 0 ; MS-Nibble noch Null? ADDLW H'F0' ; h'F0'+ B3 > h'FF'? => Carry = 1 BTFSC STATUS, c ; ja= (Nibble genutzt)=shiftend / nein= weiter GOTO shiftend ; Nibble belegt = nicht Null: ab hier anzeigen! RLF Vorgabe, 1 ; Schiebe c-Ergebniss (Stelle genutzt) in LSBit DECF Bitindex, 1 MOVF B0, 1 ; letzte Stelle bleibt angezeigt! RLF Vorgabe, 1 ; Schiebe c-Ergebniss (Stelle genutzt) in LSBit DECF Bitindex, 1 goto komplett shiftend RLF Vorgabe, 1 ; rotiere in Ausgangsposition (vorher höchstwertige = akut DECFSZ Bitindex, 1 ; reduziere Bitnummer goto shiftend komplett ;RLF Vorgabe,1 ; letztes Rotieren stellt "Vorgabe" wieder richtig StartStream NB_un ; ***** Streame Anzeigewert für unteres Nibble (8Bit) *** MOVLW B'00001111' ; Maske oberes Nibble, greife unteres ANDWF INDF, 0 ; Maskiere 2. Nibble MOVWF Anzeige ; Halte Unteres Nibble MOVWF Testwert ; aktueller Testwert CALL Kodierung ; Kodierung auf Byte zur Anzeige MOVLW d'8' ; ini. Bitzaehler beim Streamen MOVWF Bitindex Los_un RLF Anzeigewert, 1 ; rotiere links BTFSC STATUS, c GOTO Ge2 Ng2 BCF PORTA, serLED ; setze SerialBit 0 GOTO w2 Ge2 BSF PORTA, serLED ; setze SerialBit 1 w2 BSF PORTA, ClockLED ; setze Clock BCF PORTA, ClockLED ; nulle Clock DECFSZ Bitindex, 1 ; reduziere Bitnummer goto Los_un NB_ob ; ***** Streame Anzeigewert für obere Nibble (8Bit) **** MOVLW H'F0' ; Maskiere unteres Nibble, greife oberes ANDWF INDF, 0 ; Nehme oberes Nibble MOVWF Anzeige ; Halte Obereres Nibble MOVWF Testwert ; aktueller Testwert SWAPF Testwert, 1 ; reduziere Wert höheres Nibble auf einfaches Nibble CALL Kodierung ; Kodierung auf Byte zur Anzeige MOVLW d'8' ; ini. Bitzaehler beim Streamen MOVWF Bitindex Los_ob RLF Anzeigewert, 1 ; rotiere links BTFSC STATUS, c GOTO Ge1 Ng1 BCF PORTA, serLED ; lösche SerialBit 0 GOTO w1 Ge1 BSF PORTA, serLED ; setze SerialBit 1 w1 BSF PORTA, ClockLED ; setze Clock BCF PORTA, ClockLED ; nulle Clock DECFSZ Bitindex, 1 ; reduziere Bitnummer goto Los_ob ; nächstes Byte (2 Stellen) DECF FSR, 1 ; erhöhe Pointer auf Stelle INCF ByteNr, 1 MOVLW D'4' SUBWF ByteNr, 0 BTFSS STATUS, z ; goto StartStream BSF PORTA, Strobe ; Überneme nach vier Byte (8 Stellen) BCF PORTA, Strobe ; nulle Strobe MOVLW 0 MOVWF ByteNr Return EinByte INCF INDF, 1 ; Inc. Zähler MOVLW B'00001111' ; Maske oberes Nibble ANDWF INDF, 0 ; Maskiere 2. Nibble ADDLW D'246' ; Führe Überlauf herbei wenn Bx =9 BTFSS STATUS, c ; Überlauf erreicht? RETURN ; wenn kein Überlauf erhöhe um 1... MOVLW B'11110000' ; Maske unteres Nibble ANDWF INDF, 1 ; setze unteres Nibble 0 (nulle halb) MOVLW B'00010000' ADDWF INDF, 1 ; Übertrag zu 2.tem Nibble, 2.Stelle um 1 erhöht... NIBBLE2 ; nach 99 (1001.1001) kommt 160 (1010.0000) MOVF INDF, 0 ; Hole aktualisierten Zählerstand ins W ADDLW d'96' ; Führe Überlauf herbei wenn 100 (100 -> 160 A0) BTFSS STATUS, c ; 99 voll? RETURN ; wenn NOR voll zurück... MOVLW 0 MOVWF INDF ; Lösche ganz: Ein Byte, zwei Stellen DECF FSR,1 ; erhöhe Pointer auf Hunderterstelle INCF ByteNr, 1 ; Erhöhe Bytezähler (Werttigkeit) Call EinByte INCF FSR, 1 ; zurück Stelle tiefer... DECF ByteNr, 1 ; Reduziere Bytezähler (Werttigkeit) RETURN goto Zyklus Kodierung ; (->Anzeigewert) Kodierung zur Siebensegmentanzeige Eins ; 0->15 Anzeige-> Testwert -> Anzeigewert DECFSZ Testwert, 1 ; Reduziere Anzeige und übergehe wenn Null goto Zwei MOVLW d'6' ; Eins-Anzeige h'06' goto Uebernahme Zwei ; 2->1 DECFSZ Testwert, 1 ; Reduziere Anzeige und übergehe wenn Null goto Drei MOVLW d'91' ; Zwei-Anzeige h'5B' goto Uebernahme Drei ; 3->2 DECFSZ Testwert, 1 ; Reduziere Anzeige und übergehe wenn Null goto Vier MOVLW d'79' ; Drei-Anzeige h'4F' goto Uebernahme Vier ; 4->3 DECFSZ Testwert, 1 ; Reduziere Anzeige und übergehe wenn Null goto Fuenf MOVLW d'102' ; Vier-Anzeige h'66' goto Uebernahme Fuenf ; 5->4 DECFSZ Testwert, 1 ; Reduziere Anzeige und übergehe wenn Null goto Sechs MOVLW d'109' ; Fuenf-Anzeige h'6D' goto Uebernahme Sechs ; 6->5 DECFSZ Testwert, 1 ; Reduziere Anzeige und übergehe wenn Null goto Sieben MOVLW d'125' ; Sechs-Anzeige h'7D' goto Uebernahme Sieben ; 7->6 DECFSZ Testwert, 1 ; Reduziere Anzeige und übergehe wenn Null goto Acht MOVLW d'7' ; Sieben-Anzeige h'07' goto Uebernahme Acht ; 8->7 DECFSZ Testwert, 1 ; Reduziere Anzeige und übergehe wenn Null goto Neun MOVLW d'127' ; Acht-Anzeige h'7F' goto Uebernahme Neun ; 9->8 DECFSZ Testwert, 1 ; Reduziere Anzeige und übergehe wenn Null goto Dasa MOVLW d'111' ; Neun-Anzeige h'6F' goto Uebernahme Dasa ; 10(A)->9 DECFSZ Testwert, 1 ; Reduziere Anzeige und übergehe wenn Null goto Dast MOVLW d'220' ; "a"-Anzeige h'DC' goto Uebernahme Dast ; 11(B)->10 DECFSZ Testwert, 1 ; Reduziere Anzeige und übergehe wenn Null goto Dasr MOVLW d'120' ; "t"-Anzeige h'78' goto Uebernahme Dasr ; 12(C)->11 DECFSZ Testwert, 1 ; Reduziere Anzeige und übergehe wenn Null goto Leer MOVLW d'80' ; "r"-Anzeige h'50' goto Uebernahme Leer ; 13(D)->12 DECFSZ Testwert, 1 ; Reduziere Anzeige und übergehe wenn Null goto Ausruf MOVLW d'0' ; " "-Anzeige h'00' goto Uebernahme Ausruf ;14(E)->13 DECFSZ Testwert, 1 ; Reduziere Anzeige und übergehe wenn Null goto Dasn MOVLW d'134' ; "!"-Anzeige h'86' goto Uebernahme Dasn ;15(F)->14 DECFSZ Testwert, 1 ; Reduziere Anzeige und übergehe wenn Null goto Null MOVLW d'84' ; Null-Anzeige h'54' goto Uebernahme Null ; (0)->15 MOVLW d'0' BTFSC Vorgabe, 0 ; "0" nicht anzeigen wenn führende Null (LS-Bit = akut) MOVLW d'63' ; Null-Anzeige h'3F' goto Uebernahme Uebernahme RRF Vorgabe , 1 ; Schieben auf nächste Stelle MOVWF Anzeigewert ; Wert für Anzeigeelement Return ; aus |-> an Pulsweitenmodulation ; PWMm >>>>>>>>>>>> PWMa >>>> PWMs >>>> 0 DECFSZ PWMa, 1 ; Dekrementiere aktuellen PMW-Laeufer goto w3 MOVLW PWMm ; PWM-Maximalwert MOVWF PWMa ; Setzte zurück auf Zyklusvollwert. w3 MOVF PWMs, 0 ; komplementiere Schwellwert in W SUBWF PWMa, 0 ; addiere neg. Schwellwert vom aktuellen Wert BTFSS STATUS, c ; wenn noch über Schwellwert (C=1) ... BSF PORTA, OutEnabl ; ... setze Anzeige an! BTFSC STATUS, c ; wenn überm Schwellwert... BCF PORTA, OutEnabl ; ... setzte Anzeige aus! Return Zaehlnull ; nur für lange Delayrutine MOVLW D'0' ; ini. Stellenzähler MOVWF B0 MOVWF B1 MOVWF B2 MOVWF B3 Return IniByte MOVLW H'13' ; erstes Byte MOVWF FSR ; Lade Pointer auf erstes Byte MOVLW D'0' ; ini. Stellenzähler MOVWF ByteNr ; Lade Schleifenzähler mit 0 Return IniStream MOVLW H'13' ; Initialisiere Streamen MOVWF FSR ; Zeige auf höchste Stelle MOVLW D'0' MOVWF ByteNr ; Lade Schleifenzähler mit 0 Return Delay Call IniByte ; Initialisierung für Byte-Rutinennutzung Call Zaehlnull ; Zähler mit Null laden Schleife CALL EinByte ; zähle für Delay dekadisch aufwärts (Ca. 5µS/call) Call Pulsweitenmodulation MOVLW H'10' ; Bei 1 Mio ist Schluss SUBWF B2, 0 ; Subtrahiere 1 Mio. BTFSS STATUS, z ; Checke ob am Ende goto Schleife Return EEtoDisplay ; W-> Diese Prozedur gibt die vom EEProm eingelesenen ; Stellen zu Kontrollzwecken auf dem Display in der ; Form: Ausleseadresse Auslesewert ; z.B. Hex: "S_1B I_1B" ; W wird übergeben! MOVWF B0 ; Ausgabe in Stelle B0 (HEX) MOVLW h'1D' ; "I_" in B1 MOVWF B1 MOVF EEADR, 0 ; Anzeige akt. Adresse MOVWF B2 w6 MOVLW h'5D' ; "S_" MOVWF B3 ; Call IniStream Call STREAM ; Zeige Hubzählerstand MOVLW PWMF ; mach an MOVWF PWMs Call Delay ; ca. 1,5s Verzögerung. MOVLW 1 ; mach aus MOVWF PWMs ; Return SCHLUSS ; Durch Einschalten aller LED-Elemente soll nach der Datensicherung ; die kondensatorspannung möglichst schnell herunter gefahren ; werden, um Korruption des EE-Speichers zu vermeiden !!! MOVLW h'88' ; "88" MOVWF B0 MOVLW h'88' ; "88" MOVWF B1 MOVLW h'88' ; "88" MOVWF B2 MOVLW h'88' ; Fehler beim EESchreiben zeigen! MOVWF B3 Call IniStream Call STREAM ; Zeige "88888888" BSF PORTA, OutEnabl goto $ ; Programm bleibt hier stehen !!! end