list p=16f84a #include p16f84a.inc __config _XT_OSC & _PWRTE_OFF & _WDT_OFF & _CP_OFF w50 EQU 0x0C ; 50 microsekund-tæller ms1 EQU 0x0D ; Millisekund-tæller adresse 1 ms2 EQU 0x0E ; Millisekund-tæller adresse 2 ms EQU 0x10 ; Millisekund-tæller antal ms lcd EQU 0x11 ; Data til LCD ins EQU 0x12 ; Instruktion til LCD num EQU 0x13 cnt EQU 0x14 int_w EQU 0x20 ; Plads til W under interruptservice int_s EQU 0x21 ; Plads til STATUS under interruptservice int_b EQU 0x22 ; Plads til B under interruptservice int_ob EQU 0x23 ; int_n EQU 0x24 tmr_run EQU 0x30 tmr_mi1 EQU 0x31 tmr_m10 EQU 0x32 tmr_se1 EQU 0x33 tmr_s10 EQU 0x34 ORG 0x000 ; Reset vector GOTO start ; Hop til programstart ORG 0x004 ; Interrupt vector GOTO service ; Hop til interruptserviceroutine start MOVLW b'00001000' ; Interrupts fra, Port change interrupt til MOVWF INTCON ; Skriv til INTCON register BSF STATUS,RP0 ; Skift til hukommelsesbank 1 MOVLW 0x00 ; 00000000 MOVWF TRISA ; A porte til output MOVLW 0xF0 ; 11110000 MOVWF TRISB ; Høje B porte input, lave B porte til output MOVLW b'11001000' ; Disable Pullup, Interrupt on Rising, Internal TMR0 Source, Increment on Rising, Prescaler to WDT, Prescaler Value x3 MOVWF OPTION_REG ; Skriv til OPTION register BCF STATUS,RP0 ; Skift til hukommelsesbank 0 MOVLW 0x00 MOVWF PORTA ; A porte til lav MOVWF PORTB ; B porte til lav MOVLW .50 MOVWF ms CALL waitms ; Vent 50 ms display_init MOVLW b'00000010' ; 4 bit mode MOVWF lcd CALL send_nibble MOVLW b'00101100' ; 001xxx-- "Function set", 4 bit mode, 2 line mode, Display on MOVWF lcd CALL send_byte MOVLW b'00010000' ; 0001xx-- "Cursor or display shift", Cursor move, Left shift MOVWF lcd CALL send_byte MOVLW b'00001100' ; 00001xxx "Display on/off control", Display on, Cursor off, Blink off MOVWF lcd CALL send_byte MOVLW b'00000110' ; 000001xx "Entry mode set", Increase, Display not is shifted MOVWF lcd CALL send_byte CALL clear_display CLRF tmr_run CALL clear_timer BSF INTCON,7 ; Slå interrupts til loop CALL update_display BTFSS tmr_run,0 GOTO loop MOVLW .250 MOVWF cnt MOVLW .4 MOVWF ms CALL tick_tock loop_1 BTFSS tmr_run,0 GOTO loop CALL waitms DECFSZ cnt,f GOTO loop_1 GOTO loop tick_tock MOVF tmr_se1,w SUBLW .0 BTFSC STATUS,2 GOTO tick_tock_1 DECF tmr_se1,f RETURN tick_tock_1 MOVLW .9 MOVWF tmr_se1 MOVF tmr_s10,w SUBLW .0 BTFSC STATUS,2 GOTO tick_tock_2 DECF tmr_s10,f RETURN tick_tock_2 MOVLW .5 MOVWF tmr_s10 MOVF tmr_mi1,w SUBLW .0 BTFSC STATUS,2 GOTO tick_tock_3 DECF tmr_mi1,f RETURN tick_tock_3 MOVLW .9 MOVWF tmr_mi1 MOVF tmr_m10,w SUBLW .0 BTFSC STATUS,2 GOTO tick_tock_4 DECF tmr_m10,f RETURN tick_tock_4 BCF tmr_run,0 CALL clear_timer BSF PORTA,2 RETURN clear_timer CLRF tmr_mi1 CLRF tmr_m10 CLRF tmr_se1 CLRF tmr_s10 RETURN update_display MOVLW b'11000000' MOVWF ins CALL send_instruction MOVF tmr_m10,w CALL get_number MOVWF lcd CALL send_byte MOVF tmr_mi1,w CALL get_number MOVWF lcd CALL send_byte MOVLW a':' MOVWF lcd CALL send_byte MOVF tmr_s10,w CALL get_number MOVWF lcd CALL send_byte MOVF tmr_se1,w CALL get_number MOVWF lcd CALL send_byte RETURN get_number ANDLW 0x0F ADDWF 0x02,f RETLW a'0' RETLW a'1' RETLW a'2' RETLW a'3' RETLW a'4' RETLW a'5' RETLW a'6' RETLW a'7' RETLW a'8' RETLW a'9' RETLW a'A' RETLW a'B' RETLW a'C' RETLW a'D' RETLW a'E' RETLW a'F' clear_display MOVLW b'00000001' MOVWF ins CALL send_instruction MOVLW .2 MOVWF ms CALL waitms RETURN return_home MOVLW b'00000010' MOVWF ins CALL send_instruction MOVLW .2 MOVWF ms CALL waitms RETURN send_instruction BCF PORTA,3 ; Skift til "Instructions" mode MOVF ins,w ; Kopier ins til W MOVWF lcd ; Kopier W til lcd CALL send_byte ; Send byte BSF PORTA,3 ; Skift til "Display data" mode RETURN send_byte ; Send byte til display, højste 4 bits først SWAPF lcd,f ; Swap lcd nibbles CALL send_nibble ; Send de 4 højste bits SWAPF lcd,f ; Swap lcd nibbles CALL send_nibble ; Send de 4 laveste bits RETURN send_nibble ; Send 4 bits til display MOVLW 0xF0 ; W til 11110000 ANDWF PORTB,f ; AND W i port B til port B, så de laveste 4 bits bliver 0 MOVLW 0x0F ; W til 00001111 ANDWF lcd,w ; AND W i lcd til W, kopierer de laveste 4 bits fra lcd til W IORWF PORTB,f ; OR W i port B til port B, kopierer de laveste 4 bits fra W til port B BSF PORTA,4 ; Set Read/Write enable CALL wait50 ; Vent 50 microsekunder BCF PORTA,4 ; Clear Read/Write enable CALL wait50 ; Vent 50 microsekunder RETURN ; Done waitms MOVF ms,w MOVWF ms1 waitms_1 MOVLW .19 MOVWF ms2 waitms_2 CALL wait50 DECFSZ ms2,f GOTO waitms_2 DECFSZ ms1,f GOTO waitms_1 RETURN wait50 MOVLW .15 MOVWF w50 wait50_1 DECFSZ w50,f GOTO wait50_1 RETURN service BCF INTCON,7 ; Slå interrupts fra MOVWF int_w ; Gem W SWAPF STATUS,w ; Hent STATUS register (SWAPF brugt for ikke at ødelægge Z-flag) MOVWF int_s ; Gem STATUS¨ BTFSC INTCON,0 GOTO bsvc_0 GOTO service_end bsvc_0 SWAPF PORTB,w ; Kopier B inputs til 4 laveste bits i W ANDLW 0x0F ; AND W med 00001111 så vi kun gemmer de bits vi har brug for MOVWF int_b ; Gem resultetet XORWF int_ob,w MOVWF int_n MOVF int_b,w ANDWF int_n,f BTFSC PORTA,2 GOTO bsvc_mute BTFSC tmr_run,0 GOTO bsvc_stop BTFSS int_n,0 GOTO bsvc_1 CALL clear_timer GOTO bsvc_end bsvc_1 BTFSS int_n,1 GOTO bsvc_2 INCF tmr_se1,f MOVF tmr_se1,w SUBLW .10 BTFSS STATUS,2 GOTO bsvc_end CLRF tmr_se1 INCF tmr_s10,f MOVF tmr_s10,w SUBLW .6 BTFSC STATUS,2 CLRF tmr_s10 GOTO bsvc_end bsvc_2 BTFSS int_n,2 GOTO bsvc_3 INCF tmr_mi1,f MOVF tmr_mi1,w SUBLW .10 BTFSS STATUS,2 GOTO bsvc_end CLRF tmr_mi1 INCF tmr_m10,f MOVF tmr_m10,w SUBLW .6 BTFSC STATUS,2 CLRF tmr_m10 GOTO bsvc_end bsvc_3 BTFSS int_n,3 GOTO bsvc_end BSF tmr_run,0 GOTO bsvc_end bsvc_mute BCF PORTA,2 GOTO bsvc_end bsvc_stop BTFSS int_n,3 GOTO bsvc_end BCF tmr_run,0 bsvc_end MOVF int_b,w MOVWF int_ob service_end MOVLW b'11111000' ANDWF INTCON,f ; Clear interrupt flags SWAPF int_s,w ; Hent gemt STATUS MOVWF STATUS ; Skriv til STATUS register SWAPF int_w,f ; Swap gemt W (for at udligne) SWAPF int_w,w ; Hent gemt W BSF INTCON,7 ; Slå interrupts til RETFIE END