www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Zeile 2 eines LC_Display beschreiben


Autor: Steffen K. (steffen3)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,
ich habe ein Problem damit die zweite Zeile eines 2*16 LCD zu 
beschreiben.
Da ich von Assembler nichts verstehe, bin ich auf eine Lösung in C 
angewiesen. Die erste Zeile lässt sich einwandfrei benutzen.
Als init()-Funktion für das Display verwende ich die Funkktion die das 
Tutorial "AVR-GCC-Tutorial" beschreibt.
void lcd_init(void)
{
  LCD_DDR=LCD_DDR |0xF0;
  LCD_RS_DDR|=(1<<LCD_RS);
  LCD_EN_DDR|=(1<<LCD_EN);
  _delay_ms(15);
  LCD_PORT &=0x0F;
  LCD_PORT |= 0x30;
  LCD_RS_PORT &= ~(1<<LCD_RS);
  lcd_enable();
  _delay_ms(5);
  lcd_enable();  
  _delay_ms(1);
  lcd_enable();
  _delay_ms(1);

  LCD_PORT &= 0x0F;
  LCD_PORT |=0x20;
  lcd_enable();

  lcd_command(0x28);
  lcd_command(0x0C);
  lcd_command(0x06);
  lcd_clear();
}

Musste die Pinbelegung etwas ändern, weil ich sie noch für andere Dinge 
brauche.

Da ich nicht weiter weiß, hoffe ich das mir da jemand weiterhelfen kann.

Gruss Steffen

Autor: Marvin M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Den Commands nach ist das ein LCD mit Standard-Controller. Versuchs mal 
mit lcd_command(0xC0).
Müsste auch im Datenblatt des LCD-Controllers nachzulesen sein ;-)
Gleich die Antwort auf die nächste Frage: Die erste Zeile wird mit 0x80 
angesprochen ;-)

Autor: Steffen K. (steffen3)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
erstmal danke für die schnelle Antwort. Leider funktiniert es nicht, 
wenn ich
lcd_command(0xC0)
verwende.

Autor: Otto (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Steffen,

manche Displays haben zwar nur 16 Zeichen, die 2. Zeile beginnt aber 
nach 40 Zeichen.

Gruss Otto

Autor: Steffen K. (steffen3)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich habe
lcd_command(0x29)
 versucht, geht aber auch nicht. Beim Verstellen des Kontrasts ist mir 
aufgefallen, dass ich ihn in der zweiten Zeile nicht verändern kann und 
er konstant ehr schwach ist.
Daher frage ich mich, ob ich die zweite Zeile vielleicht auch 
initialisieren muss?

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hat das Display nur einen Enable-Eingang? Es gibt auch Displays, die 
für jede Zeile nen eigenen Controller haben. Die haben dann zwei Enables 
und müssen auch entsprechend angesteuert werden.

Autor: winne (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Am Besten ihr lest mal die Datasheet.

Zum einen gibt es entsprechende Inits die zahl der aktivierten Zeilen 
betreffend.

Zum anderen ist die richtige Adressierung zu beachten sie kann von 
sowohl vom LCD-Controller als vom konkreten Modul abhängen.

Zumeist hat jede Zeile 40-Byte unabhängig von der Anzahl der tatsächlich 
verwendeten Bytes.

Autor: Steffen K. (steffen3)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Johannes M. wrote:
> Hat das Display nur einen Enable-Eingang?
Das LCD ist ein Addon von "myavr" und verfügt laut Datenblatt über die 
Eingänge RS=Enable und E=Enable.
Folgender Quelltext beschreibt auch die zweite Zeile, leider habe ich 
von Assembler keine Ahnung und verstehe nicht warum es mit dem Quelltext 
klappt.
;---------------------------------------------------------------------------
; Title         : Programmbeispiel für myAVR-Board mit LCD Add-On
;---------------------------------------------------------------------------
; Funktion      : gibt Zeichenketten auf dem myAVR LCD Modul, 2 Zeilen
; Schaltung     : PORT D2 = RS, PORT D3 = E, PORT D4-7 = D4-7
;---------------------------------------------------------------------------
; Prozessor     : ATmega8
; Takt      : 3,6864 MHz
; Sprache       : Assembler
; Datum         : 03.02.2005
; Version       : 1.6
; Autor         : Dipl. Ing. Päd. Alexander Huwaldt
;---------------------------------------------------------------------------
.equ  F_CPU,  3686400
.include  "AVR.H"
;---------------------------------------------------------------------------
; Reset- und Interruptvektoren          ; VNr.  Beschreibung
  rjmp  main  ; 1     POWER ON RESET
  reti    ; 2     Int0-Interrupt
  reti    ; 3     Int1-Interrupt
  reti    ; 4     TC2 Compare Match
  reti    ; 5     TC2 Overflow
  reti    ; 6     TC1 Capture
  reti    ; 7     TC1 Compare Match A
  reti    ; 8     TC1 Compare Match B
  reti    ; 9     TC1 Overflow
  reti    ; 10    TC0 Overflow
  reti    ; 11    SPI, STC Serial Transfer Complete
  reti    ; 12    UART Rx Complete
  reti    ; 13    UART Data Register Empty
  reti    ; 14    UART Tx complete
  reti    ; 15    ADC Conversion Complete
  reti    ; 16    EEPROM Ready
  reti    ; 17    Analog Comperator
  reti    ; 18    TWI (I²C) Serial Interface
  reti    ; 19    Store Program Memory Ready
;---------------------------------------------------------------------------
; Start, Power ON, Reset
main:  ldi  r16,lo8(RAMEND)
  out  SPL,r16  ; Init Stackpointer LO
  ldi  r16,hi8(RAMEND)
  out  SPH,r16  ; Init Stackpointer HI
  rcall  LCD_init
  rcall  LCD_clear
;---------------------------------------------------------------------------
mainloop:  rcall  wait
  ldi  r16,'H'
  rcall  LCD_data
  ldi  r16,'a'
  rcall  LCD_data
  ldi  r16,'l'
  rcall  LCD_data
  ldi  r16,'l'
  rcall  LCD_data
  ldi  r16,'o'
  rcall  LCD_data
  ldi  r16,' '
  rcall  LCD_data

  rcall  LCD_line2

  ldi  r16,'S'
  rcall  LCD_data
  ldi  r16,'i'
  rcall  LCD_data
  ldi  r16,'S'
  rcall  LCD_data
  ldi  r16,'y'
  rcall  LCD_data
  ldi  r16,' '
  rcall  LCD_data

  rcall  LCD_home

  rjmp  mainloop
;===========================================================================
; hier Unterprogramme und Interruptroutinen zufügen
;---------------------------------------------------------------------------
wait:  push  r24
  ldi  r24,0x13  ; hier delay einstellen 13 = ca. 20yS
w1:  subi  r24,0x01
  rcall  wait20ms
  brcc  w1
  pop  r24
  ret
;---------------------------------------------------------------------------
wait5ms:  ldi  r16,255
  ldi  r17,26
w5ms:  dec  r16
  brne  w5ms
  dec  r17
  brne  w5ms
  ret
;---------------------------------------------------------------------------
wait20ms:  ldi  r16,255
  ldi  r17,104
w20ms:  dec  r16
  brne  w20ms
  dec  r17
  brne  w20ms
  ret
;---------------------------------------------------------------------------
LCD_init:  sbi  DDRD,2  ; LCD RS = OUT
  sbi  DDRD,3  ; LCD E  = OUT
  sbi  DDRD,4  ; LCD D4 = OUT
  sbi  DDRD,5  ; LCD D5 = OUT
  sbi  DDRD,6  ; LCD D6 = OUT
  sbi  DDRD,7  ; LCD D7 = OUT
  cbi  PORTD,2  ; LDC RS = Low

; warte bis PowerUp
  ldi  r18,20
powerup:  rcall  wait5ms
  dec  r18
  brne  powerup  ; Power-Up Wartezyklus min 30 ms

; sende Resetsequenz kompatibel zu HD44780 Industriestandard
  ldi  r16,0b00110000  ; Reset-Sequenz Teil 1
  out  PORTD,r16
  rcall  LCD_enable  ; Enable-Impuls
  rcall  wait5ms
  ldi  r16,0b00110000  ; Reset-Sequenz Teil 2
  out  PORTD,r16
  rcall  LCD_enable  ; Enable-Impuls
  rcall  wait5ms
  ldi  r18,100  ; Wartezyklus bei RESET LCD min 100 µs
resetLCD:
  nop
  nop
  nop
  dec  r18
  brne  resetLCD
  ldi  r16,0b00110000  ; Reset-Sequenz Teil 3
  out  PORTD,r16
  rcall  LCD_enable  ; Enable-Impuls
  rcall  wait5ms

; sende init 1
  ldi  r16,0b00100000  ; 4 Bit Modus aktivieren
  out  PORTD,r16
  rcall  LCD_enable  ; Enable-Impuls
  rcall  wait5ms
  ldi  r16,0b00101000
  rcall  LCD_cmd  ; Function Set 4 Bit, 2 Zeilen, 5x7
  rcall  LCD_off
  rcall  LCD_clear
  ldi  r16,0x06
  rcall  LCD_cmd  ; Entry Mode Set, increase+shifted
  rcall  LCD_on
  ret
;---------------------------------------------------------------------------
LCD_data:  ldi  r18,0b0000100  ; RS = hi
  rjmp  LCD_out
;---------------------------------------------------------------------------
LCD_cmd:  ldi  r18,0b0000000  ; RS = lo
LCD_out:  mov  r17,r16
  swap  r17
  andi  r16,0b11110000
  or  r16,r18
  andi  r17,0b11110000
  or  r17,r18
  out  PORTD,r16
  rcall  LCD_enable
  out  PORTD,r17
  rcall  LCD_enable
  rcall  wait5ms
  ret
;---------------------------------------------------------------------------
LCD_enable:  sbi  PORTD,3  ; Enable high
  nop    ; kurz warten
  nop
  nop
  cbi  PORTD,3  ; Enable wieder low
  ret
;---------------------------------------------------------------------------
LCD_clear:  ldi  r16,0b00000001  ; Display löschen
  rcall  LCD_cmd
  rcall  wait5ms
  ret
;---------------------------------------------------------------------------
LCD_off:  ldi  r16,0b00001000
  rcall  LCD_cmd
  rcall  wait5ms
  ret
;---------------------------------------------------------------------------
LCD_on:  ldi  r16,0x0E
  rcall  LCD_cmd
  rcall  wait5ms
  ret
;---------------------------------------------------------------------------
LCD_home:  ldi  r16,0b00000010  ; Display Cursor HOME
  rcall  LCD_cmd
  rcall  wait5ms
  ret
;---------------------------------------------------------------------------
LCD_line1:  ldi  r16,0b10000000  ; DRAM auf Adresse 0x00
  rcall  LCD_cmd
  rcall  wait5ms
  ret
;---------------------------------------------------------------------------
LCD_line2:  ldi  r16,0b11000000  ; DRAM auf Adresse 0x40
  rcall  LCD_cmd
  rcall  wait5ms
  ret
;---------------------------------------------------------------------------
; Goto r16 = Adresse (Zeile 1 = 0x00..0x0F, Zeile 2 = 0x40..0x4F)
LCD_goto:  ori  r16,0b10000000  ; Goto DRAM auf Adresse r16
  rcall  LCD_cmd
  rcall  wait5ms
  ret
;---------------------------------------------------------------------------

Der Code ist eine Codevorlage aus dem Programm "myAVR Workpad", hoffe 
das ich ihn hier posten darf.

Autor: Marvin M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"Beim Verstellen des Kontrasts ist mir
aufgefallen, dass ich ihn in der zweiten Zeile nicht verändern kann und
er konstant ehr schwach ist."

Dann stimmt etwas mit der Initialisierung des LCD nicht. Poste mal 
Deinen kompletten C-Code (idealerweise als *.zip angehängt).
Im Prinzip ist der Befehl 0x28 für die Initialisierung zuständig, den 
hast Du in Deinem ersten Code-Fragment drinnen. Könnte ein 
Timing-Problem sein. Ganz schlau werde ich auch nicht daraus, dass Du 
zuerst den LCD-Port "von Hand" durchklingelst und später dann doch eine 
Funktion "lcd_command()" verwendest.

Autor: Marvin M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ah- ist schon spät... habs gerade bemerkt, 4-Bit Modus... klar.

Aber Du solltest den Code besser mit Copy & Paste einfügen ;-)

Wie schon vermutet, ist Deine Initialisierungsroutine falsch. In zwei 
Zeilen hast Du Zahlendreher drinnen:
void lcd_init(void)
{
  LCD_DDR=LCD_DDR |0xF0;
  LCD_RS_DDR|=(1<<LCD_RS);
  LCD_EN_DDR|=(1<<LCD_EN);
  _delay_ms(15);
  LCD_PORT &=0x0F;
  
  // falsch: LCD_PORT |= 0x30; !!!
  LCD_PORT |= 0x03;  // richtig...

  LCD_RS_PORT &= ~(1<<LCD_RS);
  lcd_enable();
  _delay_ms(5);
  lcd_enable();  
  _delay_ms(1);
  lcd_enable();
  _delay_ms(1);

  LCD_PORT &= 0x0F;
  // falsch: LCD_PORT |=0x20; !!!
  LCD_PORT |=0x02;  // richtig...

  lcd_enable();

  lcd_command(0x28);
  lcd_command(0x0C);
  lcd_command(0x06);
  lcd_clear();
}

Autor: Steffen K. (steffen3)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Das ändern der init() hat nichts gebracht, im Anhang ist der komplette 
Quelltext.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.