;************************************************************************* ; Ziver Koc 1 september 2007 PIC 16F648A to HD44780 LCD ; ; ; LCD control lines ; #define LCD_RS 0 ; 0 = Command, 1 = Data ; #define LCD_RW 1 ; 0 = Write, 1 = Read ; #define LCD_E 2 ; 1 to send data ; #define LCD_D4 3 ; 4 data lines ; #define LCD_D5 4 ; #define LCD_D6 5 ; #define LCD_D7 6 ; ; ; Registers we will be using ; #define R_DEL1 0x20 ; Delay register ; #define R_DEL2 0x21 ; Delay register ; #define R_WDATA_TMP1 0x22 ; #define R_WDATA_TMP2 0x23 ; #define R_SEND_W_TMP 0x24 ; ;************************************************************************* CONSTANT FUNCTSET81 = b'00110000' ; 8-bit mode, 1 lines CONSTANT FUNCTSET82 = b'00111000' ; 8-bit mode, 2 lines CONSTANT FUNCTSET41 = b'00100000' ; 4-bit mode, 1 lines CONSTANT FUNCTSET42 = b'00101000' ; 4-bit mode, 2 lines CONSTANT DDZERO = b'10000000' ; WRITE 0 to DDRAM CONSTANT LCDSH = b'00000110' ;Commands for working with LCD display CONSTANT LCDCLR = b'00000001' ;Clear display, cursor home CONSTANT LCDCH = b'00000010' ;Cursor home CONSTANT LCDCL = b'00001000' ;Move cursor to the left CONSTANT LCDCR = b'00001010' ;Move cursor to the right CONSTANT LCDSL = b'00011000' ;Move the content of display to the left CONSTANT LCDSR = b'00011100' ;Move the content of display to the right CONSTANT LCDCOU = b'00001110' ;Turn on visible underline cursor CONSTANT LCDCOB = b'00001111' ;Turn on visible blinking-block cursor CONSTANT LCDCONT = b'00001100' ;Make cursor invisible CONSTANT LCDL1 = b'10000000' ;Select line 1 CONSTANT LCDL2 = b'11000000' ;Select line 2 ;************************************************************************* ; ; ;************************************************************************* LCD_init macro ; Begin the LCD initialisation ; Power up timer should give delay, but do it anyway movlw 0x14 call delay ; Send the command to select 4-bit mode first bcf PORTB, LCD_RS bcf PORTB, LCD_RW movlw 0x02 ; Still in 8-bit, so appears as 0x20 to LCD call LCD_data call LCD_pulse_e ; Should now be in 4-bit mode - send init LCD_cmd FUNCTSET42 LCD_cmd LCDCOU LCD_cmd LCDSH endm ;************************************************************************* ; ; ;************************************************************************* LCD_cmd macro lcddata bcf PORTB, LCD_RS ; Command mode movlw lcddata ; Send cmd call LCD_SendW bsf PORTB, LCD_RS ; Data mode call delay_1ms ; Takes a couple of ms endm LCD_printC macro lcddata movlw lcddata call LCD_SendW endm LCD_println macro select, text ;This macro prints text parameter of up to ;24 characters from the current cursor local Message ;position local Start local Exit local i=0 goto Start dt text ;Form a lookup table from parameters dt 0 Start if select==1 LCD_cmd LCDL1 else if select==2 LCD_cmd LCDL2 endif endif while i<24 ;Conditional program translation - repeat 24x call Message+1 ;Read lookup table and store value to W addlw 0 bz Exit ;until it reads zero call LCD_data ;Call the routine that prints W on LCD i=i+1 endw Exit endm ;************************************************************************* ; ; ;************************************************************************* LCD_SendW: movwf R_SEND_W_TMP swapf R_SEND_W_TMP, F movlw 0x0F andwf R_SEND_W_TMP, W call LCD_data call LCD_pulse_e swapf R_SEND_W_TMP, F movlw 0x0F andwf R_SEND_W_TMP, W call LCD_data call LCD_pulse_e return LCD_data: movwf R_WDATA_TMP1 movf PORTB, W movwf R_WDATA_TMP2 bcf R_WDATA_TMP2, LCD_D4 bcf R_WDATA_TMP2, LCD_D5 bcf R_WDATA_TMP2, LCD_D6 bcf R_WDATA_TMP2, LCD_D7 btfsc R_WDATA_TMP1, 0 bsf R_WDATA_TMP2, LCD_D4 btfsc R_WDATA_TMP1, 1 bsf R_WDATA_TMP2, LCD_D5 btfsc R_WDATA_TMP1, 2 bsf R_WDATA_TMP2, LCD_D6 btfsc R_WDATA_TMP1, 3 bsf R_WDATA_TMP2, LCD_D7 movf R_WDATA_TMP2, W movwf PORTB return LCD_pulse_e bsf PORTB, LCD_E nop nop nop nop bcf PORTB, LCD_E call delay_1ms call delay_1ms return ; Calls the delay_1ms routine the number of times specified by ; the W register. delay movwf R_DEL2 delay_loop call delay_1ms decfsz R_DEL2, F goto delay_loop return ; When called gives a delay of about 1000 cycles, or 1ms at 4Mhz ; before the next instruction is executed. delay_1ms movlw d'248' movwf R_DEL1 delay_1ms_loop nop decfsz R_DEL1, F goto delay_1ms_loop return