20x4 LCD display with an I2C interface

How to interface TWI with an i2C display?

JAG
Benutzer
Avatar
Geschlecht:
Herkunft: Mexico
Alter: 61
Beiträge: 18
Dabei seit: 07 / 2008
Betreff:

20x4 LCD display with an I2C interface

 · 
Gepostet: 09.06.2023 - 18:00 Uhr  ·  #1
AVRCO and the LCDport 4bit-mode library have been used for quite some time with the AtMega128-16AU in our systems. It is now necessary to save the processor lines to free TX2/RX2 of port D, which was previously used for LCDPort.

We plan to use a 20x4 LCD display with an I2C interface connected to an AtMega TWI (SCL, SDA).

I would appreciate if you could provide a brief example of how to accomplish this new interface. I greatly appreciate your help in advance.
Der an diesem Beitrag angefügte Anhang ist entweder nur im eingeloggten Zustand sichtbar oder die Berechtigung Deiner Benutzergruppe ist nicht ausreichend.
Harry
Moderator
Avatar
Geschlecht:
Herkunft: zwischen Augsburg und Ulm
Alter: 60
Beiträge: 2155
Dabei seit: 03 / 2003
Betreff:

Re: 20x4 LCD display with an I2C interface

 · 
Gepostet: 09.06.2023 - 19:27 Uhr  ·  #2
Can you tell me which display should be used exactly?

Or do you want to connect the display to a PCA9554 or PCF8574?
golf
Benutzer
Avatar
Geschlecht:
Herkunft: Donauwörth
Alter: 72
Beiträge: 266
Dabei seit: 11 / 2009
Betreff:

Re: 20x4 LCD display with an I2C interface

 · 
Gepostet: 09.06.2023 - 19:31 Uhr  ·  #3
Hallo Jag,

ich hab hier mal was vor Jahren editiert, ohne Gewähr

Import LCDPort mit defines ....... LCDrows= 4; LCDcolumns= 20;


// pulse En mit Verzögerungen
procedure pulseEn(data : byte);
begin
//TWIout(LcdAdr, data or En);
I2Cout(LcdAdr, data or En);
udelay(1);
//TWIout(LcdAdr, data and not (En));
I2Cout(LcdAdr, data and not (En));
udelay(50);
end;
//------------------------------------------------------------------------------------------------------
// schreibe 4 Bit
// Daten und Steuerleitungen stehen in data
procedure write4bits(data : byte);
begin
data:= data or Backlight;
//TWIout(LcdAdr, data);
I2Cout(LcdAdr, data);
pulseEn(data);
end;
//------------------------------------------------------------------------------------------------------
// lese 4 Bit
// Daten und Steuerleitungen stehen in data
// gelesene Daten stehen im hiNibble
function read4bits(data : byte) : byte;
var
ip : byte;
begin
data:= $F0 or data or Backlight;
//TWIout(LcdAdr, data); //
I2Cout(LcdAdr, data);
//TWIout(LcdAdr, data or En); // En auf 1
I2Cout(LcdAdr, data or En); // En auf 1
udelay(5);
//TWIinp(LcdAdr, ip); // HighNibble einlesen
I2Cinp(LcdAdr, ip); // HighNibble einlesen
//TWIout(LcdAdr, data); // En zurückauf 0
I2Cout(LcdAdr, data); // En zurückauf 0
udelay(20);
return(ip); // die Daten stehen im HiNibble
end;
//------------------------------------------------------------------------------------------------------

procedure init_lcd;
begin
mdelay(50);
write4bits($30);
mdelay(5);
write4bits($30);
mdelay(5);
write4bits($30);
udelay(10);
write4bits($20);
udelay(10);

lcdctrl(%00001100); // Display on, Cursor aus
lcdctrl(%00010100); // shift Cursor nach rechts
lcdctrl(%00000110); // autoincrement
lcdclr;
Backlight:= BL; // Backlight ein
end;
//------------------------------------------------------------------------------------------------------

userdevice LCDIOS(cmd, data : byte) : byte;
var
mode : byte;
loN, hiN : 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 *)

// Writeln(Serout, bytetostr(cmd) + ', ' + bytetobin(data));

// if TWIstat(LcdAdr) then
case cmd of
0 : // hardware init
//TWIout(LcdAdr, $F8); // all LCD control lines inactive
I2Cout(LcdAdr, $F8); // Backlight on
cmd:= 0;
|
1 : // select display
cmd:= 0;
|
2 : // write to data port : Rs = true, Rw := false
mode:= Rs;
hiN:= data and $F0;
loN:= (data and $0F) shl 4;
write4bits(hiN or mode);
write4bits(loN or mode);
|
3 : // read from data port : Rs,Rw = true
mode:= Rw or Rs;
hiN:= read4bits(mode);
hiN:= (hiN and $F0);

loN:= read4bits(mode);
loN:= (loN shr 4) and $0F;
cmd:= hiN or loN;

|
4 : // write to control port : Rs = false, Rw := false
mode:= 0;
hiN:= data and $F0;
loN:= (data and $0F) shl 4;
write4bits(hiN or mode);
write4bits(loN or mode);
|

5 : // read from control port : Rs = false, Rw = true;
mode:= Rw;
hiN:= read4bits(mode);
hiN:= (hiN and $F0);

loN:= read4bits(mode);
loN:= (loN shr 4) and $0F;
cmd:= hiN or loN;
|
endcase;

// endif;

return(cmd);
end;
//------------------------------------------------------------------------------------------------------




// im main programm

init_lcd;

LCDxy(0, 0); //
Write(LCDout, 'line 0');
LCDxy(5, 1); //
Write(LCDout, 'line 1');
LCDxy(2, 2); //
Write(LCDout, 'LINE 2');
LCDxy(10, 3); //
Write(LCDout, 'line 3');


-----------------
golf
JAG
Benutzer
Avatar
Geschlecht:
Herkunft: Mexico
Alter: 61
Beiträge: 18
Dabei seit: 07 / 2008
Betreff:

Re: 20x4 LCD display with an I2C interface

 · 
Gepostet: 09.06.2023 - 20:08 Uhr  ·  #4
Zitat geschrieben von Harry

Can you tell me which display should be used exactly?

Or do you want to connect the display to a PCA9554 or PCF8574?


the I2C module is PCF8574T connected to a 44780 compatible 4x20 display. Thank you.
golf
Benutzer
Avatar
Geschlecht:
Herkunft: Donauwörth
Alter: 72
Beiträge: 266
Dabei seit: 11 / 2009
Betreff:

Re: 20x4 LCD display with an I2C interface

 · 
Gepostet: 10.06.2023 - 06:29 Uhr  ·  #5
Hallo JAG,

ich hab gerade gesehen, daß dieser Source aus dem Forum stammt.
Beitrag : LCD über PCF8574 / TWI ansteuern vom 21.5.2019

topic.php?t=3778&page=2

Gruß
golf
JAG
Benutzer
Avatar
Geschlecht:
Herkunft: Mexico
Alter: 61
Beiträge: 18
Dabei seit: 07 / 2008
Betreff:

Re: 20x4 LCD display with an I2C interface

 · 
Gepostet: 10.06.2023 - 15:12 Uhr  ·  #6
I appreciate Golf and Harry's guidance on LCD-I2C implementation, I'll keep posting results here.
JAG
Benutzer
Avatar
Geschlecht:
Herkunft: Mexico
Alter: 61
Beiträge: 18
Dabei seit: 07 / 2008
Betreff:

Re: 20x4 LCD display with an I2C interface

 · 
Gepostet: 13.06.2023 - 23:33 Uhr  ·  #7
Based on the sample code kindly posted in this thread, here is a fully debugged example of an AvrCo AtMega128 working with an I2C 20x4 LCD display shown above.


program TWIDisplay;

{$NOSHADOW}
{ $WG} {global Warnings off}

Device = mega128, VCC = 5.0;
{ $BOOTRST $0F000} {Reset Jump to $0F000}

Define_Fuses
// Override_Fuses;
NoteBook = A;
Supply = 5.0, 100;
LockBits0 = [];
FuseBits0 = [];
FuseBits1 = [SPIEN, JTAGEN, OCDEN];
FuseBits2 = [];

import SysTick, SerPort, TWImaster, LCDport;

from System import;

define
ProcClock = 16000000; {Hertz}
SysTick = 10; {msec}
StackSize = $0100, iData;
FrameSize = $0100, iData;

LCDport = LcdUserPort;
LCDtype = 44780; {66712}
LCDrows = 4; {4 rows}
LCDcolumns = 20; {20 chars per line}

TWIpresc = TWI_BR400;

SerPort = 19200, Stop2; {Baud, StopBits|Parity}
RxBuffer = 32, iData;
TxBuffer = 60, iData;


implementation

{$IDATA}

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

type


{--------------------------------------------------------------}
{ Const Declarations }
const
// this example uses the PCF8574 as an 8bit I/O port to the display
// the display is operated in 4bit mode
// the display control lines are connected to PCF8574 0..3
// the display data lines are connected to PCF8574 4..7

// Belegung des PCF8574(a)
// Achtung: es gibt wohl auch Displays die anders belegt sind !!
// HiNibble = Daten
// LowNibble = Steuerleitungen
En : byte = %0100;// Enable bit
Rw : byte = %0010;// Read/Write bit : 0= write
Rs : byte = %0001;// Register select bit : 0=Instruction Register
BL : byte = %1000;// Backlight on

// PCF8574 I2C address alle Address-Leitungen offen
LcdAdr : byte = $27;
// PCF8574A I2C address alle Address-Leitungen offen
// LcdAdr : byte = $3F;

{--------------------------------------------------------------}
{ Var Declarations }
{$IDATA}
var

led[@portB, 5] : bit;
Backlight : byte;

t1000ms : Systimer;

cnt : byte;
{--------------------------------------------------------------}
{ functions }

procedure InitPorts;
begin
portB := %00000000; //nc,nc,led,nc,nc,nc,nc,nc
ddrB := %00100000;

portC := %00110000;
ddrc := %00110000;

end;


// pulse En mit Verzögerungen
procedure pulseEn(data : byte);
begin
TWIout(LcdAdr, data or En);
udelay(1);
TWIout(LcdAdr, data and not (En));
udelay(50);
end;

// schreibe 4 Bit
// Daten und Steuerleitungen stehen in data
procedure write4bits(data : byte);
begin
data := data or Backlight;
TWIout(LcdAdr, data);
pulseEn(data);
end;

// lese 4 Bit
// Daten und Steuerleitungen stehen in data
// gelesene Daten stehen im hiNibble
function read4bits(data : byte) : byte;
var
ip : byte;
begin
data := $F0 or data or Backlight;
TWIout(LcdAdr, data); //
TWIout(LcdAdr, data or En); // En auf 1
udelay(5);
TWIinp(LcdAdr, ip); // HighNibble einlesen
TWIout(LcdAdr, data); // En zurückauf 0
udelay(20);
return(ip); // die Daten stehen im HiNibble
end;



// initialiseire LCD
procedure init_lcd;
begin
mdelay(50);
write4bits($30);
mdelay(5);
write4bits($30);
mdelay(5);
write4bits($30);
udelay(10);
write4bits($20);
udelay(10);

lcdctrl(%00001100); // Display on, Cursor aus
lcdctrl(%00010100); // shift Cursor nach rechts
lcdctrl(%00000110); // autoincrement
lcdclr;
Backlight := BL; // Backlight ein
end;



userdevice LCDIOS(cmd, data : byte) : byte;
var
mode : byte;
loN, hiN : 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 *)

// Writeln(Serout, bytetostr(cmd) + ', ' + bytetobin(data));


// if TWIstat(LcdAdr) then
case cmd of
0 : // hardware init
TWIout(LcdAdr, $F8); // all LCD control lines inactive
// Backlight on
cmd := 0;
|
1 : // select display
cmd := 0;
|
2 : // write to data port : Rs = true, Rw := false
mode := Rs;
hiN := data and $F0;
loN := (data and $0F) shl 4;
write4bits(hiN or mode);
write4bits(loN or mode);
|
3 : // read from data port : Rs,Rw = true
mode := Rw or Rs;
hiN := read4bits(mode);
hiN := (hiN and $F0);

loN := read4bits(mode);
loN := (loN shr 4) and $0F;
cmd := hiN or loN;

|
4 : // write to control port : Rs = false, Rw := false
mode := 0;
hiN := data and $F0;
loN := (data and $0F) shl 4;
write4bits(hiN or mode);
write4bits(loN or mode);
|

5 : // read from control port : Rs = false, Rw = true;
mode := Rw;
hiN := read4bits(mode);
hiN := (hiN and $F0);

loN := read4bits(mode);
loN := (loN shr 4) and $0F;
cmd := hiN or loN;
|
endcase;

// endif;

return(cmd);
end;



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

begin
InitPorts;
// InitADC;

EnableInts;
Writeln(Serout, 'LCDPort via PCF8574');


init_lcd;


// spalte, zeile
LCDclr;
Write(LCDout, 'LCDPort via PCF8574');
LCDxy(7, 1);
Write(LCDout, 'line 1');
LCDxy(7, 2); // spalte, zeile
Write(LCDout, 'line 2');

loop
if isSysTimerZero(t1000ms) then
SetSysTimer(t1000ms, 1000 div SysTick);
toggle(led);
Inc(cnt);
// LCDclrLine(3);
LCDxy(7, 3); // spalte, zeile
Write(LCDout, bytetostr(cnt : 6));
endif;
endloop;
end TWIDisplay.
Merlin
Administrator
Avatar
Geschlecht:
Alter: 25
Beiträge: 1474
Dabei seit: 03 / 2005
Betreff:

Re: 20x4 LCD display with an I2C interface

 · 
Gepostet: 14.06.2023 - 08:20 Uhr  ·  #8
Thanks for posting this Jag.
Gewählte Zitate für Mehrfachzitierung:   0

Registrierte in diesem Topic

Aktuell kein registrierter in diesem Bereich

Die Statistik zeigt, wer in den letzten 5 Minuten online war. Erneuerung alle 90 Sekunden.
MySQL Queries: 15 · Cache Hits: 14   139   153 · Page-Gen-Time: 0.0406s · Speichernutzung: 2 MB · GZIP: ein · Viewport: SMXL-HiDPI