کد:
;***************************************************************************
;
; File Name :'lcd4.asm"
; Title :HD44xx kompatibilis LCD Driver (I/O Port)
; Date :2003.10.28.
; Version :1.0.0
; Support telephone :+36-70-333-4034, old: +36-30-9541-658 VFX
; Support fax :
; Support Email :info@vfx.hu
; Target MCU :ATmega128
;
;***************************************************************************
; D E S C R I P T I O N
;
; http://home.iae.nl/users/pouweha/lcd/lcd.shtml
;
; Support 2x16 char LCD
;
;***************************************************************************
; M O D I F I C A T I O N H I S T O R Y
;
;
; rev. date who why
; ---- ---------- --- ------------------------------------
; 0.01 2003.10.28 VFX Creation
;
;***************************************************************************
;Hardware
;***************************************************************************
;*
;* SYSCLK: f=16.000 MHz (T= 62.5 ns)
;*
;***************************************************************************
;
;
;**************************************************************************
;* Hardware Def.
;
;***************************************************************************
.equ LCDRS_PORT=PORTD ;LCD Register Select
.equ LCDRS_DIR=DDRD ;Register Select 1=data 0=command
.equ LCDRS=0
.equ LCDRW_PORT=PORTD ;LCD Read/Write
.equ LCDRW_DIR=DDRD ;0=write to display, 1= read from display
.equ LCDRW=1
.equ LCDEN_PORT=PORTD ;LCD Enable
.equ LCDEN_DIR=DDRD ;Enable - data clocked on falling edge
.equ LCDEN=4
.equ LCDDAT_PORT=PORTF ;LCD Data PortF[3..0]
.equ LCDDAT_DIR=DDRF
.equ LCDDAT_PIN=PINF
.equ LCDDAT_Mask=0b00001111
;***************************************************************************
;**** VARIABLES
.DSEG
;***************************************************************************
.ESEG
;***************************************************************************
;**** CODE SEG
;***************************************************************************
.CSEG
;*****************************************************
;** Wait1ms
;**
;** In: R16 - 16*1ms varakozas
;**
;** Out: -
;**
;**
;** Alt R16
;**
;** Description: wating for R16 * 1 ms
;*
Wait1ms:
ldi XL,low(SYSCLK/(5*1000))
ldi XH,high(SYSCLK/(5*1000))
Waitx1: sbiw XL,1 ;[2] \
nop ;[1] - 5 cycles in loop
brne Waitx1 ;[2] /
dec R16
brne Wait1ms
ret
;*****************************************************
;** LCD_pulseE
;**
;** In: -
;**
;** Out: R0 - Data on LCDDat pin
;**
;**
;** Alt
;**
;** Description: Generate ENABLE signal to LCD
;*
LCD_pulseE:
sbi LCDEN_PORT,LCDEN ;Enable high
nop ;Wait 500ns @16MHz
nop
nop
nop
nop
nop
nop
nop
in R0,LCDDAT_PIN
cbi LCDEN_PORT,LCDEN ;Enable low, latch data
ret
;*****************************************************
;** LCD_Init
;**
;** In: -
;**
;** Out: -
;**
;**
;** Alt:
;**
;** Description: Initialize LCD in 4 bit mode
;*
LCD_Init:
sbi LCDEN_DIR,LCDEN ;LCD I/O Disabled
cbi LCDEN_PORT,LCDEN
sbi LCDRS_DIR,LCDRS ;Sel. LCD Command Register
cbi LCDRS_PORT,LCDRS
sbi LCDRW_DIR,LCDRW ;LCD Write mode
cbi LCDRW_PORT,LCDRW
ldi R16,LCDDAT_Mask ;LCD Data lines outputs
sts LCDDAT_DIR,R16
ldi R16,0 ;All zeros
sts LCDDAT_PORT,R16
ldi R16,15 ;Wait at least 15msec after
rcall Wait1ms ;powerup before writing to display
;tuti ami tuti legyen 250ms
; Put the LCD in 8-bit mode. Even though we want the display to
; operate in 4-bit mode, the only way to guarantee that our commands
; are aligned properly is to initialize in 8-bit. (The user might have
; hit reset between nibbles of a dual 4-bit cycle.)
lds R16,LCDDAT_PORT
andi R16,255-LCDDAT_PORT
ori R16,0b00000011 ;3x probalkozunk 8 bit mode-ba rakni
sts LCDDAT_PORT,R16
nop
nop
cbi LCDRS_PORT,LCDRS ;Set to Command Reg.
cbi LCDRW_PORT,LCDRW ;read
rcall LCD_pulseE ;1
ldi R16,15
rcall Wait1ms ;wait 5ms
cbi LCDRS_PORT,LCDRS ;Set to Command Reg.
cbi LCDRW_PORT,LCDRW ;read
rcall LCD_pulseE ;2
ldi R16,5
rcall Wait1ms ;wait 5ms
cbi LCDRS_PORT,LCDRS ;Set to Command Reg.
cbi LCDRW_PORT,LCDRW ;read
rcall LCD_pulseE ;3
ldi R16,5
rcall Wait1ms ;wait 5ms
; Now it's safe to go into 4-bit mode.
lds R16,LCDDAT_PORT
andi R16,255-LCDDAT_PORT
ori R16,0b00000010 ;4bit bus mode
sts LCDDAT_PORT,R16
rcall LCD_pulseE
ldi R16,5
rcall Wait1ms ;wait 5ms
; *** Send the 'FUNCTION SET' command
; +------ Data: 0 = 4-bit; 1 = 8-bit
; |+----- Lines: 0 = 1; 1 = 2
; ||+---- Font: 0 = 5x8; 1 = 5x11
ldi R16,0b00101000
rcall LCD_SendCmd
; *** Send the 'CURSOR/DISPLAY SHIFT' command
; +----- S/C: 0 = cursor; 1 = display
; |+---- R/L: 0 = left; 1 = right
ldi R16,0b00010100
rcall LCD_SendCmd
; *** Send the 'ENTRY MODE' command
; +--- Direction: 0 = left; 1 = right
; |+-- Shift Dislay: 0 = off; 1 = on
ldi R16,0b00000110
rcall LCD_SendCmd
; *** Send the 'DISPLAY ON/OFF' command
; +---- Display: 0 = off; 1 = on
; |+--- Cursor: 0 = off; 1 = on
; ||+-- Blink: 0 = off; 1 = on
ldi R16,0b00001100
rcall LCD_SendCmd
rcall LCD_Clear
ret
;*****************************************************
;** LCD_Clear
;**
;** In: -
;**
;** Out: -
;**
;**
;** Alt:
;**
;** Description:
;** Clears the display and sends the cursor home.
;
LCD_Clear:
ldi R16,0b00000001 ;Clear LCD
rcall LCD_SendCmd
ldi R16,0b00000010 ;Send the cursor home
rcall LCD_SendCmd
ret
;*****************************************************
;** LCD_WaitBusy
;**
;** In: -
;**
;** Out: -
;**
;**
;** Alt: R0, R16
;**
;** Description:
;** Waits for the busy flag to go low. Since we're in 4-bit mode,
;** the register has to be read twice (for a total of 8 bits).
;*
LCD_WaitBusy:
push R16
lds R16,LCDDAT_DIR
andi R16,255-LCDDAT_Mask ;LCD data bits going to input
sts LCDDAT_DIR,R16
lds R16,LCDDAT_PORT
ori R16,LCDDAT_Mask ;pull-up
sts LCDDAT_PORT,R16
rjmp LCDWait1
LCDWait0:
ldi R16,2 ;Wait min. ~1us
LCDWait01: nop
dec R16
brne LCDWait01
LCDWait1:
cbi LCDRS_PORT,LCDRS ;Set to Command Reg.
sbi LCDRW_PORT,LCDRW ;read
rcall LCD_pulseE ;Busy Flag read bit 7.
mov R16,R0
rcall LCD_pulseE ;lower nibble must read
sbrc R16,3 ;Check busy flag
rjmp LCDWait0
lds R16,LCDDAT_DIR ;LCD Data lines outputs
ori R16,LCDDAT_Mask
sts LCDDAT_DIR,R16
lds R16,LCDDAT_PORT
andi R16,255-LCDDAT_Mask ;All zero
sts LCDDAT_PORT,R16
pop R16
ret
;*****************************************************
;** LCD_SendCmd
;**
;** In: R16 - Command byte
;**
;** Out: -
;**
;**
;** Alt: R0, R1, R16, R17
;**
;** Description:
;** Routine to write a command to the instruction register.
;
LCD_SendCmd:
rcall LCD_WaitBusy
mov R1,R16
swap R16
andi R16,LCDDAT_Mask ;send upper nibble first
lds R17,LCDDAT_PORT
andi R17,255-LCDDAT_Mask
or R17,R16
sts LCDDAT_PORT,R17
cbi LCDRS_PORT,LCDRS ;Set to Command Reg.
cbi LCDRW_PORT,LCDRW ;Write
rcall LCD_PulseE ;Latch upper nibble
mov R16,R1
andi R16,LCDDAT_Mask ;send lower nibble
lds R17,LCDDAT_PORT
andi R17,255-LCDDAT_Mask
or R17,R16
sts LCDDAT_PORT,R17
cbi LCDRS_PORT,LCDRS ;Set to Command Reg.
cbi LCDRW_PORT,LCDRW ;Write
rcall LCD_PulseE ;Latch lower nibble
ret
;*****************************************************
;** LCD_SendChar
;**
;** In: R16 - character code
;**
;** Out: -
;**
;**
;** Alt: R0,R1, R16, R17
;**
;** Description:
;** Routine to write a character to the data register.
;
LCD_SendChar:
rcall LCD_WaitBusy
mov R1,R16
swap R16
andi R16,LCDDAT_Mask ;send upper nibble first
lds R17,LCDDAT_PORT
andi R17,255-LCDDAT_Mask
or R17,R16
sts LCDDAT_PORT,R17
sbi LCDRS_PORT,LCDRS ;Set to data Reg.
cbi LCDRW_PORT,LCDRW ;Write
rcall LCD_PulseE ;Latch upper nibble
mov R16,R1
andi R16,LCDDAT_Mask ;send lower nibble
lds R17,LCDDAT_PORT
andi R17,255-LCDDAT_Mask
or R17,R16
sts LCDDAT_PORT,R17
sbi LCDRS_PORT,LCDRS ;Set to Data Reg.
cbi LCDRW_PORT,LCDRW ;Write
rcall LCD_PulseE ;Latch lower nibble
ret
;*****************************************************
;** LCD_Goto
;**
;** In: R16 - position
;** 0x00 - 1.row, 1.col
;** 0x40 - 1.row, 2.col
;**
;** Out: -
;**
;**
;** Alt: R0, R1, R16, R17
;**
;** Description:
;**
;
LCD_Goto:
ori R16,0b10000000 ;Set address Command
rcall LCD_SendCmd
ret
;*****************************************************
;** LCD_PrnFLASHStr
;**
;** In: Z+RAMP - start address of string
;**
;** Out: -
;**
;**
;** Alt: R0, R1, R16, R17
;**
;** Description:
;** Print a null terminated string to LCD
;
LCD_PrnFLASHStr:
elpm R16,Z+
tst R16
breq LCD_PrnFLSH0
rcall LCD_SendChar
rjmp LCD_PrnFLASHStr
LCD_PrnFLSH0:
ret