⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ks0066ulcdr.asm

📁 ks0066ulcd控制器的汇编源代码
💻 ASM
字号:
; ******************************************************************
;    L C D    D I S P L A Y    R O U T I N E S
; ******************************************************************
;
;   Interfaces the AVR '8515 microcontroller with LCDs controlled
;   by the Samsung KS0066U (and similiar) LCD driver.
;
;   Author:   Adam Swann <adam@velocity2.com>
;   Homepage: http://www.velocity2.com/~adam/
;
;   The code below is fairly straightforward and well-documented.
;   See my Web site or e-mail me if you need further instructions.
;
;   I used an 8515 at 4 MHz.  My LCD is Jameco Part #171715.
;
;   I wired the LCD display as follows (onto Port C)
;     AVR   LCD
;      0 --> no connection
;      1 --> Enable on LCD
;      2 --> R/W on LCD
;      3 --> RS on LCD
;      4 --> Data4
;      5 --> Data5
;      6 --> Data6
;      7 --> Data7
;
;   References: (URLs may be wrapped)
;    o KS0066U Datasheet <http://www.usa.samsungsemi.com/
;                          products/summary/charlcd/ks0066u.htm>
;
; ******************************************************************

; *** LCD_Init: Routine to initialize the LCD.
LCD_Init:  push  Temp

    ldi  DelayTime, 255

    ; 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.)
    ldi  Temp, 0b00110000
    out  LCD_PORT, Temp
    rcall  LCD_PulseE

    rcall  DELAY
    rcall  DELAY

    ; Now it's safe to go into 4-bit mode.
    ldi  Temp, 0b00100000
    out  LCD_PORT, Temp
    rcall  LCD_PulseE

    rcall   DELAY
    rcall  DELAY

    ; *** Send the 'FUNCTION SET' command
    ;       +------ Data:  0 = 4-bit; 1 = 8-bit
    ;       |+----- Lines: 0 = 1; 1 = 2
    ;       ||+---- Font:  0 = 5x8; 1 = 5x11
    ldi  Temp, 0b00101100
    rcall   LCD_SendCmd

    ; *** Send the 'CURSOR/DISPLAY SHIFT' command
    ;        +----- S/C:  0 = cursor; 1 = display
    ;        |+---- R/L:  0 = left; 1 = right
    ldi  Temp, 0b00010100
    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  Temp, 0b00001100
    rcall   LCD_SendCmd

    ; *** Send the 'ENTRY MODE' command
    ;          +--- Direction: 0 = left; 1 = right
    ;          |+-- Shift Dislay: 0 = off; 1 = on
    ldi  Temp, 0b00000110
    rcall   LCD_SendCmd

    rcall   LCD_Clear

    pop   Temp
    ret

; *** LCD_PrintMem: Prints from memory.
;       Put the starting memory location in Z (r31:r30)
;       Put the number of characters to print in Temp2
;  After execution, Z is at the character AFTER the last to be printed
;                   and Temp2 is zero.
;       This function will not wrap if you the string is bigger than the LCD.

LCD_PrintMem:  push  Temp

   LCD_MemRead: ld  Temp, Z+
    rcall  LCD_SendChar
    dec  Temp2
    brne  LCD_MemRead

    pop  Temp
    ret

; *** LCD_PrintEE: Prints from EEPROM
;LCD_PrintEE:  push  Temp
;
 ;   LCD_EERead: sbic   EECR, EEWE   ; Wait for EEWE to clear
;    rjmp   LCD_EERead
;
;    out   EEARH, r31   ;output address high byte, remove if no high byte exist
;    out   EEARL, r30   ;output address low byte
;
;    sbi   EECR, EERE   ;set EEPROM Read strobe
;    in   Temp, EEDR   ;get data
;
;    rcall  LCD_SendChar
;
;    dec  Temp2
;    brne  LCD_EERead
;
;    pop  Temp
;    ret

; *** LCD_PrintPM: Prints from program memory
LCD_PrintPM:  push  r0
    push  Temp

    LCD_PMRead: lpm
        mov  Temp, r0
    rcall  LCD_SendChar
    adiw  r30, 1
    dec  Temp2
    brne  LCD_PMRead

    pop  Temp
    pop  r0
    ret



; *** LCD_Clear: Clears the display and sends the cursor home.

LCD_Clear:  push   Temp

    ; *** Clear the display
    ldi  Temp, 0b00000001
    rcall   LCD_SendCmd

    ; *** Send the cursor home
    ldi  Temp, 0b00000010
    rcall   LCD_SendCmd

    pop  Temp
    ret

; *** LCD_SendCmd: Routine to write a command to the instruction register.
;       The value to be written should be stored in Temp.
;       The value is sent 4 bits at a time.

LCD_SendCmd:  push   Temp
    push   Temp2

    rcall  LCD_WaitBusy

    mov   Temp2, Temp    ; Make a backup copy
    andi   Temp2, 0b11110000  ; Only use the upper nibble
    out  LCD_PORT, Temp2    ; Send it
    rcall   LCD_PulseE    ; Pulse the enable

    swap  Temp      ; Swap upper/lower nibble
    andi   Temp, 0b11110000  ; Only use the upper nibble
    out  LCD_PORT, Temp    ; Send it
    rcall   LCD_PulseE    ; Pulse the enable

    pop   Temp2
    pop   Temp
    ret
; *** LCD_SendChar: Routine to write a character to the data register.
;       The value to be written should be stored in Temp.
;       The value is sent 4 bits at a time.

LCD_SendChar:  push   Temp
    push   Temp2

    mov   Temp2, Temp    ; Make a backup copy
    rcall  LCD_WaitBusy
    mov   Temp, Temp2    ; Make a backup copy

    andi   Temp2, 0b11110000  ; Only use the upper nibble
    ori  Temp2,  0b00001000
    out  LCD_PORT, Temp2    ; Send it
    rcall   LCD_PulseE    ; Pulse the enable

    swap  Temp      ; Swap upper/lower nibble
    andi   Temp,  0b11110000  ; Only use the upper nibble
    ori  Temp,  0b00001000
    out  LCD_PORT, Temp    ; Send it
    rcall   LCD_PulseE    ; Pulse the enable

    pop   Temp2
    pop   Temp
    ret

; *** LCD_WaitBusy: Wait for the busy flag to go low.
;       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).  The
;       second read is never used.
;       If you need more code space, this function could be replaced with
;       a simple delay.

LCD_WaitBusy:  push   Temp

    ldi  Temp, 0b00001111  ; Disable data bit outputs
    out  LCD_DDR, Temp

    ldi  Temp, 0x00    ; Clear all outputs
    out  LCD_PORT, Temp

LCDWaitLoop:  ldi  Temp, 0b00000100  ; Enable only read bit
    out  LCD_PORT, Temp
    sbi  LCD_PORT, LCD_E    ; Raise the Enable signal.
    nop
    nop
    in  Temp, LCD_PIN    ; Read the current values
    cbi  LCD_PORT, LCD_E    ; Disable the enable signal.
    rcall   LCD_PulseE    ; Pulse the enable (the second nibble is discarded)
    sbrc  Temp, 7      ; Check busy flag
    rjmp  LCDWaitLoop

    ldi  Temp, 0b11111111  ; Enable all outputs
    out  LCD_DDR, Temp

    pop  Temp
    ret

LCD_PulseE:  sbi  LCD_PORT, LCD_E
    nop
    nop
    cbi  LCD_PORT, LCD_E
    ret

; *** Provide millisecond delay (DelayTicks specifies number of ms)
DELAY:  push DelayTime
  push r25

  ldi  r25, DelayCount1

DELAY1:  dec r25
  brne DELAY1
  dec DelayTime
  brne DELAY1

  pop r25
  pop DelayTime
  ret

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -