Sad news (see http://wiringpi.com/wiringpi-deprecated/) .
Talk is cheap, here is the code.
PCF8574ForLCD1602.py
# -*- coding: utf-8 -*-
"""
Python3 Code for LCD1602 Control via PCF8574
Created on Tue Aug 20 10:21:33 2019
@author: Farman
"""
import smbus
import time
'''
Hardware Connection
LCD1602 PCF8574T
-----------------
01 - VSS
02 - VDD
03 -- V0
04 -- RS 04 - P0 : 0 - command 1 - data
05 -- RW 05 - P1 : 0 - write 1 - read
06 --- E 06 - P2 : rising edge - data set to bus
falling edge - data read/write trig
07 -- D0
08 -- D1
09 -- D2
10 -- D3
11 -- D4 09 - P4
12 -- D5 10 - P5
13 -- D6 11 - P6
14 -- D7 12 - P7
15 --- A
16 --- K
Python3 module smbus is used for I2C communication.
Use "sudo raspi-config" to enable I2C interface.
Use "sudo apt install python3-smbus, i2c-tools" to install smbus module
of python3 and make command "i2cdetect" ready.
I2C address of PCF8574 is hardware configurable,
use "i2cdetect -y 1" for PCF8574 address detection
after correct hardware connection.
I2C bus related pins (physical name) of RaspberryPi:
pin 1 - 3.3V
2 - 5.0V
3 - SDA of I2C bus
4 - 5.0V
5 - SCL of I2C bus
6 - GND
Adjust the LCD contrast risistor first for perfect display after LCD power-on.
'''
class PCF8574ForLCD1602:
def __init__(self, bus=1, addr=0x27):
self.bus = bus
self.smbus = smbus.SMBus(self.bus)
self.addr = addr
return
def write_command_byte(self, byte):
def write_half_command_byte(smbus, half_byte):
i2c_data = (half_byte<<4) & 0xF0 # RS = RW = E = 0
smbus.write_byte(self.addr, i2c_data)
time.sleep(0.001)
i2c_data |= 0x04 # RS = RW = 0, E = 1
smbus.write_byte(self.addr, i2c_data)
time.sleep(0.001)
i2c_data ^= 0x04 # RS = RW = 0, E = 1
smbus.write_byte(self.addr, i2c_data)
time.sleep(0.001)
return
write_half_command_byte(self.smbus, byte >> 4) # high half-byte
write_half_command_byte(self.smbus, byte) # low half_byte
return
def write_command_bytes(self, command_bytes):
for byte in command_bytes:
#print('Output:', hex(byte))
self.write_command_byte(byte)
return
def write_data_byte(self, byte):
def write_half_data_byte(smbus, half_byte):
i2c_data = (half_byte<<4) & 0xF0 # RS = RW = E = 0
i2c_data |= 0x01
smbus.write_byte(self.addr, i2c_data)
i2c_data |= 0x04 # RS = RW = 0, E = 1
smbus.write_byte(self.addr, i2c_data)
i2c_data ^= 0x04 # RS = RW = 0, E = 1
smbus.write_byte(self.addr, i2c_data)
return
write_half_data_byte(self.smbus, byte >> 4) # high half-byte
write_half_data_byte(self.smbus, byte) # low half_byte
return
def write_data_bytes(self, byte_list):
for byte in byte_list:
self.write_data_byte(byte)
return
if __name__ == '__main__':
pcf8574 = PCF8574ForLCD1602()
bus_width=4
lines=2
font_big=0
display_on=1
cursor_on=0
blink_on=0
display_entire_shift_on=1
display_shift_increase=1
commands = [0x02, # set bus width
0x20 + (0x10 if bus_width==8 else 0x00) + (0x08 if lines==2 else 0x00) + (0x04 if font_big else 0x00), # function set
0x08 + (0x04 if display_on else 0x00) + (0x02 if cursor_on else 0x00) + (0x01 if blink_on else 0x00),
0x01,
0x06,
]
pcf8574.write_command_bytes(commands)
pcf8574.write_command_byte(0x80)
pcf8574.write_data_bytes("1234567890".encode())
LCD1602.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
LCD1602 Display Control in Python3 on RaspberryPi
Created on Tue Aug 20 10:21:33 2019
@author: Farman
"""
from PCF8574ForLCD1602 import PCF8574ForLCD1602 as pcf8574
import time
'''
Commands of HD44780/KS0066(Controller of LCD1602)
------------------------------------------------
clear display 0x01
return home 0x02
entry mode 0x04 + ID*2 + S
| |: 1 - entire shift on 0 - entire shift off
|
|: 1-increment 0 - decrement
display on/off 0x08 + D*4 + C*2 + B
| | |: blink of cursor, 1 - on 0 - off
| |
| |: cursor on/off, 1 - on 0 - off
|
|: entire display on/off, 1 - on 0- off
cursor/display shift 0x10 + SC*8 + RL*4
| |: 1-shift to right 0-shift to left
|
|: 1-display shift 2-cursor move
function set 0x20 + DL*0x10 + N*8 + F*4
| | F: 1 - 5*10dots 0-5*8 dots
| N: 1 - 2 lines 0 - 1 lines
DL: 1 - 8-bit bus 0 - 4-bit bus
set CGRAM address 0x40 + addr (6-bit width)
set DDRAM address 0x80 + addr (7-bit width)
read buzy flag and address : RS=0, RW=1
write data to CG or DDRAM : RS=1, RW=0
read data from CG or DDRAM: RS=1, RW=1
For any character LCD display module with cotroller compatible with
HD44780 and/or KS0066, such as LCD2002, LCD2402, LCD4002 and LCD4004,
this code should could be used with perfect hardware parameter configuration.
'''
class LCD1602:
def __init__(self, communicator):
self.communicator = communicator
self.lines = 2
return
def reset(self, bus_width=4, lines=2, font_big=0,
display_on=1, cursor_on=0, blink_on=0,
display_entire_shift_on=0, display_shift_increase=1):
'''
bus_width : 8 - 8-bit, else - 4-bit
lines : 2 - 2-line, else - 1-line
font_big : 1 - 5*10, else - 5*8
display_on: 1 - on, else off
cursor_on : 1 - on, else off
blink_on : 1 - on, else off
display_entire_shift_on : 1 - on, else off
display_shift_increase : 1 - on, else off
'''
self.lines = lines
self.communicator.write_command_bytes(
[0x02, # set bus width
0x20 + (0x10 if bus_width==8 else 0x00) + (0x08 if lines==2 else 0x00) + (0x04 if font_big else 0x00), # function set
0x08 + (0x04 if display_on else 0x00) + (0x02 if cursor_on else 0x00) + (0x01 if blink_on else 0x00), # display cursor set
0x01, # clear display
0x04 + (0x01 if display_entire_shift_on else 0x00) + (0x02 if display_shift_increase else 0x01), # entry mode
])
if self.lines == 1:
self.write_string(0, 0, "LCD1602 DISPLAY Farman@2019")
else:
self.write_string(0, 0, "LCD1602 DISPLAY")
self.write_string(1, 0, "Farman@20190820*")
time.sleep(3)
self.clear_all()
def write_string(self, line, column, string):
'''
line : 0 - the upper line, else the lower line (2-line mode)
column : the first column to write string, value should be
[0, 80) for 1-line mode
[0, 40) for 2-line mode
'''
line = min(line, 1)
data = string.encode()
if self.lines == 1:
column = min(column, 79)
addr = column
data = data[:min(len(data), 79-column)]
else:
column = min(column, 39)
addr = line * 0x40 + column
data = data[:min(len(data), 39-column)]
self.communicator.write_command_byte(0x80|addr)
self.communicator.write_data_bytes(string.encode())
return
def clear_line(self, line):
'''
line : 0 - the upper line, else the lower line (2-line mode)
'''
self.write_string(line, 0, ' '*20)
return
def clear_all(self):
'''
Clear all display.
'''
self.communicator.write_command_byte(0x01)
return
if __name__ == '__main__':
communicator = pcf8574()
lcd = LCD1602(communicator)
lcd.reset()
lcd.clear_all()
lcd.write_string(0, 0, '123456789jhu0')
while True:
for line in range(2):
for column in range(16):
lcd.clear_all()
lcd.write_string(line, column, '#')
lcd.write_string(0, 0, "%s %s"%(line, column))
time.sleep(0.2)
break
if lcd.lines == 1:
lcd.write_string(0, 0, "LCD1602 DISPLAY Farman@2019")
else:
lcd.write_string(0, 0, "LCD1602 DISPLAY")
lcd.write_string(1, 0, "Farman@20190820*")
time.sleep(1)
lcd.clear_line(0)
time.sleep(1)
lcd.clear_line(1)
time.sleep(1)
if lcd.lines == 1:
lcd.write_string(0, 0, "LCD1602 DISPLAY Farman@2019")
else:
lcd.write_string(0, 0, "LCD1602 DISPLAY")
lcd.write_string(1, 0, "Farman@20190820*")
time.sleep(1)
lcd.clear_all()
pcf8574.h
#ifndef __PCF8574_H__
#define __PCF8574_H__
#include // in /usr/include
#include // in /usr/include
/*
device_addr :
I2C addr of PCF8574, which is hardware configurable.
Use "sudo raspi-config" to enable I2C interface.
Use "sudo apt install i2c-tools" to make command "i2cdetect" ready.
I2C address of PCF8574 is hardware configurable,
use "i2cdetect -y 1" for PCF8574 address detection
after correct hardware connection.
*/
int pcf8574_init(int device_addr);
/*
device is get by pcf8574_init().
Low half of half_byte is actual value send.
*/
void pcf8574_write_half_command_byte(int device, char half_byte);
/*
device is get by pcf8574_init().
*/
void pcf8574_write_command_byte(int device, char byte);
/*
device is get by pcf8574_init().
bytes[] contains bytes to send.
n is length in byte of bytes[].
*/
void pcf8574_write_command_bytes(int device, char bytes[], int n);
/*
device is get by pcf8574_init().
Low half of half_byte is actual value send.
*/
void pcf8574_write_half_data_byte(int device, char half_byte);
/*
device is get by pcf8574_init().
*/
void pcf8574_write_data_byte(int device, char byte);
/*
device is get by pcf8574_init().
bytes[] contains bytes to send.
n is length in byte of bytes[].
*/
void pcf8574_write_data_bytes(int device, char bytes[], int n);
#endif // #ifndef __PCF8574_H__
pcf8574.c
#include
#include "pcf8574.h"
int pcf8574_init(int device_addr)
{
wiringPiSetupGpio();
return wiringPiI2CSetup(device_addr);
}
void pcf8574_write_half_command_byte(int device, char half_byte)
{
half_byte <<= 4;
wiringPiI2CWrite(device, half_byte);
usleep(50);
half_byte |= 0x04;
wiringPiI2CWrite(device, half_byte);
usleep(50);
half_byte ^= 0x04;
wiringPiI2CWrite(device, half_byte);
usleep(50);
return;
}
void pcf8574_write_command_byte(int device, char byte)
{
pcf8574_write_half_command_byte(device, byte>>4);
pcf8574_write_half_command_byte(device, byte);
usleep(50);
return;
}
void pcf8574_write_command_bytes(int device, char bytes[], int n)
{
int i;
for(i=0; i>4);
pcf8574_write_half_data_byte(device, byte);
return;
}
void pcf8574_write_data_bytes(int device, char bytes[], int n)
{
int i;
for(i=0; i
pcf8574_test.c
#include
#include "pcf8574.h"
int main()
{
int device;
device = init();
if (device < 0)
{
printf("I2C bus initialize failed ---.\n");
return 0;
}
int bus_width = 4;
int lines = 2;
int font_big = 0;
int display_on = 1;
int cursor_on = 0;
int blink_on = 0;
int display_entire_on = 1;
int display_shift_increase = 1;
char command;
write_command_byte(device, 0x02);
command = 0x20;
command += bus_width==8 ? 0x10 : 0x00;
command += lines==2 ? 0x08 : 0x00;
command += font_big==1 ? 0x04 : 0x00;
write_command_byte(device, command);
command = 0x08;
command += display_on==1 ? 0x04 : 0x00;
command += cursor_on==1 ? 0x02 : 0x00;
command += blink_on==1 ? 0x01 : 0x00;
write_command_byte(device, command);
write_command_byte(device, 0x01);
command = 0x04;
command += display_entire_on==1 ? 0x02 : 0x00;
command += display_shift_increase==1 ? 0x01 : 0x00;
write_command_byte(device, command);
write_data_bytes(device, "01234567890!", 12);
return 0;
}
lcd1602.h
#include
#include
#include
#include "pcf8574.h"
/*
CONNECTIONS OF
LCD1602 PCF8574T
-----------------
01 - VSS
02 - VDD
03 -- V0
04 -- RS 04 - P0
05 -- RW 05 - P1
06 --- E 06 - P2
07 -- D0
08 -- D1
09 -- D2
10 -- D3
11 -- D4 09 - P4
12 -- D5 10 - P5
13 -- D6 11 - P6
14 -- D7 12 - P7
15 --- A
16 --- K
*/
/*
hold the parameter of LCD1602 display lines,
which is used by hd44780_write_string().
*/
int hd44780_display_lines;
/*
device_addr :
I2C addr of PCF8574, which is hardware configurable.
Use "sudo raspi-config" to enable I2C interface.
Use "sudo apt install i2c-tools" to make command "i2cdetect" ready.
I2C address of PCF8574 is hardware configurable,
use "i2cdetect -y 1" for PCF8574 address detection
after correct hardware connection.
return device id for further operation by other functions.
*/
int hd44780_init(int device_addr);
void hd44780_reset(
int device, // get by hd44780_init()
int bus_width, // 8 - 8-bit bus, 4 - 4-bit bus
int lines, // 1 - 1-line, 2 - 2-line, depend on LCD hardware.
int font_big, // 1 - 8*10 font, 0 - 5*8 font
int display_on, // 1 - entire display on, 0 - entire display off
int cursor_on, // 1 - cursor on, 0 - cursor off
int blink_on, // 1 - cursor blink on, 0 - cursor blink off.
int display_entire_shift_on, // entire display shift : 1 - on, 0 - off
int display_shift_increase // DDRAM address (cursor or blink): 1 - increase 0 -decrease
);
void hd44780_write_string(
int device, // get by hd44780_init()
int line, // write to which line. If hd44780_display_lines==1, this parameter is ignored.
int column, // write to which column, max column is 39 for hd44780_display_lines==2, else 79.
char string[], // buffer contains string to write.
int str_len // buffer length in byte.
);
/*
device : get by hd44780_init()
line : which line to clear, 1 or 2. If hd44780_display_lines==1, this parameter is ignored.
*/
void hd44780_clear_line(int device, int line);
/*
device : get by hd44780_init()
Clear all display.
*/
void hd44780_clear_all(int device);
lcd1602.c
#include "lcd1602.h"
/*
device_addr :
I2C addr of PCF8574, which is hardware configurable.
Use "sudo raspi-config" to enable I2C interface.
Use "sudo apt install i2c-tools" to make command "i2cdetect" ready.
I2C address of PCF8574 is hardware configurable,
use "i2cdetect -y 1" for PCF8574 address detection
after correct hardware connection.
*/
int hd44780_init(int device_addr)
{
return pcf8574_init(device_addr);
}
void hd44780_reset(
int device,
int bus_width,
int lines,
int font_big,
int display_on,
int cursor_on,
int blink_on,
int display_entire_shift_on,
int display_shift_increase
)
{
hd44780_display_lines = lines;
char command;
pcf8574_write_command_byte(device, 0x02);
command = 0x20;
command += bus_width==8 ? 0x10 : 0x00;
command += lines==2 ? 0x08 : 0x00;
command += font_big==1 ? 0x04 : 0x00;
pcf8574_write_command_byte(device, command);
command = 0x08;
command += display_on==1 ? 0x04 : 0x00;
command += cursor_on==1 ? 0x02 : 0x00;
command += blink_on==1 ? 0x01 : 0x00;
pcf8574_write_command_byte(device, command);
pcf8574_write_command_byte(device, 0x01);
usleep(50000);
command = 0x04;
command += display_entire_shift_on==1 ? 0x02 : 0x00;
command += display_shift_increase==1 ? 0x01 : 0x00;
pcf8574_write_command_byte(device, command);
return;
}
void hd44780_write_string(
int device,
int line,
int column,
char string[],
int str_len
)
{
int addr;
line = line < 1 ? line : 1;
if (hd44780_display_lines == 1)
{
column = column < 79 ? column : 79;
str_len = str_len < 79 - column ? str_len : 79 - column;
addr = column;
}
else
{
column = column < 39 ? column : 39;
str_len = str_len < 39 - column ? str_len : 39 - column;;
addr = line * 0x40 + column;
}
pcf8574_write_command_byte(device, 0x80 | addr);
pcf8574_write_data_bytes(device, string, str_len);
return;
}
void hd44780_clear_line(int device, int line)
{
char blanks[80];
int n;
for (n=0; n<80; ++n)
{
blanks[n] = 0x20; // ' '
}
hd44780_write_string(device, line, 0, blanks, 80);
return;
}
void hd44780_clear_all(int device)
{
pcf8574_write_command_byte(device, 0x01);
usleep(1600);
return;
}
lcd1602_test.c
#include "lcd1602.h"
int main()
{
int device = hd44780_init(0x27);
if (device < 0)
{
printf("Init PCF8574 Failed.");
return 0;
}
hd44780_reset(device, 4, 2, 1, 1, 0, 0, 1, 0);
hd44780_clear_all(device);
hd44780_write_string(device, 0, 0, "Too young, ", 16);
hd44780_write_string(device, 1, 0, "Too naive, boy!!", 16);
//return 0;
sleep(2);
hd44780_clear_all(device);
int n;
char buf[40];
for (n=0; n<64; ++n)
{
sprintf(buf, "%016X", n);
hd44780_write_string(device, 1, 0, buf, strlen(buf));
usleep(50000);
}
return 0;
}
command for compile and run
rm pcf
gcc -Wall -o pcf pcf8574.c lcd1602.c lcd1602_test.c -lwiringPi
./pcf
That's all.