list p=18f25k22 errorlevel -306 ; no page boundary warnings errorlevel -305 ; no default destination messages errorlevel -302 ; no bank 0 warnings errorlevel -202 ; no 'argument out of range' warnings include ; Device configuration settings config FCMEN = OFF config IESO = OFF config PRICLKEN = ON config PLLCFG = OFF config FOSC = HSMP config BORV = 285 config BOREN = OFF config PWRTEN = ON config WDTPS = 2048 config WDTEN = OFF config CCP2MX = PORTB3 config PBADEN = OFF config CCP3MX = PORTC6 config HFOFST = OFF config T3CMX = PORTB5 config P2BMX = PORTC0 config MCLRE = INTMCLR config XINST = ON config DEBUG = OFF config LVP = OFF config STVREN = ON config CP0 = OFF config CP1 = OFF config CP2 = OFF config CP3 = OFF config CPD = OFF config CPB = OFF config WRT0 = OFF config WRT1 = OFF config WRT2 = OFF config WRT3 = OFF config WRTC = OFF config WRTB = OFF config WRTD = OFF config EBTR0 = OFF config EBTR1 = OFF config EBTR2 = OFF config EBTR3 = OFF config EBTRB = OFF CONTMR equ 000 CPSTATE equ 001 DLYCOUNT equ 002 PILOT_12 equ 0F4 PILOT_9 equ 0D2 PILOT_6 equ 0B4 DIODE_OK equ 0B CHARGEPWM equ 3C start ; Initialize Ports TRISA ; PORTA, 0 = CP input = analog in 1 ; PORTA, 1 = PP input = analog in 1 ; PORTA, 2 = Temperatuursensor = analog in 1 ; PORTA, 3 = (niet aangesloten) 1 ; PORTA, 4 = motor driver 1 = digital out 0 ; PORTA, 5 = motor driver 2 = digital out 0 ; PORTA, 6 = kristal 1 0 ; PORTA, 7 = kristal 2 1 movlb 0F ; Stel bank F in voor alle SFR's movlw b'10001111' movwf TRISA movlw b'00001111' movwf ANSELA ; Analog to Digital conversion setup bsf ADCON0, ADON ; Turn on ADC module movlw b'00100101' ; Settings for ADC: left justified, 8 cycles, Fosc/16 movwf ADCON2 movlw b'00000001' movwf ADCON0 ; PORTB, 0 = display 1 = digital out ; PORTB, 1 = display 2 = digital out ; PORTB, 2 = display 3 = digital out ; PORTB, 3 = display 4 = digital out ; PORTB, 4 = Solid State Relais = digital out ; PORTB, 5 = Richtingsschakelaar voor RS485 = digital out ; PORTB, 6 = UART 2 TX (moet als input) ; PORTB, 7 = UART 2 RX (moet als input) movlw b'11000000' movwf TRISB ; PORTC, 0 = display 5 = digital out ; PORTC, 1 = Lock State = digital input ; PORTC, 2 = PWM output poort (moet als input geconfigureerd voor PWM operatie, pag 186) ; PORTC, 3 = display 6 = digital out ; PORTC, 4 = display 7 = digital out ; PORTC, 5 = display 8 = digital out ; PORTC, 6 = UART 1 TX, RS485 communicatie TX ; PORTC, 7 = UART 2 RX, RS485 communicatie RX movlw b'11000110' movwf TRISC ; Initialize PWM op poort C2 bcf CCPTMRS0, C1TSEL0 ; Selecteer TMR1 en TMR2 voor PWM bcf CCPTMRS0, C1TSEL1 bsf CCP1CON, CCP1M3 ; Stel in voor PWM op de CCP module bsf CCP1CON, CCP1M2 movlw b'00000110' ; Stel 16x prescaler in port Timer 2 movwf T2CON movlw 0F9h ; Stel periode in op 249 = 1 kHz bij 16 MHz movwf PR2 movlw 0FA ; Stel 100% PWM in bij start movwf CCPR1L bcf PIR2, TMR2IF bsf T2CON, TMR2ON ; Start de timer bcf PIR1, TMR1IF bsf T1CON, TMR1ON ; Start TMR1 bcf TRISC, 2 ; Enable output driver ; Stroom Duty Cycle CCPR1L:CCP1CON<5:4> CCPR1L CCP1CON<5:4> ; 6 10% 100 25 0 ; 7 11.7% 117 29 1 ; 8 13.3% 133 33 1 ; 9 15% 150 37 2 ; 10 16.7% 167 41 3 ; 11 18.3% 183 45 3 ; 12 20% 200 50 0 ; 13 21.7% 217 54 1 ; 14 23.3% 233 58 1 ; 15 25% 250 62 2 ; 16 26.7% 267 66 3 ; Initialize TMR0 to use as a delay timer ; Set to 16 bits, instruction cycle clock, use prescaler, use 4x prescaler clrf TMR0L clrf TMR0H clrf T0CON ; Always attempt to unlock on reset call unlock ; Main application enter bsf PORTA, 4 ; Motor Standby bsf PORTA, 5 bcf PORTB, 4 ; Power Off btfss PORTC, 1 ; Make sure the socket is unlocked goto unlock movlw 5 ; Reset CONTMR movwf CONTMR movlw 0FA ; Turn off PWM movwf CCPR1L idle call read_cp_high ; Check if there is a car sublw 0 btfsc STATUS, Z goto enter call delay100 ; Delay 100 ms decfsz CONTMR ; 5 times goto idle ; Check the stuff in this loop again movlw 5 movwf CONTMR goto connected ; Then go to Connected connected btfsc PORTC, 1 ; Check if the lock is closed goto lock movlw CHARGEPWM ; Start offering movwf CCPR1L ; Check if the diode is OK ; call read_cp_low ; Check the diode ; sublw 3 ; btfss STATUS, Z ; The return value must be 3, otherwise go back to enter. ; goto enter ; Check the S2 state of the vehicle call read_cp_high movwf CPSTATE sublw 1 ; Cable still connected? btfsc STATUS, Z goto connected movf CPSTATE, w sublw 2 ; Charging requested? btfsc STATUS, Z goto charging ; Cable must be disconnected, unlock and go back to idle. goto enter charging bsf PORTB, 4 ; Power On call read_cp_high movwf CPSTATE sublw 2 ; Still charging? btfsc STATUS, Z goto charging bcf PORTB, 4 ; Power Off goto connected read_cp_high ; Lees CP uit en return met een waarde in W (0 = los, 1 = connected, 2 = S2 gesloten) ; PILOT_12 = 0F4 ; PILOT_9 = 0D2 ; PILOT_6 = 0B4 ; TMR2 loopt mee gedurende de PWM. Als TMR2 < CCPR1L dan zitten we nog in de hoog periode. ; De aquisitietijd voor de AD-conversie is 4 cycli. Als we 16 cycli voor het eind van de PWM-hoog periode beginnen met samplen, hebben we tijd genoeg. ; We willen niet direct aan het begin van de periode zitten, maar na 5%. ; Dus 12 < TMR2 < (CCPR1L - 16) ; Check if TMR2 > 12d movlw d'12' subwf TMR2, W ; TMR2 - 12: moet > dan nul zijn, STATUS,C = 1 btfss STATUS, C ; Continue to next step if STATUS,C = 1 goto read_cp_high ; Check if TMR2 < (CCPR1L - 16) movlw d'16' ; 16 -> W subwf CCPR1L, W ; (CCPR1L - 16) -> W subwf TMR2, W ; TMR2 - (CCPR1L - 16): moet < dan nul zijn, STATUS,C = 0 btfsc STATUS, C ; Continue to next step if STATUS,C = 0 goto read_cp_high goto take_sample read_cp_low ; Read the CP at the low point, return 3 if OK, 0 if not. ; (CCPR1L + 12) < TMR2 < (PR2 - 16) ; Check if TMR2 > CCPR1L + 12 movf CCPR1L, W ; CCPR1L -> W addlw d'12' ; (CCPR1L + 12) -> W subwf TMR2, W ; TMR2 - (CCPR1L + 12): moet > dan nul, STATUS,C = 1 btfss STATUS, C goto read_cp_low ; Check if TMR2 < (PR2 - 16) movlw d'16' ; 16 -> W subwf PR2, W ; (PR2 - 16) -> W subwf TMR2, W ; TMR2 - (PR2 - 16): moet < dan nul zijn, STATUS,C = 0 btfsc STATUS, C goto read_cp_low goto take_sample take_sample bsf ADCON0, GO ; Start the sample wait_for_ad_result btfsc ADCON0, DONE goto wait_for_ad_result ; Check if 12V movf ADRESH, w ; Voltage -> W sublw PILOT_12 ; PILOT_12 - Voltage: moet < nul zijn, dus STATUS,C = 0 btfss STATUS, C retlw 0 ; Check if 9V movf ADRESH, w sublw PILOT_9 btfss STATUS, C retlw 1 ; Check if 6V movf ADRESH, w sublw PILOT_6 btfss STATUS, C retlw 2 ; Check if diode OK movf ADRES, w ; Voltage -> W sublw DIODE_OK ; DIODE_OK - Voltage: moet > 0, STATUS,C = 1 btfsc STATUS, C ; Skip over this of the STATUS,C = 0 retlw 3 ; Otherwise return "0", meaning just go to idle and turn everything off retlw 0 lock bcf PORTA, 4 bsf PORTA, 5 call delay100 ; Blocking 100ms delay call delay100 ; Blocking 100ms delay bsf PORTA, 4 ; Stop the motor call delay2000 ; Wait 2 seconds to charge the capacitor back up.. goto idle unlock movlw 0FA ; Turn off PWM movwf CCPR1L bsf PORTA, 4 bcf PORTA, 5 call delay100 ; Blocking 100ms delay call delay100 ; Blocking 100ms delay bsf PORTA, 5 ; Stop the motor call delay2000 ; Wait 2 seconds to charge the capacitor back up. goto enter delay100 ; Preset timer 0 value at 15533 movlw 3C movwf TMR0H movlw 0AD movwf TMR0L ; Set prescaler to 8x bcf T0CON, T0PS0 bsf T0CON, T0PS1 bcf T0CON, T0PS2 ; Start the timer bcf INTCON, TMR0IF ; Clear the interrupt bsf T0CON, TMR0ON ; Start the timer goto delay_wait delay_wait btfss INTCON, TMR0IF ; Wait for the timer to overflow goto delay_wait bcf T0CON, TMR0ON ; Stop the timer return delay500 movlw d'5' movwf DLYCOUNT goto delay_repeat delay1000 movlw d'10' movwf DLYCOUNT goto delay_repeat delay2000 movlw d'20' movwf DLYCOUNT goto delay_repeat delay_repeat call delay100 decfsz DLYCOUNT, f goto delay_repeat return end