;---------------------------------------------------------------------------------------- ; Basic 2x16 character HD44780 lcd unit test - PIC 16F628A code ; By Phil - www.retroleum.co.uk ; --------------------------------------------------------------------------------------- ; 4 bit mode / 6 wire interface (module's RW signal (pin5) connected to ground, D0:3 left unconnected) ; Does not read the busy flag, just uses long waits ; Fairly arbitrary timing and no attempt at optimization has been made ; PIC connections: ; ---------------- ; PortA [0] connected to module "RS" (pin4) ; PortA [1] connected to module "E" (pin6) ; PortB[0:3] connected to module [D4:7] (pins 11-14) ; PIC uses its internal ~4MHz RC oscillator. ; ** Caution! The simple portB write used here also puts garbage on PortB 4:7 ** ; ** Flashing HELLO WORLD demo code pulses portA,2 to indicate program is running ** ;---------------------------------------------------------------------------------------- list p=16f628a ; define processor list r=decimal ; default number base #include ; processor specific defs #define bank0 bcf STATUS,RP0 ; macros #define bank1 bsf STATUS,RP0 #define skipifzero btfss STATUS,Z #define skipifnotzero btfsc STATUS,Z #define skipifcarry btfss STATUS,C #define skipifnotcarry btfsc STATUS,C ;----- PIC H/W OPTIONS ----------------------------------------------------------------------- __CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _LVP_OFF ;----- VARIABLES------------------------------------------------------------------------------ temp1 equ 0x20 ; First PIC RAM address temp2 equ 0x21 ;---- PORT assignments -------------------------------------------------------------------------- #DEFINE lcd_rs PORTA,0 #DEFINE lcd_e PORTA,1 #DEFINE test_led PORTA,2 ;---------------------------------------------------------------------------------------------- w_temp equ 0x70 ; variable used for context saving status_temp equ 0x71 ; variable used for context saving ;********************************************************************************************* ORG 0x000 ; processor reset vector goto init_pic ; go to beginning of program ;--------------------------------------------------------------------------------------------- ORG 0x004 ; interrupt vector location ;------ INITIALIZE PIC ----------------------------------------------------------------------- init_pic movlw b'00000111' movwf CMCON ; use digital mode for PORTB (disable comparitors) clrf PORTA clrf PORTB banksel TRISA movlw b'00100000' ; set data direction for port A movwf TRISA movlw b'00000000' ; set data direction for port B movwf TRISB movlw b'10000000' movwf OPTION_REG ; port B pull ups=off banksel PORTA ; back to page 0 clrf INTCON ; disable interrupts ;------ Main demo program ------------------------------------------------------------------------ call lcd_init my_loop movlw 0x80+0x00 ; set LCD address (left char of first line) call lcd_send_instruction_w movlw 'H' ; Write "Hello" call lcd_send_data_w movlw 'e' call lcd_send_data_w movlw 'l' call lcd_send_data_w movlw 'l' call lcd_send_data_w movlw 'o' call lcd_send_data_w movlw 250 call pause_w_msec movlw 0x80+0x40 call lcd_send_instruction_w ; set address (left char of second line) movlw 'W' ; Write "World" call lcd_send_data_w movlw 'o' call lcd_send_data_w movlw 'r' call lcd_send_data_w movlw 'l' call lcd_send_data_w movlw 'd' call lcd_send_data_w movlw 250 call pause_w_msec movlw 0x80+0x00 ; set address (left char of first line) call lcd_send_instruction_w movlw '-' ; Replace "hello" with "-----" call lcd_send_data_w movlw '-' call lcd_send_data_w movlw '-' call lcd_send_data_w movlw '-' call lcd_send_data_w movlw '-' call lcd_send_data_w call pause_w_msec movlw 0x80+0x40 call lcd_send_instruction_w ; set address (left char of second line) movlw '-' ; replace "World" with "-----" call lcd_send_data_w movlw '-' call lcd_send_data_w movlw '-' call lcd_send_data_w movlw '-' call lcd_send_data_w movlw '-' call lcd_send_data_w bsf test_led ; flash a led on porta,2 (just for test purposes) movlw 250 call pause_w_msec bcf test_led goto my_loop ;------------------------------------------------------------------------------------------------- ; HD44780 lcd unit routines ;------------------------------------------------------------------------------------------------- lcd_init: bcf lcd_rs ; Ensure RS =0 : Instruction mode movlw 250 call pause_w_msec ; Wait 15mSec after power up movlw 0x03 ; "function set" command (8 bit, 1 line) #1 call lcd_nybble_write ; Send the nybble to LCD movlw 10 call pause_w_msec ; Datasheet spec: Wait at least 4.1 mSecs movlw 0x03 ; "function set" command (8 bit, 1 line) #2 call lcd_nybble_write ; Send the nybble to LCD movlw 1 call pause_w_msec ; Datasheet spec: Wait at least 100 uSecs movlw 0x03 ; "function set" command (8 bit, 1 line) #3 call lcd_nybble_write ; Send the nybble to LCD movlw 1 call pause_w_msec movlw 0x02 ; "function set" command (8 bit, 1 line) call lcd_nybble_write ; Send the nybble to LCD movlw 0x2c ; Function Set: 4 bit mode / 2 Lines / 5x10 font call lcd_send_instruction_w movlw 0x06 ; increment address (cursor) after every write call lcd_send_instruction_w movlw 0x0C ; display on / cursor off / blink off call lcd_send_instruction_w return ;--------------------------------------------------------------------------------------------------- lcd_send_data_w: movwf temp1 swapf temp1, w bsf lcd_rs ; lcd_rd: 1 = DATA call lcd_nybble_write ; Send 7:4 movf temp1, w call lcd_nybble_write ; Send 3:0 movlw 1 call pause_w_msec ; wait 1 millisecond second return ;---------------------------------------------------------------------------------------------------- lcd_send_instruction_w: movwf temp1 swapf temp1, w bcf lcd_rs ; lcd_rd: 0 = Instruction call lcd_nybble_write ; send 7:4 movf temp1, w call lcd_nybble_write ; send 3:0 movlw 15 call pause_w_msec ; wait 15 milliseconds return ;----------------------------------------------------------------------------------------------------- lcd_nybble_write movwf PORTB ; Puts bits 3:0 of W on port B call lcd_write_pulse ; cycle E signal to write to LCD return ;------------------------------------------------------------------------------------------------------ lcd_write_pulse ; Set/clear lcd's E signal bsf lcd_e nop nop nop nop nop nop nop nop nop nop nop nop bcf lcd_e nop nop nop nop nop nop nop nop nop nop nop nop return ;----------------------------------------------------------------------------------------------------- pause_w_msec ; assumes 4MHz clock movwf temp1 movlw 250 movwf temp2 ploop nop ;1 cycle decfsz temp2,f ;1 cycle goto ploop ;2 cycles decfsz temp1,f goto ploop return ;------------------------------------------------------------------------------------------------------ END