list p=16f84,r=dec include "p16f84.inc" include "mymacros.inc" __idlocs 1099h __config _XT_OSC & _WDT_OFF & _PWRTE_ON ;#define SIMULATE #define DEBUG BANKSEL macro arg #if (arg) bsf STATUS,5 #else bcf STATUS,5 #endif endm ;**************** ;** Konstanten ** ;**************** PHASE180 equ 10000/64 ;=156 (abgerundet) - bezieht sich auf 50 Hz TIMEOVER equ 11000/64 ;=171 (Netzausfall) - bezieht sich auf 50 Hz PHASEADD equ PHASE180/39 ;Günstige Teiler sind 2,3,4,6,12,13,39,... WAITRELAY equ 100/10 ;100 ms ;Primfaktoren von 156 sind 2*2*3*13 ;Belegung PortA TRIAC equ 0 ;Bit0 Triac-Steuerausgang, 0=EIN RELAY equ 2 ;Bit2 Relais-Steuerausgang, 0=EIN TESTA equ 3 ;Bit3 Testausgang REMA ;Belegung PortB SWON equ 4 ;Bit4 Schalter-Eingang, 0=EIN SWLEARN equ 5 ;Bit5 Lern-Taster, 0=EIN ZERO_I equ 6 ;Bit6 Nulldurchgangs-Detektor für Strom ZERO_U equ 7 ;Bit7 Nulldurchgangs-Detektor für Spannung ;Im Unterschied zu den Vorgängerversionen arbeitet dieses Programm ;mit der Methode, die Datenverarbeitung (Tastenabfrage u.ä.) ;je nach Zündzeitpunkt (kleiner oder größer 5ms = Viertelperiode) ;vor oder nach dem Zündvorgang durchzuführen ;Hier keine Interruptsteuerung, um Portierung zu kleineren PICs ;(z.B. 8-pin PIC12CE673) zu ermöglichen ;************************ ;** RAM-Speicherzellen ** ;************************ PHASE equ 10h ;speichert momentanen Zündwinkel LASTIN equ 11h ;letzter IN-Befehl (PortB) REMA equ 12h ;speichert Remanenz-Zustand: ; 1 "entlaust", keine Remanenz (Start mit 90°) ; 2 Remanenz positiv (Start mit 130° bzw. je nach DIL-Schalter) ; 3 Remanenz negativ (wie 2, jedoch andere Halbwelle abwarten) ; sonst Remanenz unbekannt (Softstart) ;REMA wird im EEPROM-Speicher (Speicherzelle 0) mitgeführt X equ 13h ;Hilfszelle für CheckPortChange X1 equ 14h ;weiterer Hilfsspeicher STARTP equ 15h ;speichert (angelernten) Ideal-Startwinkel ;STARTP wird im EEPROM-Speicher (Speicherzelle 1) mitgeführt PHI equ 16h ;letzte gemessene Strom-Phase PHASE0 equ 17h ;Kopie von PHASE für späte Zündung (>5ms) ;********************* ;** Programm im ROM ** ;********************* org 0 goto start dw 'm','m','e' org 4 retfie ;keine Interrupt-Routine ;==================== ;== Unterprogramme == ;==================== CheckTime ;Überprüft anhand des Timers, ob 11ms abgelaufen sind; wenn ja, wird das ;Label TIMEOUT angesprungen. Da der PIC-Stack zirkular ist, läuft nichts über. movlw TIMEOVER subwf TMR0,W ;Ist der Zählerstand zu klein?->keine Null! SKPC ; (W:=[Tmr0]-TIMEOVER) return ;okay goto TIMEOUT wait0 ;eine "späte Zündung" anhand von PHASE0 ausführen movlw 1<180°? (W:=(PHASE180-1)-W) SKPC return ;ja, Triac bleibt aus movfw PHASE sublw PHASE180/2 ;Phasenwinkel >90°? SKPC goto setlatestart ;ja, späte Zündung (jetzt nicht warten) wait: movfw PHASE subwf TMR0,W JNC wait bcf PORTA,TRIAC ;Triac einschalten return setlatestart: movfw PHASE movwf PHASE0 return NextEERead: ;nächste EEPROM-Zelle lesen incf EEADR,f EERead: ;EEPROM lesen (lästige Bankumschaltung) BANKSEL 80h bsf EECON1,RD ;Lesen auslösen eerw: btfsc EECON1,RD goto eerw BANKSEL 0 return ClearREMA: clrf REMA WriteEEPROM: ; Diese Routine vergleicht den EEPROM- mit dem RAM-Inhalt. ; Sind diese verschieden, wird die Speicherzelle gebrannt. ; Bei gesetztem Brenn-Bit (Bit 1, "WR") wird nichts getan BANKSEL 80h movlw 1< Raus! clrf EEADR ;Adresse Null: Remanenz-Code call EERead movfw REMA xorwf EEDATA,f ;Gleich? (W bleibt) JNZ burn ;ungleich - brennen! call NextEERead ;Adresse Eins: Idealstartphase movfw STARTP xorwf EEDATA,f ;Gleich? (W bleibt) JNZ burn ;ungleich - brennen! incf EEADR,f ;auf 2? return ;gleich - nichts tun burn: movwf EEDATA ;Ungleich? - Neues Datum eintragen BANKSEL 80h bsf EECON1,WREN ;Bit 2: Schreibfreigabe movlw 55h movwf EECON2 movlw 0AAh movwf EECON2 ;Kennung zun "Brennen" bsf EECON1,WR ;Brennung auslösen BANKSEL 0 return RelayOff ;Relais ausschalten und warten, VR: X1 bsf PORTA,RELAY movlw WAITRELAY movwf X1 wrelay: call EineZuendung ;einige Male (Nulldurchgänge) warten decfsz X1,f goto wrelay return ;=================== ;== Hauptprogramm == ;=================== start: ;* Aktion 1: ; Triac-Steuerpin auf Ausgabe programmieren, alles andere bleibt Eingabe clrf STATUS movlw (1<0 goto on_try2 ;springe wenn Kern nicht entmagnetisiert call ClearREMA movlw PHASE180/2 ;90° - dürfte gar nicht auftreten! on_start_with_W: movwf PHASE call EineZuendung on_0: ;alle weiteren mit 0° clrf PHASE ;voll einschalten bcf PORTA,RELAY ;und Relais zuschalten goto main_loop on_try2: movlw 1<