;sendet ein Datenbyte an das LCD lcd_data: mov tmp2, tmp1 ; kopiert tmp1 in tmp2, nötig für den 2. Nibble andi tmp1, 0b11110000 ; unteres Nibble auf Null setzen sbr tmp1, 0b00000001 ; RS setzen, wo null steht wird nichts verändert out PORTD, tmp1 ; ausgeben des oberen Nibbles rcall lcd_enable ; Enable-Routine aufrufen swap tmp2 ; Vertauschen der Bits für den unteren Nibble andi tmp2, 0b11110000 ; untere Hälfte auf Null setzen sbr tmp2, 0b00000001 ; RS setzen out PORTD, tmp2 ; ausgeben rcall lcd_enable ; Enable-Routine aufrufen rcall delay50us ; Delay-Routine aufrufen ret ; zurück zum Hauptprogramm ; sendet einen Befehl an das LCD lcd_command: ; wie lcd_data, nur RS=0 mov tmp2, tmp1 andi tmp1, 0b11110000 out PORTD, tmp1 rcall lcd_enable swap tmp2 andi tmp2, 0b11110000 out PORTD, tmp2 rcall lcd_enable rcall delay50us ret ; erzeugt den Enable-Puls ; ; Bei höherem Takt (>= 8 MHz) kann es notwendig sein, ; vor dem Enable High 1-2 Wartetakte (nop) einzufügen. ; Siehe dazu http://www.mikrocontroller.net/topic/81974#685882 lcd_enable: sbi PORTD, 1 ; Enable (E) high, liegt auf PD1 nop ; 3 Taktzyklen warten nop nop cbi PORTD, 1 ; Enable wieder low ret ; Und wieder zurück ; Pause nach jeder Übertragung delay50us: ; 50us Pause ldi tmp1, $42 ; $42: 42 in hexadezimal / &Takt angleichen delay50us_:dec tmp1 brne delay50us_ ret ; wieder zurück ; Längere Pause für manche Befehle delay5ms: ; 5ms Pause ldi tmp1, $21 WGLOOP0: ldi tmp2, $C9 WGLOOP1: dec tmp2 brne WGLOOP1 dec tmp1 brne WGLOOP0 ret ; wieder zurück ; Initialisierung: muss ganz am Anfang des Programms aufgerufen werden lcd_init: ldi tmp3,50 powerupwait: rcall delay5ms dec tmp3 brne powerupwait ldi tmp1, 0b00110000 ; muss 3mal hintereinander gesendet, entspricht out PORTD, tmp1 ; werden zur Initialisierung rcall lcd_enable ; 1 rcall delay5ms rcall lcd_enable ; 2 rcall delay5ms rcall lcd_enable ; und 3! rcall delay5ms ldi tmp1, 0b00100000 ; 4bit-Modus einstellen PD5 out PORTD, tmp1 rcall lcd_enable rcall delay5ms ldi tmp1, 0b10000010 ; 4Bit / 2 Zeilen / 5x8 rcall lcd_command ldi tmp1, 0b11000000 ; Display ein / Cursor aus / kein Blinken rcall lcd_command ldi tmp1, 0b01000000 ; inkrement / kein Scrollen rcall lcd_command ret ; Sendet den Befehl zur Löschung des Displays lcd_clear: ldi tmp1, 0b00010000 ; Display löschen rcall lcd_command rcall delay5ms ret ; Sendet den Befehl: Cursor Home lcd_home: ldi tmp1, 0b00100000 ; Cursor Home rcall lcd_command rcall delay5ms ret