list p=18f25k22 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 ; Holding registers for some values CONTMR equ 000 CPSTATE equ 001 DLYCOUNT equ 002 LCD_CHAR equ 003 LCD_NIB_H equ 004 LCD_NIB_L equ 005 DLYREG1 equ 006 DLYREG2 equ 007 WTEMP equ 008 PWM_VALUE equ 009 ; Some constants PILOT_12 equ 0F4 PILOT_9 equ 0D2 PILOT_6 equ 0B4 DIODE equ 016 PWM_6A equ 19 PWM_7A equ 1D PWM_8A equ 21 PWM_9A equ 25 PWM_10A equ 29 PWM_11A equ 2D PWM_12A equ 32 PWM_13A equ 36 PWM_14A equ 3A PWM_15A equ 3E PWM_16A equ 42 PWM_0A equ 0FA ; Some port labels LCD_BL equ 0 LCD_RS equ 3 LCD_RW equ 4 LCD_EN equ 5 ; Return codes for the read_cp functions STATE_A equ 0 STATE_B equ 1 STATE_C equ 2 KNOP_LINKS equ 0 KNOP_MIDDEN equ 1 KNOP_RECHTS equ 2 CHARGEPWM equ PWM_7A goto start 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) clrf ANSELB movlw b'11000000' movwf TRISB ; PORTC, 0 = display 5 = digital out (display verlichting) ; 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 clrf ANSELC 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 PWM_0A ; 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 8x prescaler clrf TMR0L clrf TMR0H clrf T0CON bsf T0CON, T0PS1 ; Initialize Serial port 2 (UART) bcf TXSTA2, SYNC ; Asynchronous bsf TXSTA2, BRGH ; High speed bcf BAUDCON2, BRG16 ; 8 bit Baud Rate Generator movlw 33 ; 19.2 kbaud movwf SPBRG2 bsf TXSTA2, TXEN ; Enable the transmit port bsf RCSTA2, SPEN ; Enable the receive port bsf RCSTA2, CREN ; Enable continuous receive ; Initialize LCD call delay100 call lcd_init movlw PWM_7A movwf PWM_VALUE call display_7a ; 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 display_idle bcf PORTC, LCD_BL ; Turn off LCD backlight call check_serial ; Check for serial communications call check_state ; Check if there is a car call check_knoppen sublw STATE_A 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 call check_knoppen bsf PORTC, LCD_BL ; Turn on LCD backlight call check_state sublw STATE_A btfsc STATUS, Z goto enter btfsc PORTC, 1 ; Check if the lock is closed goto lock call display_connected movff PWM_VALUE, CCPR1L call delay_1 ; Check if the diode is OK call check_diode ; Check the diode (als goed: W = 1) sublw 1 ; (W = 0) btfss STATUS, Z ; Proceed if the diode state was 1 goto enter ; Check the S2 state of the vehicle call check_state movwf CPSTATE sublw STATE_B btfsc STATUS, Z goto connected movf CPSTATE, w sublw STATE_C btfsc STATUS, Z goto charging goto enter charging call display_charging movff PWM_VALUE, CCPR1L bsf PORTB, 4 ; Power On call check_knoppen call check_state sublw STATE_C btfsc STATUS, Z goto charging bcf PORTB, 4 ; Power Off goto connected check_state ; Lees CP uit en return met een waarde in W (0 = los, 1 = connected, 2 = S2 gesloten) ; 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 8 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 - 8) ; Check if TMR2 > 12d movlw d'12' cpfsgt TMR2 ; Compare TMR2 to W, proceed if TMR2 > W goto check_state ; Check if TMR2 < (CCPR1L - 16) movlw 8 ; 8 -> W subwf CCPR1L, W ; (CCPR1L - 8) -> W cpfslt TMR2 ; Compare TMR2 to W, proceed if TMR2 < W goto check_state call take_sample movf ADRESH, W ; 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 STATE_A ; Check if >9V movf ADRESH, w sublw PILOT_9 btfss STATUS, C retlw STATE_B ; Check if >6V movf ADRESH, w sublw PILOT_6 btfss STATUS, C retlw STATE_C ; If it is something else, take state A which is safe. retlw STATE_A check_diode ; Read the CP at the low point, return 1 if OK, 0 if not. ; (CCPR1L + 12) < TMR2 < (PR2 - 8) ; Check if TMR2 > CCPR1L + 12 movf CCPR1L, W ; CCPR1L -> W addlw d'12' ; (CCPR1L + 12) -> W cpfsgt TMR2 ; Compare TMR2 to W, proceed if TMR2 > W goto check_diode ; Check if TMR2 < (PR2 - 8) movlw 8 ; 8 -> W subwf PR2, W ; (PR2 - 8) -> W cpfslt TMR2 ; Compare TMR2 to W, proceed if TMR2 < W goto check_diode call take_sample movlw DIODE cpfsgt ADRESH ; Compare ADRESH to DIODE, return 0 if ADRESH > DIODE retlw 1 retlw 0 take_sample bsf ADCON0, GO ; Start the sample wait_sample btfsc ADCON0, DONE goto wait_sample return ; Routines for locking and unlocking lock call display_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 connected unlock movlw 0FA ; Turn off PWM movwf CCPR1L bcf PORTB, 4 ; Power off call display_unlock bsf PORTA, 4 ; Start the motor 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 ; Always go to 'enter' after unlocking. ; Routines for a 100 ms delay delay100 ; Preset timer 0 value at 15533 movlw 3C movwf TMR0H movlw 0AD movwf TMR0L ; Start the timer bcf INTCON, TMR0IF ; Clear the interrupt bsf T0CON, TMR0ON ; Start the timer delay_wait btfss INTCON, TMR0IF ; Wait for the timer to overflow goto delay_wait bcf T0CON, TMR0ON ; Stop the timer return ; Routines for a 2 second delay delay2000 movlw d'20' movwf DLYCOUNT goto delay_repeat delay_repeat call delay100 decfsz DLYCOUNT, f goto delay_repeat return ; Routines to handle serial communication from the Raspberry Pi check_serial btfsc PIR3, RC2IF ; Check of er iets aan de hand is goto read_serial return read_serial btfsc RCSTA2, FERR ; Check of er een frame error is (dan naar reset) goto start_reset btfsc RCSTA2, OERR ; Check of er overrun-errors zijn en wis deze call clear_oerr movf RCREG2, W return clear_oerr bcf RCSTA2, CREN bsf RCSTA2, CREN return start_reset call display_reset reset display_reset movlw 1 call lcd_write movlw 80 call lcd_write movlw A'R' call lcd_print movlw A'E' call lcd_print movlw A'S' call lcd_print movlw A'E' call lcd_print movlw A'T' call lcd_print return ; 1 ms Delay (for display logic) delay_1 movwf WTEMP movlw 4 movwf DLYREG1 movlw 0F8 movwf DLYREG2 delay_1_inner nop decfsz DLYREG2 ; 1 cycle goto delay_1_inner ; 2 cycles delay_1_loop movlw 0F8 movwf DLYREG2 decfsz DLYREG1 goto delay_1_inner movf WTEMP, W return ; Everything having to do with the HD44780 display lcd_init call delay100 bcf TRISB, KNOP_LINKS bcf TRISB, KNOP_MIDDEN bcf TRISB, KNOP_RECHTS bcf PORTC, LCD_EN bcf PORTC, LCD_RW bcf PORTC, LCD_RS movf PORTB, W andlw 0F0 iorlw 3 ; Reset instruction, see page 45 of Hitachi datasheet movwf PORTB call lcd_go call delay_1 ; wait 5 ms call delay_1 call delay_1 call delay_1 call delay_1 call lcd_go call delay_short call lcd_go call delay_short movf PORTB, W andlw 0F0 iorlw 2 ; Set up as 4-bit mode (interpreted as 8-bit command so completes in one write) movwf PORTB call lcd_go call delay_1 ; 4-bit transmissions starts here movlw b'00101000' ; Function Set, 4-bit, 2 line display, 5x8 pixel characters call lcd_write movlw b'00001000' ; Display Off, Cursor Off, Blink Off call lcd_write movlw b'00000001' ; Clear Display call lcd_write movlw b'00000110' ; Entry mode set (increment and not shifted) call lcd_write movlw b'00001100' ; Display On, Blink On call lcd_write bsf TRISB, KNOP_LINKS bsf TRISB, KNOP_MIDDEN bsf TRISB, KNOP_RECHTS return lcd_print bsf PORTC, LCD_RS call lcd_write bcf PORTC, LCD_RS return lcd_write ; Split nibbles bcf TRISB, KNOP_LINKS bcf TRISB, KNOP_MIDDEN bcf TRISB, KNOP_RECHTS movwf LCD_CHAR andlw 0F movwf LCD_NIB_L swapf LCD_CHAR, W andlw 0F movwf LCD_NIB_H ; Write high nibble movf PORTB, W andlw 0F0 iorwf LCD_NIB_H, W movwf PORTB call lcd_go call delay_1 ; Write low nibble movf PORTB, W andlw 0F0 iorwf LCD_NIB_L, W movwf PORTB call lcd_go call delay_1 call delay_1 bsf TRISB, KNOP_LINKS bsf TRISB, KNOP_MIDDEN bsf TRISB, KNOP_RECHTS return lcd_go bsf PORTC, LCD_EN nop nop bcf PORTC, LCD_EN return delay_short decfsz DLYREG1 goto delay_short return display_idle movlw 80 call lcd_write movlw A' ' call lcd_print movlw A'G' call lcd_print movlw A'e' call lcd_print movlw A'r' call lcd_print movlw A'e' call lcd_print movlw A'e' call lcd_print movlw A'd' call lcd_print return display_connected movlw 80 call lcd_write movlw A'V' call lcd_print movlw A'r' call lcd_print movlw A'b' call lcd_print movlw A'o' call lcd_print movlw A'n' call lcd_print movlw A'd' call lcd_print movlw A'e' call lcd_print movlw A'n' call lcd_print return display_charging movlw 80 call lcd_write movlw A' ' call lcd_print movlw A'L' call lcd_print movlw A'a' call lcd_print movlw A'd' call lcd_print movlw A'e' call lcd_print movlw A'n' call lcd_print movlw A' ' call lcd_print movlw A' ' call lcd_print return display_unlock movlw 80 call lcd_write movlw A' ' call lcd_print movlw A'U' call lcd_print movlw A'n' call lcd_print movlw A'l' call lcd_print movlw A'o' call lcd_print movlw A'c' call lcd_print movlw A'k' call lcd_print movlw A' ' call lcd_print return display_lock movlw 80 call lcd_write movlw A' ' call lcd_print movlw A' ' call lcd_print movlw A'L' call lcd_print movlw A'o' call lcd_print movlw A'c' call lcd_print movlw A'k' call lcd_print movlw A' ' call lcd_print movlw A' ' call lcd_print return check_knoppen btfss PORTB, KNOP_LINKS goto set_7a btfss PORTB, KNOP_RECHTS goto set_14a btfss PORTB, KNOP_MIDDEN goto unlock return set_7a movlw PWM_7A movwf PWM_VALUE call display_7a return set_14a movlw PWM_14A movwf PWM_VALUE call display_14a return display_7a movlw 0C2 call lcd_write movlw A' ' call lcd_print movlw A'7' call lcd_print movlw A'A' call lcd_print return display_14a movlw 0C2 call lcd_write movlw A'1' call lcd_print movlw A'4' call lcd_print movlw A'A' call lcd_print return end