LIST P=12ce519 #INCLUDE ; Programm fuer neue Platine mit neuer Impuls- und Prellbehandlung ; Programmkennung EEPROM prgken set 0x96 ; Register cblock 0x08 rpulsl ; Pulszaehler in 4 microsec rpulsh rstelll ; derzeitige Stellung im Umlauf rstellh rsolll ; Soll-Impulslaenge nach Umlauf ( = Plus oder Minus) rsollh rplusl ; Impulslaenge Plusstellung (aus EEPROM) rplush rminusl ; Impulslaenge Minusstellung (aus EEPROM) rminush rstep ; Schrittgroesse fuer rstell rdely ; Verzoegerung bei Schleichgang tdely ; rzust ; Programmzustand 1 = Programmierung Endlage plus ; 2 = Programmierung Endlage minus ; 4 = Programmierung Speed ; 8 = Plustaste ; 16 = Minustaste endc ; Programmzustaende bpplus set 0x00 bpminus set 0x01 bpspeed set 0x02 btplus set 0x03 btminus set 0x04 ; Bits in PORTA ctris set 0x38 ; 0-2 Output, 3-5 Input ; 5,4,3 fuer neue Platine iplus set 0x05 ; Plus-Stellung (Eingang) iminus set 0x04 ; Minus-Stellung (Eingang) iprog set 0x03 ; Programmierung opuls set 0x00 ; Steuerimpuls (Ausgang) opplus set 0x01 ; Polarisation plus (Ausgang) opminus set 0x02 ; Polarisation minus (Ausgang) ORG 0x000 ; coding begins here movwf OSCCAL ; update register with factory cal value goto start ;*************************************************************************** ;*************************** Variable Listing **************************** ;*************************************************************************** OK EQU 01H NO EQU 00H I2C_PORT EQU GPIO ; Port B control register, used for I2C SCL EQU 07H ; EEPROM Clock, SCL (I/O bit 7) SDA EQU 06H ; EEPROM Data, SDA (I/O bit 6) EE_OK EQU 07H ; Bit 7 in PC_OFFSET used as OK flag for EE cblock 0x1A PC_OFFSET ; PC offset register (low order 4 bits), ; value based on operating mode of EEPROM. ; Also, bit 7 used for EE_OK flag EEADDR ; EEPROM Address EEDATA ; EEPROM Data EEBYTE ; Byte sent to or received from ; EEPROM (control, address, or data) COUNTER ; Bit counter for serial transfer endc ;*************************************************************************** ;*************************** EEPROM Subroutines ************************** ;*************************************************************************** ; Communication for EEPROM based on I2C protocall, with Acknowledge. ; ; WRITE_BYTE: Byte write routine ; Inputs: EEPROM Address EEADDR ; EEPROM Data EEDATA ; Outputs: Return 01 in W if OK, else return 00 in W ; ; READ_CURRENT: Read EEPROM at address currently held by EE device. ; Inputs: NONE ; Outputs: EEPROM Data EEDATA ; Return 01 in W if OK, else return 00 in W ; ; READ_RANDOM: Read EEPROM byte at supplied address ; Inputs: EEPROM Address EEADDR ; Outputs: EEPROM Data EEDATA ; Return 01 in W if OK, else return 00 in W ; ; Note: EEPROM subroutines will set bit 7 in PC_OFFSET register if the ; EEPROM acknowledged OK, else that bit will be cleared. This bit ; can be checked instead of refering to the value returned in W ;*************************************************************************** ;********************** Set up EEPROM control bytes ************************ ;*************************************************************************** READ_CURRENT MOVLW B'10000100' ; PC offset for read current addr. EE_OK bit7='1' MOVWF PC_OFFSET ; Load PC offset GOTO INIT_READ_CONTROL WRITE_BYTE MOVLW B'10000000' ; PC offset for write byte. EE_OK: bit7 = '1' GOTO INIT_WRITE_CONTROL READ_RANDOM MOVLW B'10000011' ; PC offset for read random. EE_OK: bit7 = '1' INIT_WRITE_CONTROL MOVWF PC_OFFSET ; Load PC offset register, value preset in W MOVLW B'10100000' ; Control byte with write bit, bit 0 = '0' START_BIT BCF I2C_PORT,SDA ; Start bit, SDA and SCL preset to '1' ;******* Set up output data (control, address, or data) and counter ******** ;*************************************************************************** PREP_TRANSFER_BYTE MOVWF EEBYTE ; Byte to transfer to EEPROM already in W MOVLW .8 ; Counter to transfer 8 bits MOVWF COUNTER ;************ Clock out data (control, address, or data) byte ************ ;*************************************************************************** OUTPUT_BYTE BCF I2C_PORT,SCL ; Set clock low during data set-up RLF EEBYTE, F ; Rotate left, high order bit into carry bit BCF I2C_PORT,SDA ; Set data low, if rotated carry bit is SKPNC ; a '1', then: BSF I2C_PORT,SDA ; reset data pin to a one, otherwise leave low NOP BSF I2C_PORT,SCL ; clock data into EEPROM DECFSZ COUNTER, F ; Repeat until entire byte is sent GOTO OUTPUT_BYTE NOP ;************************** Acknowledge Check ***************************** ;*************************************************************************** BCF I2C_PORT,SCL ; Set SCL low, 0.5us < ack valid < 3us NOP BSF I2C_PORT,SDA GOTO $+1 ; May be necessary for SCL Tlow at low voltage, BSF I2C_PORT,SCL ; Raise SCL, EEPROM acknowledge still valid BTFSC I2C_PORT,SDA ; Check SDA for acknowledge (low) BCF PC_OFFSET,EE_OK ; If SDA not low (no ack), set error flag BCF I2C_PORT,SCL ; Lower SCL, EEPROM release bus BTFSS PC_OFFSET,EE_OK ; If no error continue, else stop bit GOTO STOP_BIT ;***** Set up program counter offset, based on EEPROM operating mode ***** ;*************************************************************************** MOVF PC_OFFSET,W ANDLW B'00001111' ADDWF PCL, F GOTO INIT_ADDRESS ;PC offset=0, write control done, send address GOTO INIT_WRITE_DATA ;PC offset=1, write address done, send data GOTO STOP_BIT ;PC offset=2, write done, send stop bit GOTO INIT_ADDRESS ;PC offset=3, write control done, send address GOTO INIT_READ_CONTROL ;PC offset=4, send read control GOTO READ_BIT_COUNTER ;PC offset=5, set counter and read byte GOTO STOP_BIT ;PC offset=6, random read done, send stop ;********** Initalize EEPROM data (address, data, or control) bytes ****** ;*************************************************************************** INIT_ADDRESS INCF PC_OFFSET, F ; Increment PC offset to 2 (write) or to 4 (read) MOVF EEADDR,W ; Put EEPROM address in W, ready to send to EEPROM GOTO PREP_TRANSFER_BYTE INIT_WRITE_DATA INCF PC_OFFSET, F ; Increment PC offset to go to STOP_BIT next MOVF EEDATA,W ; Put EEPROM data in W, ready to send to EEPROM GOTO PREP_TRANSFER_BYTE INIT_READ_CONTROL BSF I2C_PORT,SCL ; Raise SCL nop BSF I2C_PORT,SDA ; raise SDA INCF PC_OFFSET, F ; Increment PC offset to go to READ_BIT_COUNTER next MOVLW B'10100001' ; Set up read control byte, ready to send to EEPROM GOTO START_BIT ; bit 0 = '1' for read operation ;************************** Read EEPROM data ***************************** ;*************************************************************************** READ_BIT_COUNTER BSF I2C_PORT,SDA NOP BSF I2C_PORT,SCL ; set data bit to 1 so we're not pulling bus down. MOVLW .8 ; Set counter so 8 bits will be read into EEDATA MOVWF COUNTER READ_BYTE BSF I2C_PORT,SCL ; Raise SCL, SDA valid. SDA still input from ack SETC ; Assume bit to be read = 1 BTFSS I2C_PORT,SDA ; Check if SDA = 1 CLRC ; if SDA not = 1 then clear carry bit RLF EEDATA, F ; rotate carry bit (=SDA) into EEDATA; BCF I2C_PORT,SCL ; Lower SCL BSF I2C_PORT,SDA ; reset SDA DECFSZ COUNTER, F ; Decrement counter GOTO READ_BYTE ; Read next bit if not finished reading byte BSF I2C_PORT,SCL NOP BCF I2C_PORT,SCL ;****************** Generate a STOP bit and RETURN *********************** ;*************************************************************************** STOP_BIT BCF I2C_PORT,SDA ; SDA=0, on TRIS, to prepare for transition to '1' BSF I2C_PORT,SCL ; SCL = 1 to prepare for STOP bit GOTO $+1 ; 4 NOPs neccessary for I2C spec Tsu:sto = 4.7us GOTO $+1 BSF I2C_PORT,SDA ; Stop bit, SDA transition to '1' while SCL high BTFSS PC_OFFSET,EE_OK ; Check for error RETLW NO ; if error, send back NO RETLW OK ; if no error, send back OK ;Note: SDA and SCL still being driven by master, both set to outputs. ;**************************************************************************** ;************************ End EEPROM Subroutines ************************** ; wconfig: schreiben der Konfiguration wconfig movlw 0x01 movwf EEADDR movf rplusl, W movwf EEDATA call WRITE_BYTE btfss PC_OFFSET, 7 goto wconfig wconf02 movlw 0x02 movwf EEADDR movf rplush, W movwf EEDATA call WRITE_BYTE btfss PC_OFFSET, 7 goto wconf02 wconf03 movlw 0x03 movwf EEADDR movf rminusl, W movwf EEDATA call WRITE_BYTE btfss PC_OFFSET, 7 goto wconf03 wconf04 movlw 0x04 movwf EEADDR movf rminush, W movwf EEDATA call WRITE_BYTE btfss PC_OFFSET, 7 goto wconf04 wconf05 movlw 0x05 movwf EEADDR movf rstep, W movwf EEDATA call WRITE_BYTE btfss PC_OFFSET, 7 goto wconf05 wconf06 movlw 0x06 movwf EEADDR movf rdely, W movwf EEDATA call WRITE_BYTE btfss PC_OFFSET, 7 goto wconf06 wconf07 movlw 0x07 movwf EEADDR movf rzust, W movwf EEDATA call WRITE_BYTE btfss PC_OFFSET, 7 goto wconf07 retlw 0 ; Initialisierung start clrf GPIO movlw ctris tris GPIO clrf rzust movlw 0xc6 ; Prescaler fuer Timer0 auf 128 option ; Standardkonfiguration setzen config ; Einstellung 1 und 2 msec movlw .21 ; 1,6 msec Plusstellung movwf rplusl movlw .2 movwf rplush movlw .211 ; 1,4 msec Minusstellung movwf rminusl movlw .1 movwf rminush movlw .1 movwf rstep movlw .1 movwf rdely movlw .0 movwf rzust btfsc GPIO, iprog call wconfig config1 movlw 0x00 ; Versionskennung pruefen movwf EEADDR call READ_RANDOM btfss PC_OFFSET, 7 goto config1 movlw prgken xorwf EEDATA, W btfss STATUS, Z call wconfig ; Erstprogrammierung wegschreiben xconfig movlw 0x00 ; Programmkennung setzen movwf EEADDR movlw prgken movwf EEDATA call WRITE_BYTE btfss PC_OFFSET, 7 goto xconfig ; EEPROM auslesen lies01 movlw 0x01 ; Plusstellung low movwf EEADDR call READ_RANDOM btfss PC_OFFSET, 7 goto lies01 movf EEDATA, W movwf rplusl lies02 movlw 0x02 ; Plusstellung high movwf EEADDR call READ_RANDOM btfss PC_OFFSET, 7 goto lies02 movf EEDATA, W movwf rplush lies03 movlw 0x03 ; Minusstellung low movwf EEADDR call READ_RANDOM btfss PC_OFFSET, 7 goto lies03 movf EEDATA, W movwf rminusl lies04 movlw 0x04 ; Minusstellung high movwf EEADDR call READ_RANDOM btfss PC_OFFSET, 7 goto lies04 movf EEDATA, W movwf rminush lies05 movlw 0x05 ; Step movwf EEADDR call READ_RANDOM btfss PC_OFFSET, 7 goto lies05 movf EEDATA, W movwf rstep lies06 movlw 0x06 ; Delay movwf EEADDR call READ_RANDOM btfss PC_OFFSET, 7 goto lies06 movf EEDATA, W movwf rdely lies07 movlw 0x07 ; Letzter Status movwf EEADDR call READ_RANDOM btfss PC_OFFSET, 7 goto lies07 movf EEDATA, W movwf rzust movf rdely, W movwf tdely ; Auf Pluswerte setzen movf rplusl, W movwf rsolll movwf rstelll movf rplush, W movwf rsollh movwf rstellh btfss rzust, btminus ; letzter Zustand war Minus goto relais ; Auf Minuswerte setzen movf rminusl, W movwf rsolll movwf rstelll movf rminush, W movwf rsollh movwf rstellh ; Impulserzeugung: erst Relais pruefen, dann Impuls erzeugen, dann Pause erzeugen relais movf rstellh, W subwf rplush, W btfss STATUS, Z goto rel001 movf rstelll, W subwf rplusl, W btfss STATUS, Z goto rel001 ; auf Plus pruefen ;Minusstellung bcf GPIO, opminus bsf GPIO, opplus goto impuls rel001 movf rstellh, W subwf rminush, W btfss STATUS, Z goto rel002 ; Umlauf movf rstelll, W subwf rminusl, W btfss STATUS, Z goto rel002 ; Umlauf ; Plusstellung bcf GPIO, opplus bsf GPIO, opminus goto impuls ; Umlauf rel002 bsf GPIO, opplus bsf GPIO, opminus impuls movf rstelll, W movwf rpulsl comf rpulsl, F movf rstellh, W movwf rpulsh comf rpulsh, F bsf GPIO, opuls imp001 incfsz rpulsl, F goto imp001 incfsz rpulsh, F goto imp001 ;Impuls beendet bcf GPIO, opuls ; Pause starten movlw 0x4c ; -180 movwf TMR0 movlw 0xc6 ; Prescaler fuer Timer0 auf 128 option imp002 movf TMR0,W btfss STATUS, Z ; 1 = am Ende goto imp002 ; Pause nicht am Ende ; Pause beendet, Tasten abfragen goto kontakt ; Ende eines Programmierschrittes, rsoll und rstell neu setzen endprog btfsc rzust, bpplus goto endp01 ; im Programmiermodus Plusstellung movf rminusl, W movwf rstelll movwf rsolll movf rminush, W movwf rstellh movwf rsollh goto endkont endp01 movf rplusl, W movwf rstelll movwf rsolll movf rplush, W movwf rstellh movwf rsollh ; Kontakte bearbeitet, naechsten Impuls berechnen endkont decfsz tdely, F goto relais ; noch warten movf rdely, W movwf tdely ; tdely wieder setzen ; rstell nach rsoll weiterschalten movf rstellh, W subwf rsollh, W btfss STATUS, Z goto endk01 ; Vorzeichen auswerten movf rstelll, W subwf rsolll, W endk01 btfsc STATUS, C ; rstell > rsoll -> Subtrahieren goto endk20 ; Subtrahieren endk10 movf rstep, W subwf rstelll, F btfss STATUS, C decf rstellh, F movf rstellh, W subwf rsollh, W btfss STATUS, Z goto endk12 ; Vorzeichen auswerten movf rstelll, W subwf rsolll, W endk12 btfss STATUS, C ; rstell > rsoll -> noch im Umlauf goto relais ; Ende des Umlaufs noch nicht erreicht movf rsollh, W movwf rstellh movf rsolll, W movwf rstelll ; rstell := rsoll goto relais ; Addieren endk20 movf rstep, W addwf rstelll, F btfsc STATUS, C incf rstellh, F movf rstellh, W subwf rsollh, W btfss STATUS, Z goto endk22 ; Vorzeichen auswerten movf rstelll, W subwf rsolll, W endk22 btfsc STATUS, C ; rstell < rsoll -> noch im Umlauf goto relais ; Ende des Umlaufs noch nicht erreicht movf rsollh, W movwf rstellh movf rsolll, W movwf rstelll ; rstell := rsoll goto relais kontakt btfsc GPIO, iprog goto tprogr ; Programmiertaste gedrueckt btfsc GPIO, iminus goto tminus ; Minustatste gedrueckt btfsc GPIO, iplus goto tplus ; Plustaste gedrueckt goto endkont tprogr btfss GPIO, iplus goto tprogr1 ; Plustaste nicht gedrueckt btfss GPIO, iminus goto tprogr2 ; Minustaste nicht gedrueckt bsf rzust, bpspeed goto tprogr8 ; warten auf Progr. Taste loslassen tprogr1 btfss GPIO, iminus goto tprogr9 ; Weder Plus- noch Minustaste im Programmiermodus gedrueckt bsf rzust, bpminus goto tprogr8 ; warten auf Progr. Taste loslassen tprogr2 bsf rzust, bpplus tprogr8 btfsc GPIO, iprog goto tprogr8 goto endkont ; Werte uebernehmen und auf loslassen der Programmiertaste warten tprogr9 bcf rzust, bpplus bcf rzust, bpminus bcf rzust, bpspeed call wconfig ; speichere Einstellungen goto tprogr8 tplus btfsc rzust, bpplus goto pplus0 ; im Programmiermodus Plusstellung btfsc rzust, bpminus goto pminus0 ; im Programmiermodus Minusstellung btfsc rzust, bpspeed goto pspeed0 ; im Programmiermodus Umlaufgeschwindigkeit ; Weiche nach Plus umlaufen lassen movf rplusl, W movwf rsolll movf rplush, W movwf rsollh btfsc rzust, btplus goto endkont bsf rzust, btplus bcf rzust, btminus call wconf07 ; Status speichern goto endkont tplus1 btfsc GPIO, iplus goto tplus1 goto endprog tminus btfsc rzust, bpplus goto pplus1 ; im Programmiermodus Plusstellung btfsc rzust, bpminus goto pminus1 ; im Programmiermodus Minusstellung btfsc rzust, bpspeed goto pspeed1 ; im Programmiermodus Umlaufgeschwindigkeit movf rminusl, W movwf rsolll movf rminush, W movwf rsollh btfsc rzust, btminus goto endkont bsf rzust, btminus bcf rzust, btplus call wconf07 goto endkont tminus1 btfsc GPIO, iminus goto tminus1 goto endprog ; Plustaste im Programmiermodus pplus0 incfsz rplusl, F goto pplus2 incf rplush, F pplus2 goto tplus1 pminus0 incfsz rminusl, F goto pminus2 incf rminush, F pminus2 goto tplus1 pspeed0 decfsz rdely, F goto tplus1 incf rdely, F incfsz rstep, F goto tplus1 decf rstep, F goto tplus1 ; Minustaste im Programmiermodus pplus1 movlw .1 subwf rplusl, F btfsc STATUS, C goto pplus3 subwf rplush, F pplus3 goto tminus1 pminus1 movlw .1 subwf rminusl, F btfsc STATUS, C goto pminus3 subwf rminush, F pminus3 goto tminus1 pspeed1 decfsz rstep, F goto tminus1 incf rstep, F incfsz rdely, F goto tminus1 decf rdely, F goto tminus1 ; Calibration Data org 0x3ff movlw 0xc8 end