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 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 ; 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 ; Main application enter bsf PORTA, 4 ; Motor Standby bsf PORTA, 5 bcf PORTB, 4 ; Power Off btfss PORTC, 1 ; Make sure the lock is off goto unlock movlw 5 ; Reset CONTMR movwf CONTMR movlw 0FA ; Turn off PWM movwf CCPR1L call delay100 idle call read_cp ; 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 3A ; Offer 14 amps movwf CCPR1L call read_cp 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 unlock charging bsf PORTB, 4 ; Power On call read_cp sublw 2 ; Still charging? movwf CPSTATE btfsc STATUS, Z goto charging bcf PORTB, 4 ; Power Off goto connected read_cp ; Lees CP uit en return met een waarde in W (0 = los, 1 = connected, 2 = S2 gesloten, 3 = error) ; PILOT_12 = 0F4 ; PILOT_9 = 0D2 ; PILOT_6 = 0B4 ; Selecteer CP poort voor analoge conversie movlw b'00000001' movwf ADCON0 wait_for_pwm_period ; 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 halverwege. ; Dus CCPR1L/2 < TMR2 < (CCPR1L - 16) ; Check if TMR2 > CCPR1L / 2 rrcf CCPR1L, W subwf TMR2, W ; TMR2 - CCPR1L/2: moet > dan nul zijn, STATUS, C = 1 btfsc STATUS, C goto wait_for_pwm_period ; 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 goto wait_for_pwm_period bsf ADCON0, GO ; Start the sample wait_for_ad_result btfsc ADCON0, DONE goto wait_for_ad_result ; Check if 12V movf ADRESH, w sublw PILOT_12 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 ; 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 bsf PORTA, 4 ; Stop the motor goto idle unlock movlw 0FA ; Turn off PWM movwf CCPR1L bsf PORTA, 4 bcf PORTA, 5 call delay100 ; Blocking 100ms delay bsf PORTA, 5 ; Stop the motor call delay2000 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 delay2000 movlw d'20' movwf DLYCOUNT delay2000_repeat call delay100 decfsz DLYCOUNT, f goto delay2000_repeat return end