mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik PCF 8574P + LCD


Autor: Gerald *. (pyromane)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi, ich hab hier ein LCD von Pollin(Bestellnr 120 420) welches ich per 
PCF 8574P steuere. Das LCD ist wie folgt an den PCF 8574P angebunden:

DB4 - P0
DB5 - P1
DB6 - P2
DB7 - P3
RS  - P4
RW  - P5
E   - P7

Die Initialisierung, Löschen, Kursorsteuerungen funktionieren ohne 
Probleme, jedoch werden einige Buchstaben nicht richtig dargestellt.

Ich möchte ein L auf den LCD anzeigen und übermittle dazu:
94h
1ms Pause
00h
1ms Pause
9Ch
1ms Pause
00h

Auf den LCD bekomme ich allerdings ein D angezeigt, obwohl hierfür eig 
folgendes übermittelt werden müsste:
94h
1ms Pause
00h
1ms Pause
94h
1ms Pause
00h

Dieser Fehler findet sich auch bei einigen anderen Zeichen, jedoch nicht 
bei allen.

Über Hinweise oder auch Lösungsvorschläge würde ich mich freuen.
Pyromane

Autor: Ago (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du toggelst neben dem EN auch das Command/Data usw.
Versuch einfach mal, bei der Datenübertragung nur Bit 7 (EN)zu toggeln, 
also:

94h
1ms Pause
14h
1ms Pause
9Ch
1ms Pause
1Ch

Wenn ich  mich recht erinnere, werden die Daten mit fallender Flanke 
übernommen. Habe gerade mal in meinen I2C Routinen (PIC) nachgesehen. Da 
mache es ich so ähnlich:

; lcd_config:
; Bit D0 to D3 are directly written to PCF8574(A) after being IORed with 
nibble data D4-D7
;       D0 = EN, default to H
;       D1 = RW, default to L (write to LCD)
;       D2 = RS, default to L (will be modified in LCD_Command/LCD_Data)
;       D3 = Display-Backlight, set to L (on)
...
                iorwf   lcd_temp, W
                call    IIC_Put
                andlw   0xfe            ; clear enable bit
                call    IIC_Put

Autor: Oliver Ju. (skriptkiddy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wahrscheinlich ist eine der Datenleitungen von PCF8574 zum Display nicht 
richtig angeschlosen.

tippe mal auf DB7.

Schau dir mal die binäre Codierung der Zeichen 'L' und 'D' an.

Autor: Klaus 2m5 (klaus2m5)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Pausen kannst Du Dir normalerweise sparen. I2C ist langsam genug 
(außer bei Clear/Home).

Autor: Gerald *. (pyromane)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Antworten

Ago schrieb:
> 94h
> 1ms Pause
> 14h
> 1ms Pause
> 9Ch
> 1ms Pause
> 1Ch
Es erscheint auf dem LCD leider wieder ein D

Skript Kiddy schrieb:
> Wahrscheinlich ist eine der Datenleitungen von PCF8574 zum Display nicht
> richtig angeschlosen.
Alle Pins wurden durchgemessen.

Skript Kiddy schrieb:
> Schau dir mal die binäre Codierung der Zeichen 'L' und 'D' an.
L = 0100 9
D = 0100 0100
(Leerstellen wurden zu besseren Übersicht hinzugefügt)

Klaus 2m5 schrieb:
> Die Pausen kannst Du Dir normalerweise sparen. I2C ist langsam genug
> (außer bei Clear/Home).
Danke für die Info.

Autor: Oliver Ju. (skriptkiddy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
L = 0100 1100
D = 0100 0100

Die beiden unterscheiden sich nur in einem Bit. Das würde ich als 
Grundlage für die Fehlersuche ansetzen.

Schreib mal  1100 1100 = 0xCC  als Zeichen auf das Display.

Wenn mit dem DB7 was nicht stimmt müsste dabei ein 'D' auf dem Display 
erscheinen. Denn Bit 3 und Bit 7 des Zeichens werden ja über DB7 
übertragen.

Gruß

Das Skriptende Kind

Autor: Gerald *. (pyromane)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab folgendes übertragen
9Ch
00h
9Ch
00h
und das Zeichen im Anhang erhalten.

Anmerkung:
"Display aus" benötigt den DB7 und dieser Befehl wird problemlos 
ausgeführt.

Autor: Oliver Ju. (skriptkiddy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gerald O. schrieb:
> Ich hab folgendes übertragen
> 9Ch
> 00h
> 9Ch
> 00h
> und das Zeichen im Anhang erhalten.

OK. Dann scheint es ein Software-Problem zu sein.

Kannste du mal deine Sourcen Posten?

Autor: Gerald *. (pyromane)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich verwende die AVR-NET-IO mit Ethersex Firmware. Die I2C Befehle 
werden von einem AutoIT Skript per TCP an die AVR-NET-IO übermittelt. 
Der Debug Modus in der Ehtersex Firmware ist aktitviert und somit kann 
ich sicher sein das die I2C Befehler richtig übertragen werden.
Keine elegante Lösung aber ich habe leider gerade keinen Zugriff auf 
einen Brenner. :/

AutoIT Skript dennoch posten?

Autor: Oliver Ju. (skriptkiddy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja.

Autor: Gerald *. (pyromane)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
$tab0data ist ein Input Feld
$cm* listet die übermittelten und empfangenen Befehle/Nachrichten auf
_BinaryToHexString ist eine Funktion um Binärwerte in hexadezimale 
Zahlen zu wandeln, die Funktion wurde schon mehrfach mit Diversen Tool 
gegengeprüft.
$laenge = stringlen(GUICtrlRead($tab0data))
if $laenge > 0 Then
  if $laenge > 20 Then
    $data = StringLeft(GUICtrlRead($tab0data), 20)
  Else
    $data = GUICtrlRead($tab0data)
  EndIf

  $data2 =""
  for $t=1 to $laenge  ;jeden Buchstaben im String
    $asciicode=asc(stringmid($data,$t,1))  ;in asciicode umwandeln
    for $i=7 to 0 step -1   ;asciicode in bits
      if bitand($asciicode,2^$i) then
        $data2&="1"
      else
        $data2&="0"
      endif
    next
  next

  For $i = 1 To (($laenge * 2) - 1) +1
    $zw1 = StringLeft($data2, (4*$i))
    $zw1 = StringRight($zw1, 4)
    $zw2 = "1001" & $zw1
    $zw3 = _BinaryToHexString($zw2)
  
    ;Enable ein + Befehl übermitteln
    $bef = "pcf8574x set 1 0 " & $zw3
    TCPSend($socket, $bef  & @CRLF)
    sleep(1)
    $recv = TCPRecv( $socket, 2048)
    If $recv <> "" Then
      GUICtrlSetData($cmd, " < " & $bef & @CRLF & " > " & $recv & @CRLF, true)
    endif
          
    ;Enable aus
    $bef = "pcf8574x set 1 0 00"
    TCPSend($socket, $bef  & @CRLF)
    sleep(1)
    $recv = TCPRecv( $socket, 2048)
    If $recv <> "" Then
      GUICtrlSetData($cmd, " < " & $bef & @CRLF & " > " & $recv & @CRLF, true)
    endif
    sleep(20)
  Next
EndIf

Autor: Oliver Ju. (skriptkiddy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Super kommentiert.

Na mal schauen, ob es Jemanden gibt, der sich das bei der Hitze antut.

Autor: Ago (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Boah... :-)

Also wenn ich das richtig überblicke, enthält $data2 den kompletten 
String data, und zwar jeweils 8 "Bit" als String aus 0 und/oder 1...

  For $i = 1 To (($laenge * 2) - 1) +1
    $zw1 = StringLeft($data2, (4*$i))
    $zw1 = StringRight($zw1, 4)
    $zw2 = "1001" & $zw1
    $zw3 = _BinaryToHexString($zw2)

...

  For $i = 1 To (($laenge * 2) - 1) +1
    $zw1 = StringMid($data2, (4*$i)-3, 4)
    $zw2 = _BinaryToHexString($zw1)

    ;Enable ein + Befehl übermitteln
    $bef = "pcf8574x set 1 0 9" & $zw2
...

    ;Enable aus
    $bef = "pcf8574x set 1 0 1" & $zw2
...

Autor: Ago (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oder gleich so (ohne Garantie natürlich, habe aber die internen 
Funktionen genutzt (lt. http://www.autoitscript.com/autoit3/docs/ ).

$data = GUICtrlRead($tab0data)
$laenge = StringLen($data)
if $laenge > 0 Then
  if $laenge > 20 Then
    $laenge = 20
    $data = StringLeft($data, 20)
  EndIf

  $data2 ="" ; Das wird unser Hex-String
  for $t=1 to $laenge  ;jeden Buchstaben im String
    $asciicode=asc(StringMid($data,$t,1))  ;in asciicode umwandeln
    $data2 &= Hex($asciicode, 2)           ;und dann in hex (2stellig)
  next

  For $i = 1 To ($laenge * 2)
    $zw1 = StringMid($data2, $i, 1)

    ;Enable ein + Befehl übermitteln
    $bef = "pcf8574x set 1 0 9" & $zw1
    TCPSend($socket, $bef  & @CRLF)
    sleep(1)
    $recv = TCPRecv( $socket, 2048)
    If $recv <> "" Then
      GUICtrlSetData($cmd, " < " & $bef & @CRLF & " > " & $recv & @CRLF, 
true)
    endif

    ;Enable aus
    $bef = "pcf8574x set 1 0 1" & $zw1
    TCPSend($socket, $bef  & @CRLF)
    sleep(1)
    $recv = TCPRecv( $socket, 2048)
    If $recv <> "" Then
      GUICtrlSetData($cmd, " < " & $bef & @CRLF & " > " & $recv & @CRLF, 
true)
    endif
    sleep(20)
  Next
EndIf

Autor: Gerald *. (pyromane)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für die Antworten

Ago schrieb:
> Also wenn ich das richtig überblicke, enthält $data2 den kompletten
> String data, und zwar jeweils 8 "Bit" als String aus 0 und/oder 1...
Ja, $data2 enthält den Wert aus $data in binärer Form

Ago schrieb:
>     $zw1 = StringMid($data2, (4*$i)-3, 4)
Danke, hatte ich lange gesucht

Ago schrieb:
>     ;Enable ein + Befehl übermitteln
>     $bef = "pcf8574x set 1 0 9" & $zw2
Kurze Erklärung:
pcf8574x set I2C Adressen PCF8574/PCF8574A wert
Ich verwende den PCF8574 mit A0 = 1, A1+A2 = 0 daraus ergibt sich dann 
folgendes:
pcf8574x set 1 0 wert
wert ist in meinem Fall $zw3

Ich habe den gesamten Code mit Kommentaren versehen
$laenge = stringlen(GUICtrlRead($tab0data))   ;Länge der Daten feststellen
if $laenge > 0 Then                           ;prüfen ob Daten vorhanden sind
  if $laenge > 20 Then                        ;Anzeige auf 20 Zeichen limitieren und in $data speichern
    $data = StringLeft(GUICtrlRead($tab0data), 20)
  Else
    $data = GUICtrlRead($tab0data)            ;direkt in $data speicher, da kleiner als 20 Zeichen
  EndIf

  $data2 =""                                  ;Variable anlegen, wird binär $data enthalten
  for $t=1 to $laenge                         ;jeden Buchstaben im String
    $asciicode=asc(stringmid($data,$t,1))     ;in asciicode umwandeln
    for $i=7 to 0 step -1                     ;asciicode in Bits
      if bitand($asciicode,2^$i) then
        $data2&="1"
      else
        $data2&="0"
      endif
    next
  next

  For $i = 1 To (($laenge * 2) - 1) +1      ;Daten fürs übermitteln aufbereiten
  $zw1 = StringMid($data2, (4*$i)-3, 4)     ;Nibble filtern
  $zw2 = "1001" & $zw1                      ;um Steuerdaten erweitern
  $zw3 = _BinaryToHexString($zw2)           ;binäre Daten in hex wandeln
  
    ;Enable ein + Befehl/Daten übermitteln
    $bef = "pcf8574x set 1 0 " & $zw3       ;I2C Befehl erstellen
    TCPSend($socket, $bef  & @CRLF)         ;Befehl an AVR-NET-IO übermitteln
    sleep(1)
    $recv = TCPRecv( $socket, 2048)         ;Antwort speichern
    If $recv <> "" Then                     ;Befehl + Antwort anzeigen
      GUICtrlSetData($cmd, " < " & $bef & @CRLF & " > " & $recv & @CRLF, true)
    endif
          
    ;Enable aus
    $bef = "pcf8574x set 1 0 00"           ;I2C Befehl(=enable aus) erstellen
    TCPSend($socket, $bef  & @CRLF)        ;Befehl an AVR-NET-IO übermitteln
    sleep(1)
    $recv = TCPRecv( $socket, 2048)        ;Antwort speichern
    If $recv <> "" Then                    ;Befehl + Antwort anzeigen
      GUICtrlSetData($cmd, " < " & $bef & @CRLF & " > " & $recv & @CRLF, true)
    endif
    sleep(20)
  Next
EndIf

Edit: die Funktion Hex() hatte bei mir leider nicht den gewünschten 
Effekt gebracht.

Autor: Ago (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gerald O. schrieb:
> Ago schrieb:
>>     ;Enable ein + Befehl übermitteln
>>     $bef = "pcf8574x set 1 0 9" & $zw2
> Kurze Erklärung:
> pcf8574x set I2C Adressen PCF8574/PCF8574A wert
> Ich verwende den PCF8574 mit A0 = 1, A1+A2 = 0 daraus ergibt sich dann
> folgendes:
> pcf8574x set 1 0 wert
> wert ist in meinem Fall $zw3

So wie ich das sehe, entspricht zw3 in deinem Fall auch "nur" dem 8-Bit 
Wert in Hexform, oder?

Da du ja die "1001" + 4-Bit Nibble als Hexzahl rüberschiebst, sendest du 
also immer "pcf8574x set 1 0 9x" wobei x dem Hex-nibble entspricht.

Nichts anderes sollte bei

$bef = "pcf8574x set 1 0 9" & $zw2

passieren. $zw2 enthält ja bei mir direkt den Hexwert aus $data2.

$bef = "pcf8574x set 1 0 00"           ;I2C Befehl(=enable aus) 
erstellen

Wenn das "00" das Byte ist, welches an den PCF ausgegeben wird, dann 
änderst du auch gleichzeitig mit dem Enable das "RS", wechselst also vom 
Daten in den Command-Modus (während das 2. Nibble ja eigentlich noch 
übertragen werden soll). Das kann nicht gehen.

Autor: Gerald *. (pyromane)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe in der Zwischenzeit noch mal bezüglich LCDs nachgelesen. Man 
darf nur den Enable Pin toggelen, mein Fehler :/

Ich werde die Initialisierung und die restlichen Teile entsprechend 
anpassen, hoffe danach ist der Fehler verschwunden, auf jeden Fall melde 
ich mich danach noch einmal(wahrscheinlich morgen).

Vielen Dank für die Infos und Hinweise.

Autor: Klaus 2m5 (klaus2m5)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gerald O. schrieb:
> Ich habe in der Zwischenzeit noch mal bezüglich LCDs nachgelesen. Man
> darf nur den Enable Pin toggelen, mein Fehler :/

Genau das stand in der ersten Antwort.

Gerald O. schrieb:
> Ago schrieb:
>> 94h
>> 1ms Pause
>> 14h
>> 1ms Pause
>> 9Ch
>> 1ms Pause
>> 1Ch
> Es erscheint auf dem LCD leider wieder ein D

Hat doch angeblich nicht funktioniert.

Autor: Gerald *. (pyromane)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Leider hat auch das Überarbeiten des Skriptes nicht den gewünschten 
Effekt gezeigt und es wurden immer noch falsche Buchstaben angezeigt.

Ich habe mal die gesamten Großbuchstaben versucht und bin auf folgendes 
gekommen:

SOLL  IST    SOLL         IST

H      @    0100 1000   0100 0000
J      B    0100 1010   0100 0010
L      D    0100 1100   0100 0100
M      E    0100 1101   0100 0101
N      F    0100 1110   0100 0110
O      G    0100 1111   0100 0111
X      P    0101 1000   0101 0000
Z      R    0101 1010   0101 0010

Nachdem ich mein Multimeter auf den betreffenden Pin gehängt habe und 
das Skript erneut laufen lassen habe war der Fehler auf einmal weg. >> 
Kapazitives Problem,
Aus Interesse versuchte ich dann noch mein altes Skript, welches auch 
Fehlerfrei funktionierte.

Vielen Dank für die zahlreichen Tipps und auch Lösungsvorschläge.

Autor: Klaus 2m5 (klaus2m5)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das stand schon in Antwort #2:

Skript Kiddy schrieb:
> Wahrscheinlich ist eine der Datenleitungen von PCF8574 zum Display nicht
> richtig angeschlosen.
>
> tippe mal auf DB7.

Autor: Gerald *. (pyromane)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus 2m5 schrieb:
> Das stand schon in Antwort #2:
>
> Skript Kiddy schrieb:
>> Wahrscheinlich ist eine der Datenleitungen von PCF8574 zum Display nicht
>> richtig angeschlosen.
>>
>> tippe mal auf DB7.

Ich hatte an den PINs eine Pegel von 4,95V gemessen, jedoch sagt das 
leider nichts über die Flanken aus.
Nebenbei wurde "Display aus" immer ordnungsgemäß ausgeführt und dieser 
Befehl benötigt DB7.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gerald O. schrieb:
> Klaus 2m5 schrieb:
>> Das stand schon in Antwort #2:
>>
>> Skript Kiddy schrieb:
>>> Wahrscheinlich ist eine der Datenleitungen von PCF8574 zum Display nicht
>>> richtig angeschlosen.
>>>
>>> tippe mal auf DB7.
>
> Ich hatte an den PINs eine Pegel von 4,95V gemessen, jedoch sagt das
> leider nichts über die Flanken aus.

Bei deinen Wartezeiten bis zum Toggeln des E-Pins sind die Flanken 
ziemlich egal. Ich tippe eher auf eine kalte Lötstelle oder sowas 
ähnliches. Wenn du jetzt mit deinem Multimeter draufgehst, schliesst du 
den Kontakt, der ansonsten offen ist.

Autor: Klaus 2m5 (klaus2m5)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Bei deinen Wartezeiten bis zum Toggeln des E-Pins sind die Flanken
> ziemlich egal. Ich tippe eher auf eine kalte Lötstelle oder sowas
> ähnliches. Wenn du jetzt mit deinem Multimeter draufgehst, schliesst du
> den Kontakt, der ansonsten offen ist.

Sehe ich auch so. Keiner kann vorhersagen, was bei einer instabilen 
hochohmigen Verbindung passiert und wann das Signal am Empfänger 
tatsächlich dem gesendeten entspricht oder wann nicht.

Autor: Gerald *. (pyromane)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Bei deinen Wartezeiten bis zum Toggeln des E-Pins sind die Flanken
> ziemlich egal. Ich tippe eher auf eine kalte Lötstelle oder sowas
> ähnliches. Wenn du jetzt mit deinem Multimeter draufgehst, schliesst du
> den Kontakt, der ansonsten offen ist.
Ich greife das Signal mit Klemmen am DB7 ab, sobald ich die 
Messleitungen am Multimeter abstecke tritt der Fehler wieder auf.
Beim übertragen der Werte 94h 14h an den PCF8574 merkte ich einen 
kurzzeitigen Spannungseinbruch auf 3,6V am BD7, jedoch nicht an den 
anderen PINs. Leider ist das Multimeter zu träge um genaueres zu sagen.

Wünsche noch einen schönen Abend
Gruß Pyromane

Autor: OpenCollectör (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Pullups an die PCF-Ausgänge.

Also 4k7 (oder irgendwas zwischen 1k und 15k) zwischen + und jede der 
acht Leitungen zwischen PCF und LCD.

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.