buenas...
a falta de un buen tuto que explique cómo controlar un lcd con un pic
estoy descifrando los programas ya hechos que encuentro en ensamblador
el siguiente código funciona (aunque creo que tiene un error en el número de direcciones DDRAM porque no escribe en la segunda linea)
mi consulta es porqué al principio configura el setup en 8 bits y despues en 4???
al final en el hardware termina usando el de 4 pero no entiendo porque pone en principio 8
lee el busy flag
la pagina de donde lo saqué: http://patna.sancharnet.in/guria741/pic2lcd/pic2lcd.htm
a falta de un buen tuto que explique cómo controlar un lcd con un pic
estoy descifrando los programas ya hechos que encuentro en ensamblador
el siguiente código funciona (aunque creo que tiene un error en el número de direcciones DDRAM porque no escribe en la segunda linea)
mi consulta es porqué al principio configura el setup en 8 bits y despues en 4???
al final en el hardware termina usando el de 4 pero no entiendo porque pone en principio 8
lee el busy flag
la pagina de donde lo saqué: http://patna.sancharnet.in/guria741/pic2lcd/pic2lcd.htm
Código:
list p=PIC16F84A
include <P16F84A.INC>
;*******************************************
; 4 BIT LCD interface with PIC
; only port B is implemented
; RB7-RB4 = DB7-DB4 ; RB3=E ; RB2=RW ; RB1=RS
;*******************************************
;decleration
BIT_E EQU 3
BIT_RW EQU 2
BIT_RS EQU 1
TEMP EQU 0x020 ;TEMP STORAGE
V_DLY EQU 0x021 ; Variable for DLY
V_DLY1 EQU 0x022 ; for DLY1
org 0h ;start of program at
goto START
;initialise
INITPIC
bsf STATUS,RP0 ;sellect bank 1
movlw b'00000000'
movwf TRISB ;set as output
bcf STATUS,RP0 ;select bank 0
clrf PORTB
return
INITLCD ;INITIALIZE LCD
MOVLW 0xFE ;WAIT LONG '11111110'
CALL DLY1 ;254 * 0.5 = DELAY OF 127ms
;BUSY FLAG CAN'T BE CHECKED RIGHT NOW
MOVLW B'00111000' ;FUNCTION SET - 8 BIT, BIT_E = HIGH
MOVWF PORTB
BCF PORTB,BIT_E ; BIT_E = LOW
MOVLW 0x0A ;wait for about 5ms
CALL DLY1
MOVLW B'00111000' ;FUNCTION SET - 8 BIT, BIT_E=HIGH
MOVWF PORTB
BCF PORTB,BIT_E ;00001000 => 00000000
MOVLW 0x02 ;
CALL DLY1
MOVLW B'00111000' ;FUNCTION SET - 8 BIT, BIT_E = high
MOVWF PORTB
BCF PORTB,BIT_E ;BIT_E=LOW
;above i have done same command 3 times, this may be not necessary, i just followed datasheet
CALL LCDBUSY ;BUSY FLAG CAN BE CHECKED NOW!
MOVLW B'00101000' ;FUNCTION SET - 4 BIT ,BIT_E = HIGH
MOVWF PORTB
BCF ORTB,BIT_E
;..........EVERY INSTRUCTION WILL BE OF 2 CYCLE FROM HERE
CALL LCDBUSY ;..FUNCTION SET..
MOVLW B'00101000'
MOVWF PORTB
BCF PORTB,BIT_E ;1 CYCLE COMPLETE
MOVLW B'10001000'
MOVWF PORTB
BCF PORTB,BIT_E ;2 CYCLE
CALL LCDBUSY ;DISPLAY CONTROL -
MOVLW B'00001000' ; 1ST NIBBLE AND BIT_E=1,BIT_RW=0,BIT_RS=0
MOVWF PORTB
BCF PORTB,BIT_E ;1 CYCLY
MOVLW B'11111000' ;DISPLAY CONTROL NIBBLE (DISP=ON,CURSOR=ON,BLINK=ON) AND BIT_E=1,BIT_RW=0,BIT_RS=0
MOVWF PORTB
BCF PORTB,BIT_E ;2 CYCLE
CALL LCDBUSY ;CLEAR DISPLAY AND HOME CURSOR
MOVLW B'00001000'
MOVWF PORTB
BCF PORTB,BIT_E
MOVLW B'00011000'
MOVWF PORTB
BCF PORTB,BIT_E
CALL LCDBUSY ;ENTRY SET -
MOVLW B'00001000' ; BIT_E=1,BIT_RW=0,BIT_RS=0
MOVWF PORTB
BCF PORTB,BIT_E ;1 CYCLE
MOVLW B'01101000' ;ENTRY SET - INCREMENT,NO DISP SHIFT(CUR SHIFT),BIT_E=1,BIT_RW=0,BIT_RS=0
MOVWF PORTB
BCF PORTB,BIT_E ;2 CYCLE
RETURN
LCDBUSY
BSF STATUS,RP0 ;SELLECT BANK 1
MOVLW B'11110000'
MOVWF TRISB ;SET RB7-RB4 INPUT
BCF STATUS,RP0 ;SELLECT BANK 0
BSF PORTB,BIT_RW ; leer
BCF PORTB,BIT_RS , a registro de control
BSF PORTB,BIT_E
MOVF PORTB,W ;READ
BCF PORTB,BIT_E ;1 CYCLE complete
BSF PORTB,BIT_RW
BCF PORTB,BIT_RS
BSF PORTB,BIT_E
NOP ;DO NOTTHING COZ BUSY FLAG IS IN FIRST NIBBLE
BCF PORTB,BIT_E ;2nd CYCLE complete
ANDLW 0x80
BTFSS STATUS,Z ;CHECK BUSY
GOTO LCDBUSY ;LOOP IF BUSY
BCF PORTB,BIT_RW ;**
BSF STATUS,RP0 ;NOT BUSY SO MAKE PORT B O/P
MOVLW 0x000
MOVWF TRISB
BCF STATUS,RP0
RETURN
;LCD COMMANDS--- i have written routines for only 2 basic commands,
; one has to write routines for shifting display/crussor, home crussor etc.
;it's easy just follow datasheet and i'll include it someday!
LINE2 ;by selecting DDRAM address = 0x40 in case of 16x4 line LCD, see datasheet of HD44780
MOVLW B'11001000'
MOVWF PORTB
BCF PORTB,BIT_E
MOVLW B'00001000'
MOVWF PORTB
BCF PORTB,BIT_E
RETURN
LCDWRITE ;Writes data/character in W register to sellected CG/DD RAM, see its use in START routine
MOVWF TEMP
CALL LCDBUSY
MOVF TEMP,W
ANDLW B'11110000'
IORLW B'00001010' ;BIT_E=1,BIT_RW=0,BIT_RS=1
MOVWF PORTB
BCF PORTB,BIT_E ;1 CYCLE COMPLETE
SWAPF TEMP,W ;SWAP NIBBLES AND STORE IN W REGISTER
ANDLW B'11110000'
IORLW B'00001010' ;BIT_E=1,BIT_RW=0,BIT_RS=1
MOVWF PORTB
BCF PORTB,BIT_E ;2 CYCLE COMPLETE
RETURN
;Delay routines
;500uS delay with 4MHz
DLY
MOVLW D'165' ;
MOVWF V_DLY
DLY_LOOP
DECFSZ V_DLY, F
GOTO DLY_LOOP
RETURN
; w times DLY
DLY1
MOVWF V_DLY1 ; 0xFE WAIT LONG '11111110'
DLY1_LOOP
CALL DLY
DECFSZ V_DLY1, F
GOTO DLY1_LOOP
RETURN
START
CALL INITPIC ;initialize PIC
CALL INITLCD ;initialize LCD
MOVLW D'72' ;H ;Write to DDRAM which is displayed in LCD, DDRAM already sellected at initialization
CALL LCDWRITE
MOVLW D'69' ;E
CALL LCDWRITE
MOVLW D'76' ;L
CALL LCDWRITE
MOVLW D'76' ;L
CALL LCDWRITE
MOVLW D'79' ;O
CALL LCDWRITE
MOVLW D'32' ; 0x20 space
CALL LCDWRITE
MOVLW D'87' ;W
CALL LCDWRITE
MOVLW D'79' ;O
CALL LCDWRITE
MOVLW D'82' ;R
CALL LCDWRITE
MOVLW D'76' ;L
CALL LCDWRITE
MOVLW D'68' ;D
CALL LCDWRITE
MOVLW D'33' ;!
CALL LCDWRITE
CALL LINE2 ;set crussor to line 2
MOVLW D'76' ;L
CALL LCDWRITE
MOVLW D'73' ;I
CALL LCDWRITE
MOVLW D'78' ;N
CALL LCDWRITE
MOVLW D'69' ;E
CALL LCDWRITE
MOVLW D'32' ;space
CALL LCDWRITE
MOVLW D'50' ;2
CALL LCDWRITE
LOOP NOP
GOTO LOOP ;endless loop
END