20x4 LCD display with an I2C interface

How to interface TWI with an i2C display?

JAG
Benutzer
Avatar
Gender:
Location: Mexico
Age: 59
Posts: 18
Registered: 07 / 2008
Subject:

20x4 LCD display with an I2C interface

 · 
Posted: 09.06.2023 - 18:00  ·  #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.
Attachments
20x4 LCD display with an I2C interface
Filename: ezgif.com-webp-to-jpg.jpg
Filesize: 91.39 KB
Title:
Download counter: 51
Harry
Moderator
Avatar
Gender:
Location: zwischen Augsburg und Ulm
Age: 59
Posts: 2089
Registered: 03 / 2003
Subject:

Re: 20x4 LCD display with an I2C interface

 · 
Posted: 09.06.2023 - 19:27  ·  #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
Gender:
Location: Donauwörth
Age: 70
Posts: 250
Registered: 11 / 2009
Subject:

Re: 20x4 LCD display with an I2C interface

 · 
Posted: 09.06.2023 - 19:31  ·  #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
Gender:
Location: Mexico
Age: 59
Posts: 18
Registered: 07 / 2008
Subject:

Re: 20x4 LCD display with an I2C interface

 · 
Posted: 09.06.2023 - 20:08  ·  #4
Quote by 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
Gender:
Location: Donauwörth
Age: 70
Posts: 250
Registered: 11 / 2009
Subject:

Re: 20x4 LCD display with an I2C interface

 · 
Posted: 10.06.2023 - 06:29  ·  #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
Gender:
Location: Mexico
Age: 59
Posts: 18
Registered: 07 / 2008
Subject:

Re: 20x4 LCD display with an I2C interface

 · 
Posted: 10.06.2023 - 15:12  ·  #6
I appreciate Golf and Harry's guidance on LCD-I2C implementation, I'll keep posting results here.
JAG
Benutzer
Avatar
Gender:
Location: Mexico
Age: 59
Posts: 18
Registered: 07 / 2008
Subject:

Re: 20x4 LCD display with an I2C interface

 · 
Posted: 13.06.2023 - 23:33  ·  #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
Gender:
Age: 24
Posts: 1373
Registered: 03 / 2005
Subject:

Re: 20x4 LCD display with an I2C interface

 · 
Posted: 14.06.2023 - 08:20  ·  #8
Thanks for posting this Jag.
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: 16 · Cache Hits: 15   140   155 · Page-Gen-Time: 0.030442s · Memory Usage: 2 MB · GZIP: on · Viewport: SMXL-HiDPI