-
        
+ Antworten
Seite 1 von 6 123 ... LetzteLetzte
Ergebnis 1 bis 10 von 54

Thema: LCD Write

  1. #1
    Gast

    LCD Write

    Hi!
    Bin ziemlich neu auf dem Gebiet C-Control und hab ne Frage zur letzten Routine. Wenn man im 4Bit-Modus arbeitet, dann werden doch die Daten in 2 Takten gesendet und beidesmal in den Datenbereich ganz vorne im byteport, also die ersten 4 Bits. Und wenns ein kommando is, dann in den ganzen byteport rein. Aber irgendwie versteh ich die routine nicht, eigentlich gar nicht! Außerdem ist bei B00100000 der 1er nicht an der Stelle vom RegisterSelect, des müsste doch heißen B00000100 oder? Und warum wird keine unterscheidung zwischen kommando und zeichen senden gemacht, bitte erklär mir das verständlich, ich versuchs schon seit längerem zu kapiern, wird aber net *Gg*


    Code:
     
    ' *** Daten-Definition ***
    define lcd_buf   byte                          'Zeichen oder Kommando
    define lcd_param byte
     
    ' *** Definition LCD-Ports ***
    define lcd_port  byteport[2]
    define lcd_rs    port[14]                      'Register Select
    define lcd_rw    port[13]                      'Read/Write
    define lcd_e     port[15]                      'Enable
     
    '*** Programmoperationen  ***
    gosub LCD_INIT
    pause 10
    end
     
    ' Display initialisieren
    #LCD_INIT
    lcd_port = OFF                                  'alle Ports auf 0 setzen
    lcd_param=&H38 : gosub LCD_WRITECMD             '8-Bit-Modus aktivieren
    lcd_port=&B00000010                             'mit 8-Bit-Command in 4-Bit-Modus umschalten
    pulse lcd_e
    lcd_param = &H28 : gosub LCD_WRITECMD           'ab jetzt 4-Bit-Modus
    lcd_param = &H0C : gosub LCD_WRITECMD           'Display einschalten, kein Cursor, kein Blinken
    return
     
    ' Display löschen
    #LCD_CLS
    lcd_param = &H02 : gosub LCD_WRITECMD           'Cursor home
    lcd_param = &H01 : gosub LCD_WRITECMD           'Display clear
    return
     
    ' Zeilenwechsel
    #LCD_GOTOLINE
    if lcd_param = 1 then lcd_param = &H80          'in 1. Zeile wechseln
    if lcd_param = 2 then lcd_param = &HC0          'in 2. Zeile wechseln
    goto LCD_WRITECMD
    return
     
    ' LCD-Kommando
    #LCD_WRITECMD
    lcd_buf = OFF                                   'Controlregister aktivieren
    goto LCD_WRITE
    return
     
    ' Zeichenausgabe
    #LCD_WRITECHAR
    lcd_buf = &B00100000                            'Datenregister aktivieren
    goto LCD_WRITE
    return
     
    ' Kommando oder Zeichen an Display senden
    #LCD_WRITE
    lcd_port = lcd_buf or (lcd_param shr 4)         'Hi-Nibble senden
    pulse lcd_e
    lcd_port = lcd_buf or (lcd_param and &H0F)      'Lo-Nibble senden
    pulse lcd_e
    return

  2. #2
    Gast
    Das kommt natürlich ganz drauf an wie du's zusammengelötet hast...

    Bei mir ist 00010000 Enable
    00100000 RS
    01000000 R/W

    Gruss, Jochen

  3. #3
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    14.12.2003
    Alter
    26
    Beiträge
    1.187
    Es wird doch ne Unterscheidung gemacht. Wenn man etwas schreibt ist RS high und wenn man Komandos gibt, low.

    Matthias
    Back on the road again...

    Falls ihr wissen wollt, was ich so in meiner roboterfreien Zeit gertieben hab: www.plasmaniac.de.vu

  4. #4
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    07.01.2004
    Ort
    München
    Alter
    66
    Beiträge
    214
    Hallo Gast,

    Die bits stehen nicht "ganz vorne", sondern "ganz hinten", im LOW nibble.
    Damit komme ich auch immer wieder durcheinander:


    1. Nummerierung der BITs (und auch der BYTEs / WORDs):
    In CC_BASIC wird immer "LOW to HIGH" nummeriert, beginnend mit 1. Das bedeutet:
    Die BITs im BYTEPORT[1] heissen BIT[1] bis BIT[8],
    und dabei ist BIT[1] das LSB (das mit dem niedrigsten Wert: "2 hoch 0" = 1),
    und BIT[8] das MSB (das mit dem höchsten Wert: "2 hoch 7" = 12.

    --- Ich nummeriere bits (und bytes..) eigentlich immer ab 0, nicht ab 1; das machen auch die meisten Assembler und Datenblätter so.

    --- Aber meine Verwechslungen entstehen oft auch dadurch:
    In CC-BASIC schreibt man bei Aufzählungen untereinander zuerst BIT[1] (LSB), dann BIT[2], .. bis BIT[8] (MSB),
    während ich das IMMER umgekehrt mache, nämlich zuerst bit_7 (MSB), dann bit_6, .. bis bit_0 (LSB).
    Ich bin's halt seit über 30 Jahren so gewohnt, und ich kann mir so aus den bit-Werten leichter den HEX Wert des Bytes zusammenbasteln; Dir gehts anscheinend genauso (siehe Punkt2).


    2. Der LCD_PORT ist definiert als BYTEPORT[2] und umfasst demnach die bit ports PORT[9] bis PORT[16].
    Dabei ist wieder PORT[9] das LSB und PORT[16] das MSB.
    PORT[9] bis PORT[12] ist also das niederwertige Halbbyte ("low nibble")
    und PORT[13] .. PORT[16] ist das high nibble dieses bytes.

    --- Also ist bei &B00100000 = &H20 im LCD_PORT = BYTEPORT[2] die "1" der PORT[14] (und das ist RS, siehe Punkt 4).


    3. Leitungen des LCD:
    RS = select command (0) or data (1)
    R/W (quer) = write to LCD (0) oder read from LCD (1)
    E = enable (pulse)
    DB0..DB3 = data LOW nibble; nur benutzt im LCD 8-bit modus; ignoriert im 4-bit mode (!!)
    DB4..DB7 = data HIGH nibble im 8-bit mode; im 4-bit-mode: zuerst high nibble, dann low nibble
    Die Nummerierung der data bits im LCD beginnt also mit 0 (nicht mit 1).


    4. Hardware-Beschaltung des BYTEPORT[2] für das LCD:
    Das low nibble des BYTEPORT[2] (also PORT[9]..PORT[12]) liegt am high (!!) nibble der LCD DATA, weil der 4-bit mode des LCD genutzt werden soll.
    Das high nibble des BYTEPORT[2] enthält die LCD Steuerleitungen, und zwar:
    PORT[13] liegt an RW des LCD (0 = "write to LCD"),
    PORT[14] liegt an RS des LCD (0 = "LCD command", 1 = "LCD data"),
    PORT[15] ist das LCD enable signal (wird gepulst),
    und PORT[16] ist nicht zum LCD verdrahtet.

    Das low nibble des LCD ist NICHT verdrahtet (braucht auch keine pull ups), weil hier ja der 4-bit-modus des LCD genutzt wird.


    5. Im LCD 4-bit-modus werden sowohl Data als auch Command in zwei Takten übertragen.
    Im ersten Takt steht das high nibble, und im zweiten Takt das low nibble des zu übertragenden Bytes im PORT[9]..PORT[12] ( = low nibble) des LCD_PORT.
    In beiden Fällen wird aber auch immer PORT[13]..PORT[16] gesetzt,
    wobei PORT[15] = ENABLE immer 0 ist
    und PORT[13] = RW ebenfalls immer 0 = "write to LCD" ist.
    PORT[16] ist nicht zum LCD verdrahtet, bedeutet also fürs LCD nix.

    Jeder Takt wird dem LCD mit einem pulse des PORT[15] (= LCD enable) signalisiert;
    erst jetzt interpretiert das LCD die anliegenden Daten, nämlich:
    PORT[9] .. PORT[12] = Wert des high nibble beim 1. Takt bzw. des low nibble beim 2. Takt;
    PORT[13] = RW = "Write to LCD";
    PORT[14] = RS = "data" (falls 1) oder "command" (falls 0).


    6. Die Übertragung von commands und data im 4-bit mode müsstest Du jetzt nachvollziehen können:
    LCD_WRITECMD setzt PORT[14] = RS = 0 = "LCD command",
    LCD_WRITECHAR dagegen PORT[14] = RS = 1 = "LCD data".
    Bei beiden ist PORT[13] = RW = 0 = "Write to LCD".
    Im LCD_WRITE wird zuerst das high nibble, und dann das low-nibble erzeugt und jeweils mit pulse LCD_E an das LCD übergeben.

    Für die Bedeutung der commands und der bits innerhalb der commands brauchst Du natürlich auch eine Beschreibung des LCD.


    7. Mit dem LCD_INIT soll das LCD in den 4-bit modus versetzt werden.

    Zuerst wird &H38 mit "gosub LCD_WRITECMD" ausgegeben.
    Ich erkläre mir das so, bin mir aber nicht ganz sicher (-- vielleicht kann jemand sagen, ob's stimmt --):

    FALLS das LCD zu diesem Zeitpunkt im 4-bit mode läuft, dann ist das EIN command ans LCD:
    001 = LCD command "FUNCTION SET" mit DL = 1 = "8-bit-mode", N = 1 = "display 2 lines" und F = 0 = "5x8 char matrix"

    FALLS ABER das LCD aber zu diesem Zeitpunkt bereits im 8-bit-mode war, z. B. nach power-on, dann erzeugt "gosub LCD_WRITECMD" jetzt ZWEI commands an das LCD:
    command 1 (ist das high nibble von &H3: 001 = LCD command "FUNCTION SET" mit DL = 1 = "8-bit-mode" ( + floatendes low nibble der LCD data Leitungen)
    command 2 (ist das low nibble von &H3: 1 = "Set DD-RAM address" auf wert 000 ( + floatendes low nibble der LCD data Leitungen)

    Egal wie: das LCD ist jetzt definitiv im 8-bit-mode.
    Das folgende "LCD_PORT = &B00000010 : pulse LCD_E" ist deshalb immer ein LCD command IM 8 BIT MODE (wird ja auch NICHT mit "gosub LCD_WRITECMD" ausgegeben, sonder direkt gepulst):
    PORT[13] = RW = 0 = "write to LCD",
    PORT[14] = RS = 0 = "LCD command" und
    PORT[9]..PORT[12] = low nibble = 0010; das liegt ja aber am HIGH (!!) nibble der LCD data. Also:
    001 = LCD command "FUNCTION SET" mit DL = 0 = "4-bit-mode" ( + floatendes low nibble der LCD data Leitungen)

    Jetzt ist das LCD also definitiv im 4-bit-mode,
    und die Ausgaben &H28 und &H0C mit "gosub LCD_WRITECMD" sind normale LCD commands im 4-bit modus:
    &H28 = 001 = "FUNCTION SET" mit DL = 0 = "4-bit-mode", N = 1 = "display 2 lines" und F = 0 = "5x8 char matrix"
    &H0C = 00001 = "DISPLAY" mit D = 1 = "Display on", C = 1 = "Cursor unsichtbar" und B = 0 = "blinken aus".


    UFF, ich hoffe das stimmt alles,
    sonst habe ich Dich jetzt sehr verwirrt!

  5. #5
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    14.12.2003
    Alter
    26
    Beiträge
    1.187
    Übrigens: Ich würd die "clear"-Routine nicht benutzen, sondern das, was weg sein soll einfach mit Leerzeichen übermalen, dann flimmerts nich so. Hier noch eine routiene, mit der man den Zeileninhalt nach rechts schieben kann. Wie man`s in beide Richtungen macht, poste ich später nochmal

    #lcd_shift
    parameter=&b00011100
    gosub LCD_WRITECMD
    return
    Back on the road again...

    Falls ihr wissen wollt, was ich so in meiner roboterfreien Zeit gertieben hab: www.plasmaniac.de.vu

  6. #6
    Gast
    sorry, noch immer ein paar fragen offen geblieben ..

    - warum bei lcd_buf das RS an der falschen stelle
    - wie muss man bei daten- bzw. kommando-senden vorgehen bzw. wohin muss man es schreiben
    - die zwei zeilen mit shr und and 0F erklären ..

  7. #7
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    14.12.2003
    Alter
    26
    Beiträge
    1.187
    1. Wenn man z.B. 01110101 versenden will schiebt man das gnze zuerst mal um 4 Stellen nach rechts: die Zahl 0111 entsteht. Dann nimmt man die Zahl von vorhin mit 00001111 and, das bedeutet, dass, wenn im vergleich und im ursprung eine 1 an der gleichen Stelle ist, kommt die dann aus dem rechenschritt raus, weil man nur die letzten vier nimmt, kommt die zahl 00000101 raus.
    2. Man schreibt den Buchstaben, den man schreiben will, im ASCII-Code in die Variable LCD_param. Dann gosubst du nach LCD_WRITECHAR und das Zeichen wird geschrieben. Wenn du eine Zeile auswälen möchtest, musst du 1 für Zeile 1 usw. in LCD_param schreiben. Dann gosubst du nach LCD_writecmd.
    3. Das este bit ist das höhste bit. Es hat den grösten wert. Die bits sind bim Byteport spiegelverkeht.

    Matthias
    Back on the road again...

    Falls ihr wissen wollt, was ich so in meiner roboterfreien Zeit gertieben hab: www.plasmaniac.de.vu

  8. #8
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    07.01.2004
    Ort
    München
    Alter
    66
    Beiträge
    214
    oder andersrum gesagt:

    "lcd_buf = &B00100000" setzt alle bits auf 0, ausser BIT[6].

    Später kommt dann für den ersten Takt

    "lcd_port = lcd_buf or (lcd_param shr 4)"

    Damit wird lcd_param zuerst mal um 4 bits nach rechts verschoben;
    aus einem lcd_param = "abcdefgh" wird damit "0000abcd": der ehemalige high nibble steht jetzt als low nibble drin.
    Dann wird noch der Inhalt von lcd_buf drauf ge-oder-t, also das "00100000", und deshalb steht jetzt "0010abcd" im lcd_param.
    Dieses "0010abcd" geht im ersten Takt an lcd_port, also an den BYTEPORT[2], an dem das LCD hängt.
    Und da ist diese "1" jetzt genau am pin "RS" des LCD angekommen, oder?

    Das

    lcd_port = lcd_buf or (lcd_param and &H0F)

    im zweiten Takt ist jetzt auch einfach:
    Mit dem AND wird aus lcd_param = "abcdefgh" zunächst "0000efgh": nur der ehemalige low nibble steht jetzt noch drin (immer noch als low nibble).
    Dann wird wieder der Inhalt von lcd_buf drauf ge-oder-t, also das "00100000", und deshalb steht "0010efgh" im lcd_param, bevor's ans LCD geht.

    Daten senden:
    Du musst jedes byte einzeln senden,
    wobei in lcd_param der Zeichencode stehen muss, z.b.
    lcd_param = &H41 : gosub lcd_writechar ' schreibt ASCII A
    lcd_param = &H42 : gosub lcd_writechar ' schreibt ASCII B
    lcd_param = &H33 : gosub lcd_writechar ' schreibt ASCII 3

    Kommandos senden:
    geht entsprechend, aber: du musst dazu die LCD commands genau kennen. Wenn Du z. B. auf die 1. Zeile positionieren willst, könntest Du schreiben

    lcd_param = &H80 : gosub lcd_writecmd

    weil das CMD &H80 genau an den Anfang der 1. Zeile positioniert.
    Aber normalerweise schickst du nicht selbst LCD commands durch die Gegend, sondern rufts einfach die Hilfs-Funktionen auf, wie z. b.

    lcd_param = 1 : gosub lcd_gotoline ' positioniert auf die 1. Zeile
    oder
    gosub lcd_cls ' löscht alles

    und die schicken dann für dich das LCD command raus (eins oder mehrere).

  9. #9
    Gast
    ok recht herzlichen dank

    und das letzte problem wäre noch, dass im byteport[2] ja folgendes drinsteht:

    d4 d5 d6 d7 | R/W RS EN X ... Bedeutung
    9 10 11 12 | 13 14 15 16 ... Pins

    d.h. warum wirds nicht so gemacht: lcd_buf = &B00000100

    dann wär das bit an stelle RS gesetzt!

  10. #10
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    07.01.2004
    Ort
    München
    Alter
    66
    Beiträge
    214
    ganz einfach:

    mit "lcd_buf = &B00000100" setzt Du das dritt-niedrigste bit auf eins; das heisst aber nicht PORT[14], sondern PORT[11], und ist deshalb nicht das EN - bit.

    Das BYTEPORT[2] ist schon so zum LCD verdrahtet, wie du's geschrieben hast, NUR:
    Du hast die Reihenfolge der bits in Deinem Bild verkehrt rum aufgemalt. PORT[9] ist derjenige mit dem niederigsten Wert; den musst Du ganz nach RECHTS zeichnen, wenn Du Dich nachher an diesem Bild orientieren willst, um den LCD_BUF mit bits zu laden:

    X EN RS RW d7 d6 d5 d4 ... Bedeutung für LCD
    16 15 14 13 12 11 10 9 ... PORT-Nummer der CC1

    Jetzt kannst Du schreiben: LCD_BUF = &B00100000;
    da gibst Du ja auch ganz RECHTS das Bit mit dem geringsten Wert an.
    Und das "RS" gehört ja in das dritt-höchste bit (PORT[14]), das muss also im Bild (und auch in der bit-Maske) an dritter Stelle von LINKS stehen.

+ Antworten
Seite 1 von 6 123 ... LetzteLetzte

Benutzer, die dieses Thema gelesen haben: 0

Derzeit gibt es keine Benutzer zum Anzeigen.

Berechtigungen

  • Neue Themen erstellen: Ja
  • Themen beantworten: Ja
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •