LCD über PCF8574 / TWI ansteuern

  • 1
  • 2
  • Page 1 of 2
jomixl
Benutzer
Avatar
Gender:
Posts: 223
Registered: 02 / 2008
Subject:

LCD über PCF8574 / TWI ansteuern

 · 
Posted: 20.05.2019 - 10:47  ·  #1
Hallo zusammen,
es gibt ja aus der Arduino-Welt eine kleine Platine mit einem PCF8574 mit der man ein normales
LCD über I2c betreiben kann.
Ich hab nun erfolglos versucht das mithilfe LCDios zum laufen zu bringen.
Das Programm hängt sich trotz $LCDNOINIT sofort auf sobald in der LCDios mehr drin steht als begin und end.
Hat schon mal jemand diesen Weg erfolgreich beschritten oder bin ich mal wieder auf dem Holzweg .....

Gruß Joachim
pvs-deck
PowerUser
Avatar
Gender:
Age: 52
Homepage: pvs-deck.de
Posts: 1340
Registered: 02 / 2009
Subject:

Re: LCD über PCF8574 / TWI ansteuern

 · 
Posted: 20.05.2019 - 16:44  ·  #2
Hallo Joachim,

der Weg ist eigentlich immer gleich.
Lass das LCDIOS erst mal raus, schaue Dir (meist in C) die Init und Schreib Funktionen in den DEMOS an.
Dann übernehme diese Funktion INIT und LCD-Write.

Sobald dies funktioniert, erst dann würde ich diese Funktionen mit dem LCDIO nutzen.

Sonst suchst Du evtl. Deine Probleme an der falschen Stelle.

Thorsten
Harry
Moderator
Avatar
Gender:
Location: zwischen Augsburg und Ulm
Age: 59
Posts: 2077
Registered: 03 / 2003
Subject:

Re: LCD über PCF8574 / TWI ansteuern

 · 
Posted: 20.05.2019 - 17:13  ·  #3
Hallöchen,

gibts nicht von Rolf eine Demo genau dafür?

Hab mal gelesen .... (falls was nicht stimmt, bitte korrigiert mich) ......

LCD (genau Zeilen-LCD) über PCF8574 bedeutet 4-Bit-Modus. Der normale Treiber arbeitet in diesem Modus aber nicht via I2C. Einfach die Daten umleiten. Naja einfach?
Ok LCDIOS, aber das Handbuch sagt
Quote
Wird das Display im 8-Bit Mode betrieben, kann die Initialisierung auch durch die System-Funktion "LCDSETUP" erfolgen. Diese initialisiert über "LCDIOS" das Display. Dazu muss der Compiler Schalter {$LCDNOINIT} aktiviert werden um die automatische Initialisierung abzuschalten.

Also 8-Bit aber das beisst sich mit dem PCF. Der Multiport-Treiber funktioniert über die PCF9555 also 2x8-Bit.

Harry
jomixl
Benutzer
Avatar
Gender:
Posts: 223
Registered: 02 / 2008
Subject:

Re: LCD über PCF8574 / TWI ansteuern

 · 
Posted: 21.05.2019 - 07:52  ·  #4
hallo zusammen,
leider konnte ich das Beispiel von Rolf nicht finden, aber ich hab schon versucht die Funktion der Arduino-Lib nachzubauen.
Ich hatte gehofft dass das mit der LCDIOS dann auch funktioniert und ich die LCD-Routinen benutzen kann, aber soweit kommt es ja garnicht denn das Programm verabschiedet sich sofort.
wenn in der LCDIOS mehr steht als begin und end hängt sich das Programm auf. Die LCDIOS wird wohl trotz LCDNOINIT beim Start aufgerufen.
Das mit den 8Bit hab ich so verstanden dass das ganze Byte in "cmd" steht, wenn ich das dann in der LCDIOS in low und Hinibble zerlege sollte das keinen Unterschied machen. Frame und Stack sind übertrieben groß ($100), daran sollte es auch nicht scheitern.

Hat überhaupt mal jemand mit der LCDIOS gearbeitet?


... inzwischen bin ich etwas weiter,
die LCDIOS verträgt kein TWIstat ......
nun hängt sich das Programm zumindest nicht mehr auf

Gruß Joachim
Harry
Moderator
Avatar
Gender:
Location: zwischen Augsburg und Ulm
Age: 59
Posts: 2077
Registered: 03 / 2003
Subject:

Re: LCD über PCF8574 / TWI ansteuern

 · 
Posted: 21.05.2019 - 08:16  ·  #5
Hallo Joachim,

hier ist die Demo:
Code
program LCD_IOS;

Device = 90S8535;

Import SysTick, SerPort, LCDport, ADCport;

From System Import ;

Define
        ProcClock   = 8000000;        {Hertz}
        SysTick     = 10;             {msec}
        StackSize   = $0030, iData;
        FrameSize   = $0030, iData;
        SerPort     = 9600;           {Baud}
        RxBuffer    = 16, iData;
        TxBuffer    = 16, iData;
        LCDport     = LCDUserPort;
        LCDtype     = 44780;          {66712}
        LCDrows     = 2, 2;           {2 x 2 rows}
        LCDcolumns  = 16;             {16 chars per line}
        ADCchans    = 4, iData;        {4 channels used}
        ADCpresc    = 256;            {prescaler 256}

Implementation

{$IDATA}

{--------------------------------------------------------------}
{ Type Declarations }

type
   arrT    = array[0..5] of byte;

{--------------------------------------------------------------}
{ Const Declarations }
const
    STX      : char   = #2;
    ETX      : char   = #3;

    arrLeft  : char   = #0;
    arrRight : char   = #1;
    arrUp    : char   = #2;
    arrDown  : char   = #3;
    arrUpDn  : char   = #4;
    degree   : char   = #5;

    Col0     : char   = #0;
    Col1     : char   = #1;
    Col2     : char   = #2;
    Col3     : char   = #3;
    ColF     : char   = #4;

    stc      : string   = 'ABCDE';
    cc       : byte     = 1;

{--------------------------------------------------------------}
{ Var Declarations }
{$PDATA}
var
  LCD_EN0[@PortA, 4]     : bit;
  LCD_EN1[@PortA, 5]     : bit;
  LCD_RS[@PortA, 6]      : bit;
  LCD_RW[@PortA, 7]      : bit;

{$IDATA}
var
   LCD1         : boolean;        // flag for LCD enable select
   st           : string[10];
   v1           : byte;
   bb           : byte;
   b1           : byte;
{ $NOINIT}
   ch, v2       : char;
   v3           : integer;
   v4           : word;
   bool,
   v5           : boolean;
   led[@porta, 7]: bit;

{--------------------------------------------------------------}
{ functions }
{$D-}
UserDevice LCDIOS(cmd : byte; data : byte) : byte;
begin
  (* commands passed to user defined function "LCDIOS" *)
  (*  0  init               data = none    result = none       init user's hardware   *)
  (*  1  select display     data = 0/1     result = none       select display 1 or 2  *)
  (*  2  write dataport     data = byte    result = none       character output       *)
  (*  3  read  dataport     data = none    result = byte       character input        *)
  (*  4  write controlport  data = byte    resul  = none       command to display     *)
  (*  5  read  controlport  data = none    result = byte       get display state      *)

  // this example uses the PortC/PinC as an 8bit I/O port to the display
  // the display is operated in 8bit mode
  // the display control lines are connected to PortA 5..7
  PortA:= PortA and $1F;                // all LCD control lines inactive
  case cmd of
    0  : // hardware init
         PortC:= 0;
         DDRC:= $FF;                    // all output
         DDRA:= DDRA or $E0;            // LCD control lines
         cmd:= 0;
       |
    1  : // select display
         LCD1:= data = 1;
         cmd:= 0;
       |
    2  : // write to data port
         LCD_RW:= false;
         LCD_RS:= true;
         PortC:= data;
         DDRC:= $FF;                    // all output
         if LCD1 then
           LCD_EN1:= true;
           uDelay(10);
           LCD_EN1:= false;
         else
           LCD_EN0:= true;
           uDelay(10);
           LCD_EN0:= false;
         endif;
       |
    3  : // read from dataport
         LCD_RW:= true;
         LCD_RS:= true;
         DDRC:= $00;                    // all input
         if LCD1 then
           LCD_EN1:= true;
           uDelay(10);
           cmd:= PinC;
           LCD_EN1:= false;
         else
           LCD_EN0:= true;
           uDelay(10);
           cmd:= PinC;
           LCD_EN0:= false;
         endif;
       |
    4  : // write to control port
         LCD_RW:= false;
         LCD_RS:= false;
         PortC:= data;
         DDRC:= $FF;                    // all output
         if LCD1 then
           LCD_EN1:= true;
           uDelay(10);
           LCD_EN1:= false;
         else
           LCD_EN0:= true;
           uDelay(10);
           LCD_EN0:= false;
         endif;
       |
    5  : // read from control port
         LCD_RW:= true;
         LCD_RS:= false;
         PortC:= $80;                   // Busy pin pull-up
         DDRC:= $00;                    // all input
         if LCD1 then
           LCD_EN1:= true;
           uDelay(10);
           cmd:= PinC;
           LCD_EN1:= false;
         else
           LCD_EN0:= true;
           uDelay(10);
           cmd:= PinC;
           LCD_EN0:= false;
         endif;
       |
  endcase;
  return(cmd);
end;
{$D+}

procedure portInit;
begin
  mDelay(10);
  // the system LCD-init can only be used if the display mode is 8bit wide!!
//   LCDSETUP;                             { let the driver initialize the display}

  if (LCDstat and $80) = 0 then    // LCD present ??
    LCDupper;
    LCDclr;                               { clear display 1 }
    LCDcursor(True, true);              { display 1 on, cursor off & no blink }
    LCDlower;
    LCDclr;                               { clear display 2 }
    LCDcursor(true, true);              { display 2 on, cursor off & no blink }

    st:= ByteToStr(cc : 4 : 'x');
    st:= 'Text'+ByteToStr(cc : 4 : 'x');
    Write(LCDout, 'Text'+ByteToStr(cc : 4 : 'x'));
    mDelay(10);

    LCDupper;
    (* user defined characters for 1. display *)
    LCDCharSet(Col0, $10, $10, $10, $10, $10, $10, $10, $10);      (* 1x | *)
    LCDCharSet(Col1, $18, $18, $18, $18, $18, $18, $18, $18);      (* 2x | *)
    LCDCharSet(Col2, $1c, $1c, $1c, $1c, $1c, $1c, $1c, $1c);      (* 3x | *)
    LCDCharSet(Col3, $1e, $1e, $1e, $1e, $1e, $1e, $1e, $1e);      (* 4x | *)
    LCDCharSet(ColF, $1f, $1f, $1f, $1f, $1f, $1f, $1f, $1f);      (* 5x | *)

    LCDlower;
    (* user defined characters for 2. display *)
    LCDCharSet(arrLeft,  $08, $0C, $0E, $0F, $0E, $0C, $08, $00);  (* arrow > *)
    LCDCharSet(arrRight, $02, $06, $0E, $1F, $0E, $06, $02, $00);  (* arrow < *)
    LCDCharSet(arrUp,    $04, $04, $0E, $0E, $1F, $1F, $00, $00);  (* arrow ^ *)
    LCDCharSet(arrDown,  $00, $00, $1F, $1F, $0E, $0E, $04, $04);  (* arrow v *)
    LCDCharSet(arrUpDn,  $04, $0E, $1F, $00, $00, $1F, $0E, $04);  (* arrow | *)
    LCDCharSet(degree,   $1C, $14, $1C, $00, $00, $00, $00, $00);  (* degree  *)
  endif;
end;

{--------------------------------------------------------------}
{ Main Program }
{$IDATA}

begin
  PortInit;
  EnableInts;

  st:= ' Test';
  LCDupper;
  LCDclr;                               { clear display 1 }
  LCDcursor(true, false);              { display 1 on, cursor off & no blink }
  LCDlower;
  LCDclr;                               { clear display 2 }
  LCDcursor(false, false);              { display 2 on, cursor off & no blink }

  LCDupper;
  LCDhome;                              { cursor home }
  Write(LCDout, 'E-LAB Computers');
  LCDxy(0, 1);                          { row 2 }
  Write(LCDout, 'LCD Test');
  LCDlower;
  LCDhome;                              { cursor home }
  Write(LCDout, '2 separate');
  LCDxy(0, 1);                          { row 2 }
  Write(LCDout, 'Displays');

//  mDelay(20);
  repeat
    mDelay(4);
    LCDupper;
    LCDoff;                             { display 1 off }
    LCDlower;
    LCDcursor(false, false);            { display 2 on, cursor off & no blink }
    inc(v1);
    mDelay(4);
    LCDupper;
    LCDcursor(false, false);            { display 1 on, cursor off & no blink }
    LCDlower;
    LCDoff;                             { display 2 off }
    inc(v1);
  until v1 > 20;

  LCDupper;
  LCDclr;                               { clear display 1 }
  LCDcursor(true, false);               { cursor on, blink off, display 1 on }
  LCDlower;
  LCDclr;                               { clear display 2 }
  LCDcursor(true, false);               { cursor on, blink off, display 1 on }
  v1:= 0;
  repeat
    if v1 < 16 then
      bb:= v1;
      b1:= 0;
    else
      bb:= v1 and $0f;
      b1:= 1;
    endif;
    LCDupper;
    LCDxy(bb, b1);
    LCDlower;
    bb:= 15 - bb;
    LCDxy(bb, b1);
    inc(v1);
    mDelay(4);
  until v1 = 32;

  LCDupper;
  LCDclr;                               { clear display 1 }
  LCDcursor(false, false);              { cursor off, blink off, display 1 on }
  Write(LCDout, 'User defined');
  LCDxy(0, 1);                          { row 2 }
  Write(LCDout, 'characters');

  LCDlower;
  LCDclr;                               { clear display 2 }
  LCDcursor(false, false);              { cursor off, blink off, display 2 on }
  v1:= 0;
  repeat
    LCDout(v1);
    LCDout(' ');
    mDelay(10);
    inc(v1);
  until v1 > 5;
  mDelay(20);

  v3:= -1234;
  v1:= 0;
  LCDupper;
  LCDclr;                               { clear display 1 }
  LCDlower;
  LCDclr;                               { clear display 2 }
  repeat
    toggle(led);
    LCDupper;
    LCDhome;                            { cursor home }
    Write(LCDout, 'Upper' +st);
    LCDxy(0, 1);                        { row 2 }
    bb:= 50-v1;
    Write(LCDout, ByteToStr(bb:6));
    LCDxy(8, 1);                        { row 2.8 }
    Write(LCDout, IntToStr(v3:8:2));

    LCDlower;
    LCDhome;                            { cursor home }
    Write(LCDout, 'Lower' +st);
    LCDxy(0, 1);                        { row 2 }
    Write(LCDout, ByteToStr(v1:6));
    LCDxy(8, 1);                        { row 2.8 }
    Write(LCDout, IntToStr(v4:8:2));

    inc(v1);
    inc(v4);
    inc(v3);
    MDelay(4);
  until v1 > 50;

  LCDupper;
  LCDclr;                               { clear display 1 }
  LCDcursor(false, false);              { cursor off, blink off, display 1 on }
  LCDlower;
  LCDclr;                               { clear display 2 }
  LCDcursor(false, false);              { cursor off, blink off, display 2 on }
  loop
    toggle(led);
    LCDupper;
    LCDhome;                            { cursor home }
    Write(LCDout, 'chan1 =');
    Write(LCDout, IntToStr(GetAdc(1):6:1));

    (* channel 2 as bargraph *)
    LCDxy(0, 1);                        { row 2 }
    v4:= GetAdc(2);
    bb:= byte((v4 * 16) div 1020) -1;
    v1:= 0;
    if bb < 16 then
      repeat
        LCDout(ColF);
        inc(v1);
      until v1 > bb;
    endif;
    bb:= byte((v4 * 8) div 102) mod 5;  (* (v4 * 80) div 1020 *)
    if bb > 0 then
      LCDout(bb-1);
      inc(v1);
    endif;
    while v1 < 16 do
      LCDout(' ');
      inc(v1);
    endwhile;

    LCDlower;
    LCDhome;                            { cursor home }
    Write(LCDout, 'chan3 =');
    ch:= char(b1 mod 6);
    Write(LCDout, IntToStr(GetAdc(3):6:1) + #5 +'C' +ch);
    LCDxy(0, 1);                        { row 2 }
    Write(LCDout, 'chan4 =');
    v4:= GetAdc(4);
    if v4 in[480..520] then
      ch:= arrUpDn;
    elsif v4 > 500 then
      ch:= arrUp;
    else
      ch:= arrDown;
    endif;
    Write(LCDout, IntToStr(v4:6:2) + ' ' +ch +' ');
    inc(b1);
    MDelay(1);
  end_loop;
end LCD_IOS.


Damit gearbeitet habe ich bisher nicht, nur mit dem GraphIOS. In der Demo sieht man gut, wie das mit dem LCDios funktioniert.

Harry
jomixl
Benutzer
Avatar
Gender:
Posts: 223
Registered: 02 / 2008
Subject:

Re: LCD über PCF8574 / TWI ansteuern

 · 
Posted: 21.05.2019 - 08:38  ·  #6
hallo Harry,
diese Demo hab ich gefunden, wir aber nicht über TWI angesteuert.
Schaut so aus als ob die LCDIOS das TWIstat nicht mag.

Joachim
Harry
Moderator
Avatar
Gender:
Location: zwischen Augsburg und Ulm
Age: 59
Posts: 2077
Registered: 03 / 2003
Subject:

Re: LCD über PCF8574 / TWI ansteuern

 · 
Posted: 21.05.2019 - 09:49  ·  #7
Hallo Joachim,

als erstes teste mal, ob der PCF8574 erreichbar ist. Achtung der PCF8574 hat eine andere Adresse als der PCF8574A.
Dann zur Funktion des LCDios (ich hab da auch ne ganze Weile gebraucht, bis ich das beim GraphIOS verstanden habe ;) )
Code

UserDevice LCDIOS(cmd : byte; data : byte) : byte; 
begin 
  (* commands passed to user defined function "LCDIOS" *) 
  (*  0  init               data = none    result = none       init user's hardware   *) 
  (*  1  select display     data = 0/1     result = none       select display 1 or 2  *) 
  (*  2  write dataport     data = byte    result = none       character output       *) 
  (*  3  read  dataport     data = none    result = byte       character input        *) 
  (*  4  write controlport  data = byte    resul  = none       command to display     *) 
  (*  5  read  controlport  data = none    result = byte       get display state      *)

Die Var cmd kann den Wert 0...5 haben und entsprechend ist im case cmd of das Programm anzupassen. D.h. cmd=0 ist init. Ein $LCDNOINIT setzt nur das außer Kraft und du mußt dein Init selber schreiben (außerhalb cmd=0). Da du vermutlich nur ein Display hast und dieses nicht lesen willst entfallen cmd=1 und cmd=3. Unter cmd=2 schreibst du ein Unterprogramm, das den Wert von "data" in 2 4-Bit-Werte aufteilt, die Statusleitungen des Displays richtig bedient und mit (mindestens) 2 TWIOut raus schickt. Du mußt ja im 4-Bit-Modus arbeiten ;)
Bei Grafikdisplays macht man das normalerwiese so, daß man eine Procedure schreibt, die die Datenausgabe erledigt und gleichzeitig nach Daten und Kommando unterscheidet.

Beispiel Grafik-LCD DOGM132 via SPI:
Code

Procedure WriteLCD(Arg: Byte; IsData: Boolean);
  Var Mask : Byte;
  Begin
    If IsData
      then
        Incl(PortA,2);                      // Daten
      else
        Excl(PortA,2);                      // Befehl
      EndIf;
    SPIOutByte1(Arg);                       // Output arg
  End WriteLCD;

Das kann man sicher bei Zeilen-LCDs auch so handhaben. Das Problem wird sicher das Aufteilen der Daten in 2 Nibble und die Bedienung der Statusleitungen auf den anderen 4 Bits sein. Wenn man hier z.B. den Write-Pin betätigt, dürfen natürlich dabei die Datenleitungen nicht verändert werden.

LCDios und auch GraphIOS wird vom Anwender niemals selber verwendet, das macht der Treiber unseres geschätzten Compilers!

Soweit alles klar?

Gruss
Harry
jomixl
Benutzer
Avatar
Gender:
Posts: 223
Registered: 02 / 2008
Subject:

Re: LCD über PCF8574 / TWI ansteuern

 · 
Posted: 21.05.2019 - 11:31  ·  #8
hallo Harry,
inzwischen läuft das display!
Ich hatte mir ein Schaltbild von der Adapterplatine runtergeladen und die Arduino-Lib nachempfunden.
War beides vergebens denn bei meinem Adapterboard ist der PCF8574 anders belegt als im Schaltbild und in der Lib ......
und kaum hatte ich das angepasst lief es auch schon mit der LCDIOS, wobei das mit dem TWIstat nicht zusammenhängt.

übrigens, die funktionen der LCDIOS lassen sich problemlos aus auch aus der App aufrufen.

nochmal danke für deine Mühe
Gruß Joachim
  • 1
  • 2
  • Page 1 of 2
Selected quotes for multi-quoting:   0

Registered users in this topic

Currently no registered users in this section

The statistic shows who was online during the last 5 minutes. Updated every 90 seconds.
MySQL Queries: 15 · Cache Hits: 14   138   152 · Page-Gen-Time: 0.033197s · Memory Usage: 2 MB · GZIP: on · Viewport: SMXL-HiDPI