Forum: Mikrocontroller und Digitale Elektronik wieder Probleme mit dem LCD


von Samuel J. (capstrovor)


Angehängte Dateien:

Lesenswert?

So, lange hats nicht gedauert bis etwas wieder nicht so funktioniert wie 
ich es will.

Ich habe vor ein paar Stunden das Forum um Hilfe bei einem LCD (44780, 
Atmega16, 16MHz) gebeten. Das hat nach einer Weile auch geklappt.
Allerdings habe ich dort noch mit Timern gearbeitet. Ich jetzt aber das 
Busyflag benutzen, nur das geht nicht wie ich es will. Der Code ist im 
Anhang

Kann mir jemand meinen Fehler zeigen?

mfg

: Bearbeitet durch User
von Georg G. (df2au)


Lesenswert?

Das Busy Flag ist nur gültig, während E aktiv ist. Danach ist der Bus 
wieder hochohmig. Du fragst zum falschen Zeitpunkt ab.

von Samuel J. (capstrovor)


Angehängte Dateien:

Lesenswert?

Ok, ich habs jetzt nochmal geändert, allerdings funktioniert es immer 
noch nicht :(

von Max H. (hartl192)


Lesenswert?

1) Kann es sein, dass du die Eingänge über PINB abfragen musst?
2) Wenn du den gesamten PORT auf Input setzt, hat das LCD dann keine
   definierten Pegel an den Eingängen
>  ldi R16, 0x00
>  out LCD_DDR, R16

: Bearbeitet durch User
von Samuel J. (capstrovor)


Lesenswert?

zu 1.) Also so wie ich es im Tutorial (hier auf dieser Seite) gelesen 
habe, sollte es mit
1
sbic
 funktionieren.

zu 2.) Das sollte eigentlich egal sein, da der Modus auf "lesen" gesetzt 
ist. Da muss man eigentlich keine Pegel definieren.

von Max H. (hartl192)


Lesenswert?

Samuel J. schrieb:
> Das sollte eigentlich egal sein
Beim R/W, RS und vor allem Enable wird es dem LCD nicht egal sein.

>sbic LCD_PORT, DB7    ;Wenn Busyflag gesetzt, nicht mehr
>                      ;zu check_busyflag >springen
Das müsste vllt. so ausschauen:
sbic PINB, DB7

Kann auch sein, dass ich falsch liege. Ich programmiere eigentlich nur 
PIC

: Bearbeitet durch User
von Samuel J. (capstrovor)


Angehängte Dateien:

Lesenswert?

@Max:
stimmt auch wieder. Ich habs geändert, allerdings löst das immer noch 
nicht das Problem :/

von Samuel J. (capstrovor)


Lesenswert?

Ja natürlich, das muss PINB heißen facepalm
Allerdings geht es immernoch nicht :D

von Bastler (Gast)


Lesenswert?

1
check_busyflag:
2
3
  cbi LCD_PORT, RS    ;RS auf Low legen
4
  sbi LCD_PORT, RW    ;RW auf High legen
5
  nop
6
  sbi LCD_PORT, E      ;Enable auf High  
7
8
  ldi R16, 0b11110000    ;Port, an dem das LCD hängt, auf Eingang schalten
9
  out LCD_DDR, R16
10
11
  sbic LCD_PORT, DB7    ;Wenn Busyflag gesetzt, nicht mehr zu check_busyflag springen
12
  rjmp check_busyflag

Du springst ja wieder hoch und lässt die Bits erneut zappeln.
1
check_busyflag:
2
3
  cbi LCD_PORT, RS    ;RS auf Low legen
4
  sbi LCD_PORT, RW    ;RW auf High legen
5
  nop
6
  sbi LCD_PORT, E      ;Enable auf High  
7
8
  ldi R16, 0b11110000    ;Port, an dem das LCD hängt, auf Eingang schalten
9
  out LCD_DDR, R16
10
check:
11
  sbic LCD_PORT, DB7    ;Wenn Busyflag gesetzt, nicht mehr zu check_busyflag springen
12
  rjmp check

Probier mal das.

von Max H. (hartl192)


Lesenswert?

Bastler schrieb:
> Du springst ja wieder hoch und lässt die Bits erneut zappeln.

Wenn die bits gesetzt/gelöscht sind sollte es doch egal sein, wenn sie 
nochmal gesetzt/gelöscht werden. Die Ausgänge verden ja gesetzt/gelöscht 
und nicht getoggelt.

: Bearbeitet durch User
von Samuel J. (capstrovor)


Lesenswert?

@Bastler
ich habs geändert, leider bringt auch das keine Veränderung :/

von Max H. (hartl192)


Lesenswert?

Samuel J. schrieb:
> nur das geht nicht wie ich es will
Was genau geht nicht?

Kannst du messen, ob das Busy-Flag gesetzt wird?

von Samuel J. (capstrovor)


Lesenswert?

@Max:
Das Problem ist, dass am LCD nur in der ersten Zeile schwarze Kästchen 
angezeigt werden, die Initialisierung also noch nicht richtig 
abgeschlossen ist.
Nein leider nicht, ich habe zu Hause kein Oszi. Ich kann fühestens am 
Freitag in der Schule messen.

von Max H. (hartl192)


Angehängte Dateien:

Lesenswert?

Ein Blick ins Datenblatt, kann oft weiterhelfen...

von Kugelblitz (Gast)


Lesenswert?

ungefähr so :
1
.equ   LCD_PORT = PORTC
2
.equ   LCD_DDR  = DDRC
3
.equ  LCDS_PORT = PORTB
4
.equ  LCDS_DDR  = DDRB
5
6
.equ  LCD_RS  = 4    ;PB4
7
.equ  LCD_RW  = 3    ;PB3
8
.equ  LCD_E  = 5    ;PB5
9
10
11
12
.def  temp  = r16
13
.def  arg    = r17    ;argument for calling subroutines
14
.def  arg2  = r18    ;argument for mathematics
15
.def  return  = r19    ;return value from subroutines
16
17
LCD_getchar:
18
  in  temp, LCD_DDR    ;make sure the data lines are inputs
19
  andi  temp, 0b00001111  ;so clear their DDR bits
20
  out  LCD_DDR, temp
21
  sbi  LCDS_PORT, LCD_RS    ;we want to access the char data register, so RS high
22
  sbi  LCDS_PORT, LCD_RW    ;we also want to read from the LCD -> RW high
23
  sbi  LCDS_PORT, LCD_E    ;while E is high
24
  nop
25
  in  temp, PinC    ;we need to fetch the HIGH nibble
26
  andi  temp, 0b00001111  ;mask off the control line data
27
  swap temp          ;******** wir haben jetzt die unteren bits also nach oben damit
28
  mov  return, temp    ;and copy the HIGH nibble to return
29
  cbi  LCDS_PORT, LCD_E    ;now take E low again
30
  nop        ;wait a bit before strobing E again
31
  nop  
32
  sbi  LCDS_PORT, LCD_E    ;same as above, now we're reading the low nibble
33
  nop
34
  in  temp, PinC    ;get the data
35
  andi  temp, 0b00001111  ;and again mask off the control line bits
36
  ;swap  temp      ******* jetzt muss hier das swap raus da wir eh schon die low bits haben
37
              ;temp HIGH nibble contains data LOW nibble! so swap
38
  or  return, temp    ;and combine with previously read high nibble
39
  cbi  LCDS_PORT, LCD_E    ;take all control lines low again
40
  cbi  LCDS_PORT, LCD_RS
41
  cbi  LCDS_PORT, LCD_RW
42
  ret          ;the character read from the LCD is now in return
43
44
LCD_getaddr:  ;works just like LCD_getchar, but with RS low, return.7 is the busy flag
45
  in  temp, LCD_DDR
46
  andi  temp, 0b00001111
47
  out  LCD_DDR, temp
48
  cbi  LCDS_PORT, LCD_RS
49
  sbi  LCDS_PORT, LCD_RW
50
  sbi  LCDS_PORT, LCD_E
51
  nop
52
  in  temp, PinC
53
  andi  temp, 0b00001111
54
  swap temp
55
  mov  return, temp
56
  cbi  LCDS_PORT, LCD_E
57
  nop
58
  nop
59
  sbi  LCDS_PORT, LCD_E
60
  nop
61
  in  temp, PinC
62
  andi  temp, 0b00001111
63
  ;swap  temp
64
  or  return, temp
65
  cbi  LCDS_PORT, LCD_E
66
  cbi  LCDS_PORT, LCD_RW
67
  ret
68
69
LCD_wait:        ;read address and busy flag until busy flag cleared
70
  
71
  rcall  LCD_getaddr
72
  andi  return, 0x80    ;bit 4 /4bit high bit (80)
73
  brne  LCD_wait
74
  ret

von Samuel J. (capstrovor)


Lesenswert?

ouhhhh.....
Vielen Danke!
Dann hat sich das wohl erledigt :D

von Bastler (Gast)


Lesenswert?

Du schaltest hiermit ...
 ldi R16, 0b11110000    ;Port, an dem das LCD hängt, auf Eingang 
schalten
  out LCD_DDR, R16
... dein Pin an dem das Busyflag hängt auf Ausgang.

von Max H. (hartl192)


Lesenswert?

Bastler schrieb:
> ldi R16, 0b11110000    ;Port, an dem das LCD hängt, auf Eingang
>... dein Pin an dem das Busyflag hängt auf Ausgang

Samuel J. schrieb:
> RS auf PB4
> RW auf PB5
> E auf PB6
> DB7-DB4 auf PB3-0

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.