;*************************************************************************** ; ; 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