www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Assemblerprogr. LCD ansteuerung will nicht funktionieren


Autor: toni (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nabend!!!

Vielleicht erbarmt sich mal jemand, und schaut mal kurzerhand über den 
code drüber, denn der will einfach nicht funktionieren; mache jez den 3 
tag daran rum.

was soll passieren: LCD-Ansteuerung mit einer 4-bit datenleitung an ein 
2x8 display. das LCD wird initialisiert, danach bleibt es dunkel, bzw. 
hell. die obere reihe wird nach dem einschalten hell, also gehe ich 
davon aus, das es zumindest mal initialisiert wird. demnach muss der 
fehler irgendwo in dem unterprogramm Daten: stecken, oder nach der 
eigentlichen ini der falsche code für den 4 bit ansteuermodus. ich finde 
nur leider kein fehler :(.

im 8 bit modus funktioniert fast der selbe code allergings tadellos. 
kann es sein, das das display nur im 8 bit modus angesteuert werden 
kann?!

und von mir schonmal ein fettes danke an die, die sich die mühe machen 
und mal scnell drüberschauen.
;definitionsdatei

.equ DBport= portd ; ausgabeport
.equ RWport= portc ; RS,RW, E
.equ DBddr= ddrd ; datenrichtung ausgabe
.equ RWddr= ddrc ; datenrichtung rs, rw, e
.equ pine= 3    ;PD3 = Pin5
.equ pinrs= 5    ;PD2= Pin4

.device mega8
.include "m8def.inc"


rjmp start

;****************Warteschleifen*******************
ms2:     
             ldi r24, low (125)         ;// 2000 = µs = 2ms; 4 = takte
             ldi r25, high (125)        ;// 2000 = µs = 2ms; 4 = takte
  ms21:      sbiw r24,1                 ;//2takte
             brne ms21                  ;//2takte
             ret                        ;//4takte

ms5:                          
             ldi r24, low (1250)         ;// 5000 = µs = 5ms; 4 = takte
             ldi r25, high (1250)        ;// 5000 = µs = 5ms; 4 = takte
  ms51:      sbiw r24,1                 ;//2takte
             brne ms51                  ;//2takte
             ret                        ;//4takte

ms10:                         
             ldi r24, low (2500)         ;// 10000 = µs = 10ms; 4 = takte
         ldi r25, high (2500)        ;insgesamt 4Takte
  ms101:     sbiw r24,1                 ;//2takte
             brne ms101                  ;//2takte
             ret                        ;//4takte

; Stack initialisieren
start:

ldi r16, LOW(RAMEND)
out SPL, r16

ldi r16, HIGH(RAMEND)
out SPH, r16

ldi r16, 0xff
out ddrd, r16
ldi r16, 0xff
out ddrc, r16

; ----- LCD Anfang -----

;****************hier starten********************
rcall ms10
rcall ms10
rcall ini

rjmp haupt

;****************Daten/Befehle senden*************

;----------Daten Senden
daten:    sbi portc,  pinrs
      mov r18,   r17
      andi r17, 0b11110000
      out portd,  r17
      nop
      sbi portc,   pine 
      nop
      nop
      nop
      nop
      cbi portc,   pine
      swap r18
      andi r18, 0b11110000
      out portd,  r18
      nop
      sbi portc,   pine 
      nop
      nop
      nop
      nop
      cbi portc,   pine
      cbi portc,  pinrs
      nop
      rcall ms2
      ret

;----------Befehle Senden
befehl:    cbi portc,  pinrs
      mov r18,   r17
      andi r17, 0b11110000
      out portd,  r17
      sbi portc,   pine 
      nop
      nop
      nop
      nop
      cbi portc,   pine
      swap r18
      andi r18, 0b11110000
      out portd,  r18
      nop
      sbi portc,   pine 
      nop
      nop
      nop
      nop
      cbi portc,   pine
      rcall ms2
      ret

;----------Befehl für ini mit zeit
befehlini:  cbi portc,  pinrs
      out portd,  r17
      nop
      sbi portc,  pine
      nop 
      nop
      nop
      nop
      cbi portc,   pine
      rcall ms5
      ret

;****************Initialisierung******************
ini:  ldi r17,   0x00
      out portd,   r17
      ldi r17,  $30  ;$30 = 3 mal auf ausgang
      rcall befehlini  ; 1 befehl senden
      rcall befehlini  ; 2 befehl senden
      rcall befehlini  ; 3 befehl senden
      ldi r17, 0b00100000  ; 4-bit interface
      rcall befehlini
      ;Function set
      ldi r17,   0b00101000 ;Funtion set, DL, N, F  
      rcall befehl
      ldi r17,  0b00000001  ;display löschen
      rcall befehl
      ldi r17,  0b00000110  ;Kursor nach rechts wandernd, kein Display shift
      rcall befehl  
      ldi r17,   0b00001100   ;Display ein  
      rcall befehl
      ret

;----------------Hauptprogramm-------------------

haupt:

ldi r17, '0'
rcall daten
ldi r17, '8'
rcall daten
ldi r17, '/'
rcall daten
ldi r17, '1'
rcall daten
ldi r17, '5'
rcall daten

loop:
rjmp loop
      

Autor: Neb N. (bluemorph)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mhh, also, ich hab die letzten Tage auch an meinen Display verbracht und 
mich damit abgequält. In deinem Code kann ich eigentlich kein Fehler 
finden. Was nicht heißt das keiner drin ist smile!

Aber wie hast du denn das Display mit Port D verbunden?? So??

Display:               Port D:
DB7                    PB7
DB6                    PB6
DB5                    PB5
DB4                    PB4

Und was ist mit deinem RW Pin?? Liegt der die ganze Zeit auf Low?

MfG BlueMorph

Autor: norad (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also! Ich würde spontan sagen das Du vergessen hast die Datenleitungen 
von
µC  Portd 4-7 zu Display D0-D3 richtig anzuschliessen.

Sieht so aus als ob Du wie im 8-Bit Modus senden würdest.

Ausserdem fällt mir auf das Du trotzdem noch einen zweiten Port 
verbratest.

Du könntest alles über einen Port senden. Z.B. Portd  in dem Format:

7   6   5   4    3    2    1     0

   EN  RS  RW    D a t e n b y t e

Autor: Hannes Lux (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Also! Ich würde spontan sagen das Du vergessen hast die Datenleitungen
> von µC  Portd 4-7 zu Display D0-D3 richtig anzuschliessen.

D0-D3 des LCDs bleibt im 4-Bit-Modus normalerweise unbeschaltet, es wird 
D4-D7 verwendet.

...

Autor: toni (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin!!!

danke erstmal für die ersten antworten.

"
Aber wie hast du denn das Display mit Port D verbunden?? So??

Display:               Port D:
DB7                    PB7
DB6                    PB6
DB5                    PB5
DB4                    PB4
"

richtig, genau so. der rest liegt am port c. rw liegt auf gnd, brauch 
ich erstmal nicht, da ich das busy noch nicht abfrage und alles über 
diese warteschleifen auf gut dünken steuere.
aber das freut mich schonmal ein wenig, ads ich nicht der einzigste bin, 
der keinen fehler entdeckt. der code vom tutorial funktioniert leider 
nämlich auch nicht, und dabei wird noch nichtmal das lcd initialisiert.

um weitere kommentare wäre ich dankbar :)

Autor: toni (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
achso, noch was:

"
Also! Ich würde spontan sagen das Du vergessen hast die Datenleitungen
von
µC  Portd 4-7 zu Display D0-D3 richtig anzuschliessen.

Sieht so aus als ob Du wie im 8-Bit Modus senden würdest.

Ausserdem fällt mir auf das Du trotzdem noch einen zweiten Port
verbratest.

Du könntest alles über einen Port senden. Z.B. Portd  in dem Format:

7   6   5   4    3    2    1     0

   EN  RS  RW    D a t e n b y t e
"

die anschluss belegung spielt nun erstmal keine rolle, ich habs für 
mich, der besseren übersicht halber, alles auf 2 ports gelegt. ich will 
erstmal nur, das ich einen funktionierenden code habe, dann wird 
optimiert und mehr elemente hinzugefügt.

Autor: Hannes Lux (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> rcall ms10
> rcall ms10
> rcall ini

Vermutlich ist die Wartezeit viiiieeeeelll zu kurz...
Ich bevorzuge Zeiten an 250ms...

...

Autor: toni (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
leider nicht, funktioniert auch mit 250 ms nicht :(

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Hannes hat natürlich recht. Sorry!
>D0-D3 des LCDs bleibt im 4-Bit-Modus normalerweise unbeschaltet, es wird
>D4-D7 verwendet


Aber hier meine ich hast Du ein paar Probleme. Es fehlen Pausen.
Mach mal ein paar Warteschleifen rein wie im nachfolgenden Beispiel.

>ini:
       Mach mal hier ne größere Pause rein
>      ldi r17,   0x00
>      out portd,   r17
>      ldi r17,  $30  ;$30 = 3 mal auf ausgang
>      rcall befehlini  ; 1 befehl senden
       Pause > 100ms
>      rcall befehlini  ; 2 befehl senden
       Pause > 100ms
>      rcall befehlini  ; 3 befehl senden
       Pause > 100ms
>      ldi r17, 0b00100000  ; 4-bit interface
>      rcall befehlini
       Pause > 100ms
>      ;Function set
>      ldi r17,   0b00101000 ;Funtion set, DL, N, F
>      rcall befehl
>      ldi r17,  0b00000001  ;display löschen
>      rcall befehl
       Pause > 500ms  wegen Display löschen
>      ldi r17,  0b00000110  ;Kursor nach rechts wandernd, kein Display
>      rcall befehl
>      ldi r17,   0b00001100   ;Display ein
>      rcall befehl
      ret

Das nicht einhalten der Pausen kann zu fehlerhaften Initialiserung 
führen vor allem beim beim Start der Ini und Display löschen sollte man 
ausreichend warten.
Manche Displays machen da ganz schön Probleme z.b. c-control I2C-Display

Autor: PillePalle (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin

Dir ist bekannt das die Befehle im 8Bit Modus gesendet werden müssen um 
den LCD Controller in den 4-Bit Modus zu versetzen ?

Beispiel:

;ATmega8 (clock frequency doesn't matter, tested with 1 MHz to 8 MHz)
; PortD.1 -> LCD RS (register select)
; PortD.2 -> LCD RW (read/write)
; PortD.3 -> LCd E (Enable)
; PortD.4 ... PortD.7 -> LCD data.4 ... data.7
; the other LCd data lines can be left open or tied to ground.
; the pin Vo can fit to GND for maximum of contrast 

;********************************************************************
LCD_wait:        ;read address and busy flag until busy flag cleared
  rcall  LCD_getaddr
  andi  return, 0x80
  brne  LCD_wait
  ret


LCD_delay:
  clr  r2
  LCD_delay_outer:
  clr  r3
    LCD_delay_inner:
    dec  r3
    brne  LCD_delay_inner
  dec  r2
  brne  LCD_delay_outer
ret

LCD_init:     
;**** for the most LCD you must write 3times a dummy command before you change to 4Bit***
;this is corrected by www.bellibot.com :-)) - before !you have only one LineLCD ***
  
  ldi  temp, 0b00001110  ;control lines are output, rest is input
  out  DDRD, temp
  
  rcall  LCD_delay    ;first, we'll tell the LCD that we want to use it
  ldi  arg, 0x20      ;in 4-bit mode.
  rcall  LCD_command8    ;LCD is still in 8-BIT MODE while writing this command!!!

  rcall  LCD_delay
  ldi  arg, 0x20    ;NOW: 2 lines, 5*7 font, 4-BIT MODE!     ** DUMMY ***
  rcall  LCD_command    ;
  
  rcall  LCD_wait
  ldi  arg, 0x20    ;NOW: 2 lines, 5*7 font, 4-BIT MODE!     ** DUMMY ***
  rcall  LCD_command    ;

  rcall  LCD_wait
  ldi  arg, 0x28    ;NOW: 2 lines, 5*7 font, 4-BIT MODE!     ** this change to 4bit 2 lines **
  rcall  LCD_command    ;after this point you don't can change anything 'show HD44780 Datasheet'

  rcall  LCD_wait
  ldi  arg, 0x0F    ;now proceed as usual: Display on, cursor on, blinking
  rcall  LCD_command
  
  rcall  LCD_wait
  ldi  arg, 0x01    ;clear display, cursor -> home
  rcall  LCD_command
  
  rcall  LCD_wait
  ldi  arg, 0x06    ;auto-inc cursor
  rcall  LCD_command
ret

das delay wird nur für die Init sequenz benutzt , danach abfrage des 
busy flags ( geht auch im 4bit-modus ) find ich pers. besser da keine 
Delay's mehr erforderlich .

Autor: PillePalle (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ui ui , noch was vergessen
; the following source is from AVRbeginners.net .great work- well documented
; the advantage of read the busyflag in 4-bit mode is, no delay's needed
;***********************************************************************************
lcd_command8:  ;used for init (we need some 8-bit commands to switch to 4-bit mode!)
  in  temp, DDRD    ;we need to set the high nibble of DDRD while leaving
          ;the other bits untouched. Using temp for that.
  sbr  temp, 0b11110000  ;set high nibble in temp
  out  DDRD, temp    ;write value to DDRD again
  in  temp, PortD    ;then get the port value
  cbr  temp, 0b11110000  ;and clear the data bits
  cbr  arg, 0b00001111  ;then clear the low nibble of the arg
          ;so that no control line bits are overwritten
  or  temp, arg    ;then set the data bits (from the arg) in the
          ;Port value
  out  PortD, temp    ;and write the port value.
  sbi  PortD, LCD_E    ;now strobe E
  nop
  nop
  nop
  cbi  PortD, LCD_E
  in  temp, DDRD    ;get DDRD to make the data lines input again
  cbr  temp, 0b11110000  ;clear data line direction bits
  out  DDRD, temp    ;and write to DDRD
  ret

lcd_command:  ;same as LCD_putchar, but with RS low!
  push  arg
  in  temp, DDRD
  sbr  temp, 0b11110000
  out  DDRD, temp
  in  temp, PortD
  cbr  temp, 0b11111110
  cbr  arg, 0b00001111
  or  temp, arg

  out  PortD, temp
  sbi  PortD, LCD_E
  nop
  nop
  nop
  cbi  PortD, LCD_E
  pop  arg
  cbr  temp, 0b11110000
  swap  arg
  cbr  arg, 0b00001111
  or  temp, arg
  out  PortD, temp
  sbi  PortD, LCD_E
  nop
  nop
  nop
  cbi  PortD, LCD_E
  in  temp, DDRD
  cbr  temp, 0b11110000
  out  DDRD, temp
ret


hf

Autor: PillePalle (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
und das gehört auch noch dazu :(
LCD_getaddr:  ;works just like LCD_getchar, but with RS low, return.7 is the busy flag
  in  temp, DDRD
  andi  temp, 0b00001111
  out  DDRD, temp
  cbi  PortD, LCD_RS
  sbi  PortD, LCD_RW
  sbi  PortD, LCD_E
  nop
  in  temp, PinD
  andi  temp, 0b11110000
  mov  return, temp
  cbi  PortD, LCD_E
  nop
  nop
  sbi  PortD, LCD_E
  nop
  in  temp, PinD
  andi  temp, 0b11110000
  swap  temp
  or  return, temp
  cbi  PortD, LCD_E
  cbi  PortD, LCD_RW
ret

Autor: PillePalle (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
so und nu als Include File für assembler (komplett) zum download..

mit Dank an AVR-beginner.net und anderen :-)

hf

Autor: Hannes Lux (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> das delay wird nur für die Init sequenz benutzt , danach abfrage des
> busy flags ( geht auch im 4bit-modus ) find ich pers. besser da keine
> Delay's mehr erforderlich .

Busy-Flag lese ich schon lange nicht mehr ein, stattdessen opfere ich 
etwas AVR-SRAM für einen Bildschirmspeicher. Die Print-Routinen werden 
dadurch sauschnell, denn sie schreiben nur über Pointer auf SRAM.
Ein Hintergrundjob, der vom Timer auf einen Abstand von etwa 1ms 
synchronisiert wird, schaufelt dann je ein Byte aus dem 
Bildschirmspeicher an das LCD und entwirrt dabei gleich die 
DD-RAM-Adressen, der Bildschirmspeicher hat daher 
fortlaufende/durchgängige Adressen, kann also mit Fließtext beschrieben 
werden.

...

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hannes Lux wrote:
> Busy-Flag lese ich schon lange nicht mehr ein, stattdessen opfere ich
> etwas AVR-SRAM für einen Bildschirmspeicher.

Außer, daß ich in C schreibe, scheinen wir wohl zu dem gleichen Schluß 
gekommen zu sein.
Es programmiert sich einfach viel angenehmer so, z.B.:

Beitrag "Formatierte Zahlenausgabe in C"


Peter

Autor: Hannes Lux (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Außer, daß ich in C schreibe, scheinen wir wohl zu dem gleichen Schluß
> gekommen zu sein.

Peter, ich habe sehr viel von Dir gelernt, was AVR-ASM und allgemeine 
Herangehensweise an das Programmieren betrifft. Ich habe mir auch einige 
Algorithmen von Dir abgeschaut und etliche Ratschläge angenommen, die Du 
Anderen gegeben hast.

Mit C kann ich mich aber leider nicht anfreunden, das ist mir (trotz 
vorhandenem K&R) zu kryptisch. Ich habe von Kindheit an große Probleme 
mit Sprachen und Auswendiglernen, aber nur geringe Probleme, etwas, was 
ich einmal verstanden habe, neu abzuleiten bzw. in Varianten umzusetzen. 
Dazu kommt die Tatsache, dass ich ungern unverstandenen fremden Code 
(auch in LIBs) verwende, also lieber kleinere Brötchen backe, dafür aber 
meine eigenen. Ich bin da eher der Selbermacher als der Benutzer, auch 
wenn der weg mühsamer ist und das Ergebnis etwas kleiner.

AVRASM empfinde ich als eindeutig und sehr angenehm (ich hatte mal etwas 
Kontakt zu C16-6502-ASM und MFA-8085-ASM). Und da es für mich Hobby ist, 
sehe ich auch keinen Grund mehr, mit fast 60 mühsam eine neue Sprache zu 
erlernen.

...

Autor: Route_66 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Hannes
Deine Meinung teile ich voll und ganz. Die Variante mit dem gemappten 
Display im RAM ist auch immer mein Favorit. Da sind dann auch ganz 
einfach Scrollen und Full-Screen-Editing drin. Den Vorteil des 
Umsortierens der Zeilenanfänge - je nach Display und Hersteller - 
hattest Du ja bereits erwähnt.

Autor: toni (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hmm, ich konnte das problem immernoch nicht lösen. habe nun mal 4 andere 
LCD´s versucht, keines funktioniert, alle jedoch im 8 bit modus. der 
code von der Homepage funktioniert zu meiner überraschung auch nicht. wo 
hängts da, was mache ich falsch?
achso, andere megas habe ich auch schon verwendet, ohne erfolg.

Autor: toni (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
nochmal zum besseren verständnis. im 4 bit modus funktioniert keines der 
lcd, mit keinem der beiden codes ( aus dem tutorial und der code aus dem 
ersten beitrag)
im 8 bit mlodus funktioniert jedoch alles tadellos.

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.