Forum: Mikrocontroller und Digitale Elektronik Beim 16x1 LCD will der Zeilenwechsel nicht klappen


von Kay (Gast)


Lesenswert?

Hallo, ich möchte ein 1x16 Display (2x8) zweizeilig beschreiben. Das 
Display ist von reichelt 
(http://www.reichelt.de/?;ACTION=3;LA=2;GROUP=A5211;GROUPID=3005;ARTICLE=10945;START=0;SORT=artnr;OFFSET=16;SID=285LwJH6wQARwAAAQoaygd6117d70754e93fcbe1250a8de99b8ad). 
Ich weiss nur nicht wo ich den Befehl zur Ansteuerung genau einbinden 
soll. Auf jeden Fall muss die Adresse 0x40 angesprochen werden um den 
Zeilenwechsel zu ermöglichen. Das Display wurde bei der Initialisierung 
2 zeilig initialisiert. Kann mir jemand helfen?
Gruß Kay

Hier das Programm:

;***********************************************************************
;Ansteuerung eines LCD Displays
;PIC 16F628
;Takt 4MHz
;Kay
;06.08.09
;***********************************************************************
;Pinbelegung des PIC****************************************************
;***********************************************************************
;  PortB,0    ->  Enable
;  PortB,1    ->  not connected
;  PortB,2    ->  RS (Register Select)
;  PortB,3    ->  RW (Read / Write)
;  PortB,4    ->  D4 (Datenbus 4 bittig)
;  PortB,5    ->  D5 (Datenbus 4 bittig)
;  PortB,6    ->  D6 (Datenbus 4 bittig)
;  PortB,7    ->  D7 (Datenbus 4 bittig)
;
;  RS = 1    ->  Daten des Datenbusses werden als Zeichen in den 
Textpuffer übertragen
;  RS = 0    ->  Daten des Datenbusses werden als Befehl in der 
Steuerregister geschrieben
;
;  RW = 1    ->  Lesefunktion
;  RW = 0    ->  Schreibfunktion
;***********************************************************************
;Varablen vereinbaren***************************************************
;***********************************************************************
loops    equ  0x20      ; timer für wait
loops2    equ  0x21      ; timer für wait
loops3    equ  0x22
loops4    equ  0x23
loops5    equ  0x24
LcdStatus  equ  0x25      ;
LcdDaten  equ  0x26      ;

;LcdE    equ  PortB,0      ; enable Lcd
;LcdRw    equ  PORTB,3      ; read/write Lcd
;LcdRs    equ  PORTB,2      ; Daten Lcd (nicht control)
;***********************************************************************
;Programm starten*******************************************************
;***********************************************************************
  org   0x00
  goto  Init
;***********************************************************************
;Initialisierung des PIC************************************************
;***********************************************************************
Init
  bsf  status,rp0      ; select Bank1
  movlw  B'00000010'      ; Pull up resistors activ
  movwf  option_reg
  movlw  B'11111111'      ; PortA all input
  movwf  trisa
  movlw  B'00000000'      ; PortB all output
  movwf  trisb
  bcf  status,rp0      ; select Bank0
  movlw  B'00000000'      ; Interrupt disable
  movwf  Intcon
;***********************************************************************
;Hauptprogramm**********************************************************
;***********************************************************************
Main
  call  InitLcd

Out  movlw  'G'
  movwf  LcdDaten
  call  OutLcdDaten
  movlw  'u'
  movwf  LcdDaten
  call  OutLcdDaten
  movlw  't'
  movwf  LcdDaten
  call  OutLcdDaten
  movlw  'e'
  movwf  LcdDaten
  call  OutLcdDaten
  movlw  'n'
  movwf  LcdDaten
  call  OutLcdDaten
  movlw  ' '
  movwf  LcdDaten
  call  OutLcdDaten
  movlw  'T'
  movwf  LcdDaten
  call  OutLcdDaten
  movlw  'a'
  movwf  LcdDaten
  call  OutLcdDaten

; 8 Zeichen fertig
; ACHTUNG
; Einfuegen eines Zeilenwechsels beim 2x8-Display

  call  OutLcdControl
  movlw  'g'
  movwf  LcdDaten
  call  OutLcdDaten


;***********************************************************************
;LCD initialisieren*****************************************************
;***********************************************************************
InitLcd
  movlw  D'150'        ; Delay after Vdd rises to 4,5V
  movwf  loops
  call  Wait
  bcf  PortB,0        ; defined status for enable bit
  bcf  PortB,2        ; RS = 0 -> instruction signal
  bcf  PortB,3        ; RW = 0 -> write mode
  movlw  B'00110000'      ; InitLcd step 1: 8 bit interface
  call  Transmit      ; transfer 8 bit instruction signal
  movlw  B'00110000'      ; InitLcd step 2: 8 bit interface
  call  Transmit      ; transfer 8 bit instruction signal
  movlw  B'00110000'      ; InitLcd step 3: 8 bit interface
  call  Transmit      ; transfer 8 bit instruction signal
  movlw  B'00100000'      ; InitLcd step 4: 4 bit interface
  call  Transmit      ; transfer 8 bit instruction signal
  call  LcdBusy        ; Lcd busy? If Lcd busy, busy flag is high 
(PortB,7)
  movlw  B'00000001'      ; clear und cusor home
  call  OutLcdControl
  movlw  B'00101000'      ; function set, 4-bit  2-zeilig,  5x7
  call  OutLcdControl
  movlw  B'00001000'      ; display off
  call  OutLcdControl
  movlw  B'00000110'      ; entry mode, increment, disable display-shift
  call  OutLcdControl
  ;movlw  B'00000011'      ; cursor home, cursor home
  ;call  OutLcdControl
  movlw  B'00001100'      ; display on, cursor off, cursor flash off
  call  OutLcdControl

;***********************************************************************
;Transfer 8 bit intruction signal***************************************
;***********************************************************************
Transmit
  movwf  PortB        ; Data to Databus
  bsf  PortB,0        ; enable Chip signal
  nop          ; wait
  bcf  PortB,0        ; disable Chip signal
  movlw  D'50'        ; Delay of 50ms
  movwf  loops
  call  Wait
  return
;***********************************************************************
;LCD busy at the moment?************************************************
;***********************************************************************
LcdBusy
        bsf     STATUS, RP0      ; make Port B4..7 input
  movlw  B'11110000'
  iorwf   TRISB, f
        bcf     STATUS, RP0
BusyLoop
  bcf  PortB,2
  bsf  PortB,3        ; Lesen
  bsf  PortB,0
  nop
  movf  PortB, w
  movwf  LcdStatus
  bcf  PortB,0
  nop
  bsf  PortB,0        ; Enable
  nop
  bcf  PortB,0
  btfsc  LcdStatus, 7      ; teste bit 7
  goto  BusyLoop
  bcf  PortB,3
        bsf     STATUS, RP0      ; make Port B4..7 output
  movlw  B'00001111'
  andwf   TRISB, f
        bcf     STATUS, RP0
  return
;********************************************************************
;aus W ein Byte mit Steuerdaten zum Display übertragen***************
;********************************************************************
OutLcdControl
  movwf  PortB
  call  LcdBusy
  movf  LcdDaten, w
  andlw  H'F0'
  movwf  PortB        ; Hi-teil Daten schreiben
  bsf  PortB,0
  nop
  bcf  PortB,0        ; Disable LcdBus
  swapf  LcdDaten, w
  andlw  H'F0'
  movwf  PortB        ; Lo-teil Daten schreiben
  bsf  PortB,0
  nop
  bcf  PortB,0        ; Disable LcdBus
  return
;*******************************************************************
;aus W ein Datenbyte zum Display übertragen*************************
;*******************************************************************
OutLcdDaten
  movwf  LcdDaten
  call  LcdBusy
  movf  LcdDaten, w
  andlw  H'F0'
  movwf  PortB        ; Hi-teil Daten schreiben
  bsf  PortB,2        ; Daten
  bsf  PortB,0        ; Enable LcdBus
  nop
  bcf  PortB,0        ; Disable LcdBus
  swapf  LcdDaten, w
  andlw  H'F0'
  movwf  PortB        ; Lo-teil Daten schreiben
  bsf  PortB,2        ; Daten
  bsf  PortB,0
  nop
  bcf  PortB,0        ; Disable LcdBus
  bcf  PortB,2        ;
  return
;*******************************************************************
;Subroutines********************************************************
;*******************************************************************

;Zeitverzögerung um loops * 1 ms
; 4 MHz externer Takt bedeutet 1 MHz interner Takt
; also dauert 1 ms genau 1000 Befehle
; 100 Schleifen a 10 Befehle sind 1000 Befehle = 1 ms


WAIT
top     movlw   D'100'               ; timing adjustment variable (1ms)
        movwf   loops2
top2    nop                          ; sit and wait
        nop
        nop
        nop
  nop
        nop
        nop
        decfsz  loops2, F            ; inner loops complete?
        goto    top2                 ; no, go again

        decfsz  loops, F             ; outer loops complete?
        goto    top                  ; no, go again
        retlw   0                    ; yes, return from WAIT

von Eduard Andre (Gast)


Lesenswert?

Wie kommst Du auf die Idee, dass Du ein einzeiliges Display zweizeilig 
ansteuern kannst?

von Diensthabender Troll (Gast)


Lesenswert?

> Wie kommst Du auf die Idee, dass Du ein einzeiliges Display zweizeilig
> ansteuern kannst?

Weil das bei den meisten einzeiligen LCDs mit HD44780-kompatiblen 
Controllern so üblich ist.

von Rex Gildo jr. (Gast)


Lesenswert?

Moin!

Wie kann ich 16 kByte Daten in einem 8kByte Flash ablegen ;)

Mal im Ernst, die Pixelauflösung reicht doch von vorne bis hinten nicht 
um vernünftige Zeichen darzustellen.

von Helfer (Gast)


Lesenswert?

@Kay (Gast)
Ja ich kann helfen.
Schau dir mal den Befehl "Set DDRAM Address" im Datenblatt des KS0066U 
auf S.16 an.

@Diensthabender Troll (Gast)
das hat beim KS0066U mehr praktische Gründe. Der Controller kann nur 8 
Zeichen ansteuern, aber dafür 2 Zeilen.

von Diensthabender Troll (Gast)


Lesenswert?

Wer redet denn hier von Pixeln???

Es handelt sich doch eindeutig um ein Text-LCD.

HD44780-kompatible Controller haben zwei separate DD-RAM-Bereiche je 40 
Zeichen (Bytes), die meist auf beide Hälften des sichtbaren Teils LCDs 
aufgeteilt werden. Daher sind auch die meisten einzeiligen LCDs wie 
Zweizeilige anzusteuern. Die ersten 8 Zeichen dieses 16x1 gehören an 
Adresse 00h bis 07h (0 bis 7) ins DD-RAM, die zweiten 8 Zeichen an 
Adresse 40h bis 47h (64 bis 71).

Den oben geposteten Code habe ich mir nicht angeschaut, da ich bei PIC 
nicht mitreden kann/will.

von Jens P. (picler)


Lesenswert?

Kay schrieb:

>   movlw  'T'
>   movwf  LcdDaten
>   call  OutLcdDaten
>   movlw  'a'
>   movwf  LcdDaten
>   call  OutLcdDaten
>
> ; 8 Zeichen fertig
> ; ACHTUNG
> ; Einfuegen eines Zeilenwechsels beim 2x8-Display

An der Stelle solltest du dem Display die Sequenz senden, damit es auf 
die 2. Zeile umschaltet. Also RS auf L und dann 0C0H ans Display 
schicken, danach sollte es gehen.

>   call  OutLcdControl
>   movlw  'g'

von Diensthabender Troll (Gast)


Lesenswert?

> das hat beim KS0066U mehr praktische Gründe. Der Controller kann nur 8
> Zeichen ansteuern, aber dafür 2 Zeilen.

Nur 8 Zeichen?? - Das liegt aber nicht am Controller, sondern am LCD.
Denn der Controller kann zweimal 40 Zeichen ansteuern. Bei kleineren 
LCDs kann man den sichtbaren Teil sogar mit Shiftbefehlen verschieben, 
also Scrolltext anzeigen.

von Benedikt K. (benedikt)


Lesenswert?

Diensthabender Troll schrieb:

> Nur 8 Zeichen?? - Das liegt aber nicht am Controller, sondern am LCD.
> Denn der Controller kann zweimal 40 Zeichen ansteuern.

Direkt kann er 40 Pixelspalten und 16 Pixelzeilen ansteuern, was bei 
einer 5x8 Schriftart 8x2 Zeichen entspricht. Die 40 Zeichen 
funktionieren nur über zusätzliche Treiber ICs die vom HD44780 
kompatiblen Controller angesteuert werden. Um diese einzusparen 
verdrahtet man das 1x16 Display als 2x8. So kommt man nur mit dem 
Controller alleine aus.

von Peter D. (peda)


Lesenswert?

Ich mache das immer so, daß die Zeichenausgaberoutine mitzählt und dann 
automatisch in die nächste Zeile wechselt, z.B.:
1
void lcd_data( u8 d )
2
{
3
  u8 i;
4
5
  LCD_RS = 1;
6
  lcd_byte( d );
7
  i = ++position;
8
  switch( i ){
9
    case 0xC0 + LINELEN: i = 0x80; break;
10
    case 0x80 + LINELEN: i = 0xC0; break;
11
    default: return;
12
  }
13
  lcd_command( i );
14
}


Was ist denn das für ein komischer Assembler, kann der nichtmal .DB 
Anweisungen?
Das ist ja voll ätzend, alle Bytes einzeln zu basteln.

Das wäre schon allein ein Grund für mich, vom PIC auf AVR umzusteigen:
1
        .db     "Hallo Peter", 0


Peter

von Helfer (Gast)


Lesenswert?

@Diensthabender Troll (Gast)
Dir ist wohl echt ein bissle langweilig, aber mir auch:
der Speicher reicht für 40 Zeichen, aber die Pins nicht. Im Dateblatt 
steht da was von "SEG1 Extension Driver (40SEG) SEG40". Und wenn ich das 
richtig verstehe braucht man für mehr Zeichen einfach noch mehr ICs die 
alle was Kosten.

von Jens P. (picler)


Lesenswert?

Peter Dannegger schrieb:

> Was ist denn das für ein komischer Assembler, kann der nichtmal .DB
> Anweisungen?
> Das ist ja voll ätzend, alle Bytes einzeln zu basteln.

Naja, mit dem Assembler hat das wenig zu tun, der kann es. Allerdings 
können nur die neueren (18Fxxx) und ein paar wenige von den 16Fxxx Daten 
direkt aus dem Flash lesen.

> Das wäre schon allein ein Grund für mich, vom PIC auf AVR umzusteigen:
>
1
>         .db     "Hallo Peter", 0
2
>

Für mich nicht. Der AVR hat andere Ecken und Macken.

[picasm]
ORG 0400
    da  0x00,0x07,0xE0,0x00,0x00,0x3F,0xFC...
[/picasm]

PS: Ob der ASM direkt Strings verarbeiten kann, habe ich noch nicht 
getestet, bin aber der Meinung, es geht.

von Diensthabender Troll (Gast)


Lesenswert?

Benedikt schrieb:
> Direkt kann er 40 Pixelspalten und 16 Pixelzeilen ansteuern, was bei
> einer 5x8 Schriftart 8x2 Zeichen entspricht.

Danke für die Aufklärung, das ist natürlich das Hauptargument für die 
Zeilenteilung.

Mit der Ausgabeseite der LCD-Controller habe ich mich nicht näher 
beschäftigt, da ich keine LCD-Module bauen möchte und dieses Wissen für 
das Benutzen vorhandener LCDs nicht übermäßig wichtig ist. Daher ist mir 
auch die Aufteilung 40x16 Pixel nicht aufgefallen.

Helfer schrieb:
> der Speicher reicht für 40 Zeichen, aber die Pins nicht

Danke, ich hab's verstanden (siehe oben). Dass für mehr Pixel die Pins 
nicht reichen und daher zusätzliche Treiber-ICs nötig sind, war mir 
schon klar. Mir war allerdings die Aufteilung 40x16 Pixel nicht 
aufgefallen.

Wieder was gelernt....

von Kay (Gast)


Lesenswert?

Vielen Dank für eure Hilfe!
Ich werde es gleich mal ausprobieren ob es klappt.

Gruß Kay

von Sven S. (stepp64) Benutzerseite


Lesenswert?

Jens A: schrieb:
> [picasm]
> ORG 0400
>     da  0x00,0x07,0xE0,0x00,0x00,0x3F,0xFC...
> [/picasm]
>
> PS: Ob der ASM direkt Strings verarbeiten kann, habe ich noch nicht
> getestet, bin aber der Meinung, es geht.

Ja, geht. Mache ich immer so mit Texten für das LCD. Nur die Umlaute 
klappen nicht unbedingt automatisch. Siehe auch 
http://sprut.de/electronic/pic/assemble/pseudo.html#da

Sven

von Sascha (Gast)


Lesenswert?

Ich glaube nicht dass es sinvoll ist, den String auf dem Interruptvektor 
abzulegen...

von Jens (Gast)


Lesenswert?

Wo wird ein String auf dem Interuptvektor abgelegt?

von Eduard Andre (Gast)


Lesenswert?

Hm,
ich sehe schon ich muss noch viel lernen wenn es darum geht ein paar 
Cent zu sparen.
Nichts für ungut.

von Kay (Gast)


Lesenswert?

Hey,

kurzes Feedback, es funktioniert alles wunderbar. Allerdings habe ich 
mich für ein 8 Bit Interface entschieden. Vielen Dank an "Helfer" und 
"Jens A.", ihr habt mir wirklich weiter geholfen!

von Thomas (kosmos)


Lesenswert?

solange man mit den Steuerbits das Display nicht ansteuert kann man ja 
trotzdem den Port weiterhin voll nutzen.

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.