Path:AVR-EN => Applications => LCD experimental board => Include routines assembler source code
tn24_lcd experimental board small Applications of
AVR single chip controllers AT90S, ATtiny, ATmega and ATxmega
Experimental board with an ATtiny24/44/84 and an LCD
Logo

LCD include routines in assembler for the ATtiny24/44/84 experimental board

Source code-Link: here. Please note that this version of the source code is adjusted to a 4x20 LCD.

;
; ************************************************
; * Include code for 4-bit-access to an LCD      *
; * in busy flag mode, with base routines        *
; * (C)2018 by www.avr-asm-tutorial.net          *
; ************************************************
;
; This include code provides basic routines to access
; a an LCD on an ATtiny24/44/84 in 4 bit busy mode
; and uses a 4 bit wide bidirectional data bus.
; The routine LcdInit
; - initiates the portbits and the LCD,
; - displays an init message output on the LCD,
; - waits for a period of cLcdDelay's (in 250 ms), and
; - displays an output mask on the LCD.
; Both messages to be displayed are created at the
; end of this include file and can be changed. The
; size of the LCD (rows, columns) can be configured
; here. 
;
; --------- Select the LCD size here -------------
;
.equ cLcdLines = 4 ; Number of lines of the LCD (1/2/4)
.equ cLcdColumns = 20 ; Number of char per line (8/16/20/24)
;
; -- The used ports and pins to interface the LCD --
;
; (Do not change unless you change the hardware)
;
; LCD control port
.equ pLcdCO   = PORTB  ; LCD control port, output
.equ pLcdCD   = DDRB   ; LCD control port, direction
.equ bLcdCOE  = PORTB2 ; LCD Enable pin, output
.equ bLcdCDE  = DDB2   ; LCD Enable pin, direction
.equ bLcdCORS = PORTB0 ; LCD RS pin, output
.equ bLcdCDRS = DDB0   ; LCD RS pin, direction
.equ bLcdCORW = PORTB1 ; LCD R/W pin, output
.equ bLcdCDRW = DDB1   ; LCD R/W pin, direction
; LCD data port
.equ pLcdDO   = PORTA  ; LCD data port, output
.equ pLcdDI   = PINA   ; LCD data port, input
.equ pLcdDD   = DDRA   ; LCD data port, direction
.equ mLcdDRW  = 0xF0   ; LCD data port, write mask
.equ mLcdDRR  = 0x0F   ; LCD data port, read mask
;
; ------------ Used registers -------------------
;
; The following register is to be defined in the
; main program:
;
; rmp (from R16 upwards)
;
; ---- Provides the following base routines -----
;
; Register: Chgd: Register used, content not preserved
;           Used: Register used but content preserved
;
; Routine  Provides     Calling parameters   Register
; -------  ------------ -------------------- ----------
; LcdInit  Init LCD     None                 rmp:Chgd
;                                            ZH:ZL:Chgd
; LcdText  Display the  ZH:ZL=2*Text table   rmp:Chgd
;          text in      0D=Next line         R0,R1:Used
;          flash memory FF=Ignore            ZH:ZL:Chgd
;          from line 1  FE=End of text table
;          on
; LcdTextC Display the  (see LcdText)        (see LcdText)
;          text in flash
;          at the current
;          position
; LcdSRam  Display the  XH:XL:points to      rmp:Chgd
;          text in SRAM       text in SRAM   XH:XL:Chgd
;                       ZH:ZL:LCD position   ZH:ZL:Chgd
;                             ZH:line(0..3)
;                       rmp:number of chars  R0:Used
; LcdPos   Set LCD po-  ZH: Line 0..3        rmp:Chgd
;          position     ZL: Column 0..
;                           cLcdColumns-1     
; LcdLine  Set LCD po-  rmp: Line (0..3)     rmp:Chgd
;          sistion to
;          line (col=0)
; LcdLineN Set LCD po-  N: Line 1..4         rmp:Chgd
;          sition to
;          line N,
;          column=0
; LcdChar  Display char rmp:ASCII char       rmp:Chgd
;                                            ZL:Used
; LcdCtrl  Output LCD   rmp: Control byte    rmp:Chgd
;          control byte                      ZL:Used
; LcdChars Generate     ZH:ZL: 2*char table  rmp:Chgd
;          special chars                     R0,R1:Used
;          on LCD                            ZH:ZL:Chgd
;
; ---------- Optional routines -----------
;
; Number conversion from binary to ... and display
; If switched on: the following routines are provided:
;
; Switch    Routine  Provides     Input     Register
; --------  -------- ------------ --------- --------
; sLcdDec8  LcdDec8  8 bit bin to rmp:bin   rmp:Chgd
;                    decimal (3             R0,R1,ZL:
;                    digits)                  Used
; sLcdDec16 LcdDec16 16 bit bin   ZH:ZL:    rmp:Chgd
;                    zu Dezimal     bin     R0,R1,R2:
;                    (5 digits)               Used
; sLcdHex8  LcdHex8  8 bit bin to rmp:bin   rmp:Chgd
;                    hex (2 hex
;                    digits)
; sLcdHex16 LcdHex16 16 bit bin   ZH:ZL:    rmp:Chgd
;                    to hex (4      bin
;                    hex digits)
; sLcdBin8  LcdBin8  8 bit bin    rmp:bin   rmp:Chgd
;                    to binary              ZH:ZL:Used
;                    (8 digits)
; sLcdBin16 LcdBin16 16 bit bin   ZH:ZL:    rmp:Chgd
;                    to binary      bin     ZH:ZL:Used
;                    (16 digits)
;
; --------- LCD access init ----------
;
LcdInit:
  ; Init I/O ports and pins
  cbi pLcdCO,bLcdCOE ; Enable pin = 0
  sbi pLcdCD,bLcdCDE ; Enable pin = output
  cbi pLcdCO,bLcdCORS ; RS pin = 0
  sbi pLcdCD,bLcdCDRS ; RS pin = output
  cbi pLcdCO,bLcdCORW ; RW pin = 0
  sbi pLcdCD,bLcdCDRW ; RW pin = output
  in rmp,pLcdDD ; Read direction bits data port
  ori rmp,mLcdDRW ; Data port write mask, pins to output
  out pLcdDD,rmp ; to data port direction
  ; Wait for 50 ms until the LCD is ready
  rcall Wait50ms ; delay time 50 ms
  ; Set LCD to 8 bit mode (three times)
  ldi rmp,0x30 ; 8 bit mode control byte
  rcall LcdC8Byte ; Write in 8 bit mode
  rcall Wait5ms ; Wait 5 ms
  ldi rmp,0x30
  rcall LcdC8Byte
  rcall Wait5ms
  ldi rmp,0x30
  rcall LcdC8Byte
  rcall Wait5ms
  ; Switch to 4 bit mode  
  ldi rmp,0x20 ; Control byte 4 bit mode
  rcall LcdC8Byte ; to LCD control
  rcall Wait5ms ; Wait for 5 ms
  ; Size control of the LCD
  .if cLcdLines == 1
    ldi rmp,0x20 ; 4 bit mode, single line, 5*7
    .else
    ldi rmp,0x28 ; 4 bit mode, multiple lines, 5*7
    .endif
  rcall LcdCtrl ; Byte to control LCD
  ldi rmp,0x0F ; Display on, blink cursor
  rcall LcdCtrl ; Byte to control LCD
  ldi rmp,0x01 ; Display clear
  rcall LcdCtrl ; Byte to control LCD
  ldi rmp,0x06 ; Autoindent on
  rcall LcdCtrl ; Byte to control LCD
  ldi ZH,High(2*LcdTxtInit) ; Display init text
  ldi ZL,Low(2*LcdTxtInit)
  rcall LcdText ; Display text from line 1 on
  ldi rmp,0x0C ; Cursor and blink off
  rcall LcdCtrl ; Byte to control LCD
  ldi rmp,5*cLcdDelay ; Load delay constant
LcdInit1:
  rcall Wait50ms ; Wait 50 ms
  dec rmp
  brne LcdInit1
  ldi ZH,High(2*LcdTxtMsk) ; Display output mask
  ldi ZL,Low(2*LcdTxtMsk)
  rcall LcdText ; Display text on LCD from line 1 on
  ldi rmp,0x0C ; Cursor and blink off
  rcall LcdCtrl ; Byte to control LCD
  ret
;
; Display text in flash from line 1 on
;   Z points to 2*address in flash
;   Control characters:
;     0xFE: End of text
;     0xFF: Dummy character (not displayed)
;     0x0D: Next line
;
LcdText:
  rcall LcdLine1 ; To line 1
LcdTextC: ; Display text in flash from current position on
  push R0 ; Save R0
  clr R0 ; R0 is line counter
LcdText1:
  lpm rmp,Z+ ; Read character from flash
  cpi rmp,0xFE ; End of text?
  breq LcdTextRet ; yes, return
  cpi rmp,0xFF ; Dummy character?
  breq LcdText1 ; yes, display next character
  cpi rmp,0x0D ; Carriage return/line feed?
  brne LcdText2 ; No
  inc R0 ; Next line
  mov rmp,R0 ; Display to next line
  cpi rmp,cLcdLines ; End of lines of the LCD?
  brcc LcdTextRet ; Yes, return
  rcall LcdLine ; Start at next line
  rjmp LcdText1 ; continue writing characters
LcdText2: ; Display character
  rcall LcdChar ; Display single character
  rjmp LcdText1 ; and continue reading from flash
LcdTextRet:
  pop R0 ; Restore R0
  ret ; Done
;
; Display text in SRAM on LCD
;   ZH = Line 0..3; ZL = Column 0..cLcdColumns-1,
;   XH:XL = Address in SRAM, rmp: Number of characters
;
LcdSram:
  push R0 ; Save R0
  mov R0,rmp ; Copy number of characters
  rcall LcdPos ; Set LCD position to ZH:ZL
LcdSram1:
  ld rmp,X+ ; Read character from SRAM
  rcall LcdChar ; Display character on LCD
  dec R0 ; Count downwards
  brne LcdSram1 ; More characters?
  pop R0 ; No, restore R0
  ret ; Done
;
; Set the LCD cursor to the line start of line rmp
;   Line: rmp 0..cLcdLines-1 
LcdLine:
  cpi rmp,1 ; Line 2?
  brcs LcdLine1 ; no, to line 1
.if cLcdLines > 1 ; only if cLcdLines 2 or 4
  breq LcdLine2 ; To line 2
  .if cLcdLines > 2 ; only if cLcdLines = 4
    cpi rmp,2 ; Line 3?
    breq LcdLine3 ; To line 3
    .if cLcdLines > 3 ; only if cLcdLines = 4
      rjmp LcdLine4 ; To line 4
	  .endif
    .endif
  .endif
LcdLine1:
  ldi rmp,0x80 ; Line 1
  rjmp LcdCtrl ; To control LCD
.if cLcdLines > 1 ; Only if cLcdLines 2 or 4
  LcdLine2:
    ldi rmp,0xC0 ; Line 2
    rjmp LcdCtrl ; To control LCD
  .if cLcdLines > 2 ; Only if cLcdLines = 4
    LcdLine3:
      ldi rmp,0x80+cLcdColumns ; Line 3
      rjmp LcdCtrl ; To control LCD
    .if cLcdLines > 3 ; Only if cLcdLines = 4
      LcdLine4:
        ldi rmp,0xC0+cLcdColumns ; Line 4
        rjmp LcdCtrl ; To control LCD
      .endif
    .endif
  .endif
  ret
;
; Set the LCD's cursor to the position ZH:ZL
;   ZH is line (0..3), ZL is column
;
LcdPos:
  ldi rmp,0x80 ; Position = line 1
  cpi ZH,1 ; Line 2?
  brcs LcdPos1 ; Line = 1
  ldi rmp,0xC0 ; Position = line 2
  breq LcdPos1 ; Line = 2
  ldi rmp,0x80+20 ; Position = line 3
  cpi ZH,2 ; Line 3?
  breq LcdPos1 ; Line = 3
  ldi rmp,0xC0+20 ; Line = 4
LcdPos1:
  add rmp,ZL ; Add column
  rjmp LcdCtrl ; To control LCD
;
; Define special characters
;   ZH:ZL points to character table address * 2
;   Used: R0,R1 (content restored)
;   Chgd: rmp
;
LcdChars:
  push R0 ; Save R0
  push R1 ; Save R1
LcdChars1:
  lpm ; Read character address from table
  tst R0 ; Check end of table
  breq LcdChars3 ; Done
  adiw ZL,2 ; Ignore second byte
  ldi rmp,8 ; Each character has eight bytes
  mov R1,rmp ; Copy to R1
LcdChars2:
  mov rmp,R0 ; Set character address in LCD
  rcall LcdCtrl ; Control to LCD
  lpm rmp,Z+ ; Read character data
  rcall LcdChar ; Write character data to LCD
  inc R0 ; Increase address
  dec R1 ; Count downwards
  brne LcdChars2 ; Still data
  rjmp LcdChars1 ; next character from table
LcdChars3:
  pop R1 ; Restore R1
  pop R0 ; Restore R0
  ret ; Done
;
; Macro LcdEDly provides delay for Enable pin active
;   Depends on clock frequency
;
.Macro LcdEDly
  nop ; Wait one clock cycle
  .if clock > 1000000 ; Clock larger than 1 MHz
    nop ; Wait another clock cycle
    .if clock > 2000000 ; Clock larger than 2 MHz
      nop ; Wait another two cycles
      nop
      .if clock > 4000000 ; Clock larger than 4 MHz
        nop ; Wait another four clock cycles
        nop
        nop
        nop
        .endif
      .endif
    .endif
  .endm
;
; Data byte ouptut in 4 bit mode
;   Data byte in rmp
;
LcdChar:
  rcall LcdBusy ; Wait until LCD is not busy any more
  sbi pLcdCO,bLcdCORS ; Set RS pin
  rjmp Lcd4Byte ; Output byte in rmp
;
; Control byte output to LCD in 4 bit mode
;   Data byte in rmp
;
LcdCtrl:
  rcall LcdBusy ; Wait until LCD is not busy any more
  cbi pLcdCO,bLcdCORS ; Clear RS pin
;
; Output byte in 4 bit mode to LCD
;   Data in rmp
;   Uses ZL but restores content
;
Lcd4Byte:
  push ZL ; Save ZL
  push rmp ; Byte in rmp to stack
  andi rmp,0xF0 ; Clear lower nibble
  in ZL,pLcdDO ; Read current input port
  andi ZL,0x0F ; Clear upper nibble of input
  or rmp,ZL ; Combine upper and lower nibble
  out pLcdDO,rmp ; Write to data port of the LCD
  nop ; Wait for one clock cycle
  sbi pLcdCO,bLcdCOE ; Enable pin of the LCD
  LcdEDly ; Add delay
  cbi pLcdCO,bLcdCOE ; Clear Enable pin of the LCD
  pop rmp ; Restore byte
  andi rmp,0x0F ; Clear upper nibble
  swap rmp ; Swap nibbles
  or rmp,ZL ; Combine upper and lower nibble
  out pLcdDO,rmp ; Write to data port of the LCD
  nop ; Wait for one clock cycle
  sbi pLcdCO,bLcdCOE ; Enable pin of the LCD
  LcdEDly ; Add delay
  cbi pLcdCO,bLcdCOE ; Clear Enable pin of the LCD
  pop ZL ; Restore ZL
  ret ; Done
;
; Wait until the busy bit of the LCD is clear
;   Uses rmp and ZL, content is restored 
;
LcdBusy:
  push ZL ; Save ZL
  push rmp ; Save rmp
  in rmp,pLcdDD ; Read direction register of data port
  andi rmp,mLcdDRR ; Clear the direction bits of the data port
  out pLcdDD,rmp ; To direction register of data port
  cbi pLcdCO,bLcdCORS ; Clear RS pin of the LCD
  sbi pLcdCO,bLcdCORW ; Set R/W pin of the LCD
LcdBusy1:
  sbi pLcdCO,bLcdCOE ; Activate LCD Enable pin
  LcdEDly ; Add delay
  in ZL,pLcdDI ; Read upper nibble of LCD answer
  cbi pLcdCO,bLcdCOE ; Clear LCD Enable pin
  andi ZL,0xF0 ; Clear lower nibble of data port input
  sbi pLcdCO,bLcdCOE ; Activate LCD Enable pin
  LcdEDly ; Add delay
  in rmp,pLcdDI ; Read lower nibble of LCD answer
  cbi pLcdCO,bLcdCOE ; Clear LCD Enable pin
  andi rmp,0xF0 ; Clear lower nibble of data port input
  swap rmp ; Swap upper/lower nibble
  or ZL,rmp ; Combine upper and lower nibble of LCD answer
  sbrc ZL,7 ; Skip next instruction if busy=0
  rjmp LcdBusy1 ; Repeat until busy=0
  cbi pLcdCO,bLcdCORW ; Clear R/W pin
  in rmp,pLcdDD ; Read direction register of data port 
  ori rmp,mLcdDRW ; Set LCD data port pins output
  out pLcdDD,rmp ; To direction port
  pop rmp ; Restore rmp
  pop ZL ; Restore ZL
  ret ; Done
;
; Control byte to LCD in 8 bit mode
;   Data byte in rmp
;   Uses ZL, restores content
;
LcdC8Byte:
  cbi pLcdCO,bLcdCORS ; Clear RS pin
  andi rmp,0xF0 ; Clear lower nibble
  in ZL,pLcdDO ; Read data output port
  andi ZL,0x0F ; Clear upper nibble of port
  or rmp,ZL ; Combine upper and lower nibble
  out pLcdDO,rmp ; To data port direction
  nop ; Wait one clock cycle
  sbi pLcdCO,bLcdCOE ; Activate LCD Enable pin
  LcdEDly ; Add delay
  cbi pLcdCO,bLcdCOE ; Clear LCD Enable pin
  ret ; Done
;
; ------- Optional routines ------------
;
; Convert and display 8 bit decimal at current position
;   Switch: sLcdDec8
;   Parameter: 8 bit binary in rmp
.ifdef sLcdDec8 ; only if switch is on
  LcdDec8:
    push ZL ; Save ZL
    push R0 ; Save R0
    push R1 ; Save R1
    clr ZL ; Clear ZL as leading zero suppressor
    mov R0,rmp ; Copy binary
    ldi rmp,100 ; Start with hundreds
    rcall LcdSub8 ; Subtract rmp from R0 until carry, output digit
    ldi rmp,10 ; Continue with tens 
    rcall LcdSub8 ; Subtract and display digit
    ldi rmp,'0' ; Add ASCII-Zero to remainder
    add rmp,R0 ; Last digit
    rcall LcdChar ; To LCD
    pop R1 ; Restore R1
    pop R0 ; Restore R0
    pop ZL ; Restore ZL
    ret ; Done
  LcdSub8:
    clr R1 ; R1 is counter
  LcdSub8a:
    sub R0,rmp ; Subtract from R0
    brcs LcdSub8b ; If carry set no more subtracting
    inc R1 ; Increase counter
    rjmp LcdSub8a ; Continue subtracting
  LcdSub8b:
    add R0,rmp ; Restore last subtracting
    ldi rmp,'0' ; Add ASCII zero to result
    add rmp,R1
    cpi rmp,'0' ; Check leading zero?
    brne LcdSub8c ; No more leading zero suppression
    sbrs ZL,0 ; Skip if no more leading zero suppression 
    ldi rmp,' ' ; Zero to blank
    rjmp LcdSub8d ; Display character on LCD
  LcdSub8c:
    ldi ZL,1 ; Switch leading zero suppression off
  LcdSub8d:
    rcall LcdChar ; Display digit character
    ret ; Done
  .endif
;
; Convert and display 16 bit decimal on current position
;    Switch: sLcdDec16
;    Call: LcdDec16
;    Parameter: ZH:ZL: binary
.ifdef sLcdDec16 ; Only if switch is on
  LcdDec16:
    push R0 ; Save R0
    push R1 ; Save R1
    push R2 ; Save R2
    mov R1,ZH ; Copy ZH:ZL to R1:R0
    mov R0,ZL
    clr R3 ; R3 Suppression of leading zeros
    ldi ZH,High(10000) ; Start with ten thousands
    ldi ZL,Low(10000)
    rcall LcdSub16 ; Subtract and display digit
    ldi ZH,High(1000) ; Continue with thousends
    ldi ZL,Low(1000)
    rcall LcdSub16 ; Subtract and display digit
    ldi ZH,High(100) ; Continue with hundreds
    ldi ZL,Low(100)
    rcall LcdSub16 ; Subtract and display digit
    ldi ZH,High(10) ; Continue with tens
    ldi ZL,Low(10)
    rcall LcdSub16 ; Subtract and display digit
    ldi rmp,'0' ; Rest to ASCII
    add rmp,R0
    rcall LcdChar ; And display last digit
    pop R2 ; Restore used registers
    pop R1
    pop R0
    ret ; Done
  LcdSub16:
    ldi rmp,'0' ; rmp is counter
  LcdSub16a:
    sub R0,ZL ; Subtract LSB decimal
    sbc R1,ZH ; dto., MSB with carry
    brcs LcdSub16b ; To digit display
    inc rmp ; Increase counter
    rjmp LcdSub16a ; Continue subtracting
  LcdSub16b:
    add R0,ZL ; Restore last subtraction
    adc R1,ZH
    cpi rmp,'0' ; Check zero
    breq LcdSub16c ; To zero
    inc R3 ; No more suppression
  LcdSub16c:
    tst R3 ; Suppres leading zeroes?
    brne LcdSub16d ; No
    ldi rmp,' ' ; Zero to blank
  lcdSub16d:
    rjmp LcdChar ; Display digit
  .endif
;
; Convert and display 16 bit binary on LCD
;   Switch: sLcdBin16
;   Call: LcdBit16
;   Parameter: ZH:ZL: binary
;   Register: uses and changes rmp
;
.ifdef sLcdBin16 ; Only if switched on
  .set sLcdBin8=1 ; Switch Bin8 on
  LcdBin16:
    mov rmp,ZH ; Copy MSB
    rcall LcdBin8 ; Display 8 bit binary
    mov rmp,ZL ; Copy LSB
    rjmp LcdBin8 ; Display 8 bit binary
    ret
  .endif
;
; Convert and display 8 bit binary on LCD
;   Switch: sLcdBin8
;   Call: LcdBin8
;   Parameter: rmp: binary
;   Register: uses and changes rmp
;             uses ZH and ZL and restores
;
.ifdef sLcdBin8 ; Only if switch is on
  LcdBin8:
    push ZH ; Save Z
    push ZL
    mov ZL,rmp ; Copy binary
    ldi ZH,8 ; Number of bits to be displayed
  LcdBin8a:
    ldi rmp,'0' ; Display a zero
    lsl ZL ; Shift highest bit to carry
    brcc LcdBin8b ; Display a zero
    ldi rmp,'1' ; Display a one
  LcdBin8b:
    rcall LcdChar ; Display a binary digit
    dec ZH ; Downcount bits
    brne LcdBin8a ; Continue
    pop ZL ; Restore Z
    pop ZH
    ret ; Done
  .endif
;
; Convert and display 16 bit hexadecimal
;   Switch: sLcdHex16
;   Parameter: 16 bit binary in ZH:ZL
;   Used and changed: rmp
;
.ifdef sLcdHex16
  .set sLcdNibble=1 ; Switch nibble display on
  .set sLcdHex8=1 ; Switch 8 bit hex on
  LcdHex16:
    mov rmp,ZH ; Copy MSB
    rcall LcdHex8 ; Convert and display 8 bit hex
    mov rmp,ZL ; Copy LSB
    rjmp LcdHex8 ; Convert and display 8 bit hex
  .endif
;
; Convert and display 8 bit hexadecimal
;   Switch: sLcdHex8
;   Parameter: 8 bit binary in rmp
.ifdef sLcdHex8
  .set sLcdNibble=1 ; Switch nibble display on
  LcdHex8:
    push rmp ; Save byte in rmp
    swap rmp ; Swap upper and lower nibble
    rcall LcdNibble ; Display lower nibble in hex
    pop rmp ; Restore byte
    rjmp LcdNibble ; Display lower nibble in hex
  .endif
;
; Converts and displays lower nibble in rmp in hex
.ifdef sLcdNibble ; Only if switched on
  LcdNibble:
    andi rmp,0x0F ; Isolate lower nibble
    subi rmp,-'0' ; Add ASCII-0
    cpi rmp,'9'+1 ; Digits A to F?
    brcs LcdNibble1 ; no
    subi rmp,-7 ; Add 7 for A to F
  LcdNibble1:
    rjmp LcdChar ; Display character in rmp on LCD
  .endif
;
; ------ Wait routines ------------------
;
; Wait 50ms delays execution by 50 ms. As
; at 8 MHz clock this would exceed the limits
; of a 16 bit counter, the delay routine is
; using two Wait calls in that case.
; 
Wait50ms: ; Wait for 50 ms
.equ c50ms = 50000
.equ n50ms = clock/1000000*(c50ms-16)/4
;   rcall: + 3
  push ZH ; + 2
  push ZL ; + 2
.if clock > 4000000
  ldi ZH,HIGH(n50ms/2)
  ldi ZL,LOW(n50ms/2)
Wait50ms1:
  sbiw ZL,1
  brne Wait50ms1
  ldi ZH,HIGH(n50ms/2)
  ldi ZL,LOW(n50ms/2)
  rjmp Wait
  .else
  ldi ZH,HIGH(n50ms) ; + 1
  ldi ZL,LOW(n50ms) ; + 1
  rjmp Wait ; + 2, total = 11
  .endif
;
Wait5ms: ; Wait routine 5 ms
.equ c5ms = 5000
.equ n5ms = clock/1000000*(c5ms-16)/4
  push ZH
  push ZL
  ldi ZH,HIGH(n5ms)
  ldi ZL,LOW(n5ms)
  rjmp Wait
;
; Wait routine for 4*Z+7 clock cycles
Wait: ; Wait loop, cycles = 4*(n-1)+11 = 4*n + 7
  sbiw ZL,1 ; + 2
  brne Wait ; + 1 / 2
  pop ZL ; + 2
  pop ZH ; +2
  ret ; + 4, Total (with rcall+ret) =4*n+18
;
; -------- Init message displays -------------
;
.if  cLcdColumns == 8
  LcdTxtInit:
    .db "tn24_lcd",0x0D,0xFF
    .db "avr-asm ",0x0D,0xFF
    .db "LcdInit ",0x0D,0xFF
    .db "-Start- ",0xFE,0xFE
  .endif
.if cLcdColumns == 16
  LcdTxtInit:
    .db "tn24_lcd modul01",0x0D,0xFF
    .db "avr-asm-tutorial",0x0D,0xFF
    .db "* Init - Phase *",0x0D,0xFF
    .db "(C)2018 DG4FAC  ",0xFE,0xFF
  .endif
.if cLcdColumns == 20
  LcdTxtInit:
    .db "tn24_lcd module V0.1",0x0D,0xFF
    .db "avr-asm-tutorial.net",0x0D,0xFF
    .db "  * Init - Phase *  ",0x0D,0xFF
    .db " (C)2018 by DG4FAC  ",0xFE,0xFF
  .endif
.if cLcdColumns == 24
  LcdTxtInit:
    .db "  tn24_lcd module V 0.1 ",0x0D,0xFF
    .db "  avr-asm-tutorial.net  ",0x0D,0xFF
    .db "  * LCD-Init - Phase *  ",0x0D,0xFF
    .db "   (C)2018 by DG4FAC    ",0xFE,0xFF
  .endif
;
; ------- Display output masks -------------
;
; Edit those texts to fit to your own needs
;
.if cLcdColumns == 8
  LcdTxtMsk:
    .db "Line 1  ",0x0D,0xFF
    .db "Line 2  ",0x0D,0xFF
    .db "Line 3  ",0x0D,0xFF
    .db "Line 4  ",0xFE,0xFF
  .endif
.if cLcdColumns == 16
  LcdTxtMsk:
    .db "Line 1          ",0x0D,0xFF
    .db "Line 2          ",0x0D,0xFF
    .db "Line 3          ",0x0D,0xFF
    .db "Line 4          ",0xFE,0xFF
  .endif
.if cLcdColumns == 20
  LcdTxtMsk:
    .db "Line 1              ",0x0D,0xFF
    .db "Line 2              ",0x0D,0xFF
    .db "Line 3              ",0x0D,0xFF
    .db "Line 4              ",0xFE,0xFF
  .endif
.if cLcdColumns == 24
  LcdTxtMsk:
    .db "Line 1                  ",0x0D,0xFF
    .db "Line 2                  ",0x0D,0xFF
    .db "Line 3                  ",0x0D,0xFF
    .db "Line 4                  ",0xFE,0xFF
  .endif
;
; End of include
;



To top of page




Praise, error reports, scolding and spam please via the comment page to me. Spammers: please note that behind this is not a dump standard script but I personnally select the entries to be published.

©2018 by http://www.avr-asm-tutorial.net