system
February 16, 2009, 12:17pm
1
Hi,
as the PCF8574 gives me 8 digital in and output channels i'd like to use this thing to drive a 44780 LCD on a 4Bit way. That way i would not only spare quite a bunch of Digital IOs on the Arduino, i would drive it via I2C which is quite a nice way for this to be done ;0)
Now the question is - has already someone done this? I have found a library via Google called TwiLCD which came without documentation and was not possible to be compiled - i guess it was made for an old version of the Arduino framework as it includes files i have never even heard of (like /config/lcd/lcd.h).
You can find info about it here http://trac.mlalonde.net/cral/browser/twiLCD?rev=1
Is there maybe some newer version i havent found here yet or maybe some other way to solve this 'problem'?
system
February 16, 2009, 8:43pm
2
Alright, after trying to convert some code i found at HD44780 Display via PCF8574 I²C IO-Expander i havent yet succeeded in doing this...
Is there someone who would like me to help to write a LCD4Bit-like library for the Arduino?
edit
Oh yes, my code (till now):
/*
Original Code by scriptkiller. Adapted to Arduino by Nachtwind
*/
#ifndef __I2CLCD_H__
#define __I2CLCD_H__
#include <wprogram.h>
/* pin definitions */
#define P0 0x01
#define P1 0x02
#define P2 0x04
#define P3 0x08
#define P4 0x10
#define P5 0x20
#define P6 0x40
#define P7 0x80
/* i2c addr of expander chip */
#define LCD_I2C_ADDR B0111000
/* define what display-pin is connected
* to what io-pin of expander */
#define LCD_D4 P4
#define LCD_D5 P5
#define LCD_D6 P6
#define LCD_D7 P7
#define LCD_RS P0
#define LCD_RW P1
#define LCD_E P2
/*
+-\/-+
A0 1| |16 VCC
A1 2| |15 SCA
A2 3| |14 SCL
RS 4| |13 N/C
RW 5| |12 PD7
E 6| |11 PD6
NC 7| |10 PD5
GND 8| |9 PD4
+----+
*/
/* what is the width of the display
* (height is assumed to be 2) */
#define LCD_WIDTH 16
/* init the lcd */
void lcdInit(void);
/* clear the display */
void lcdClear(void);
/* print a string on display,
* continues automatically in 2nd line,
* note that lcdClear() should be called
* before using this function */
void lcdPrintString(char *str);
/* low level function, see lcd.c */
void lcd4BitOut( char c, char data);
#endif
/*
Original Code by scriptkiller. Adapted to Arduino by Nachtwind
*/
#include <Wire.h>
/* configuration is done in lcd.h */
#include "i2clcd.h"
/* output (raw) data to lcd */
void lcdOut(char c) {
Wire.beginTransmission(LCD_I2C_ADDR);
Wire.send(&c);
Wire.endTransmission();
}
/* output data in 4bit mode to lcd
* if data != 0, register select is set high!
*/
void lcd4BitOut( char c, char data) {
char out;
char rs;
rs=0;
if(data)
rs=LCD_RS;
/* 4 upper bits */
out=0;
if(c & 0x80) out |= LCD_D7;
if(c & 0x40) out |= LCD_D6;
if(c & 0x20) out |= LCD_D5;
if(c & 0x10) out |= LCD_D4;
lcdOut(out | rs);
lcdOut(out | rs | LCD_E);
delay(1000);
lcdOut(out | rs);
/* 4 lower bits */
out=0;
if(c & 0x08) out |= LCD_D7;
if(c & 0x04) out |= LCD_D6;
if(c & 0x02) out |= LCD_D5;
if(c & 0x01) out |= LCD_D4;
lcdOut(out | rs);
lcdOut(out | rs | LCD_E);
delay(1000);
lcdOut(out | rs);
}
/* clear LCD */
void lcdClear() {
lcd4BitOut(0x01, 0); // clear display
}
/* init lcd */
void lcdInit() {
lcdOut(0x00);
// A1
lcdOut(LCD_D4 | LCD_D5);
delay(100);
lcdOut(LCD_D4 | LCD_D5 | LCD_E);
delay(100);
lcdOut(LCD_D4 | LCD_D5);
delay(50);
// A2
lcdOut(LCD_D4 | LCD_D5);
delay(100);
lcdOut(LCD_D4 | LCD_D5 | LCD_E);
delay(100);
lcdOut(LCD_D4 | LCD_D5);
delay(20);
// A3
lcdOut(LCD_D4 | LCD_D5);
delay(100);
lcdOut(LCD_D4 | LCD_D5 | LCD_E);
delay(100);
lcdOut(LCD_D4 | LCD_D5);
delay(100);
// A4
/* set mode to 4 bit */
lcdOut(LCD_D5);
delay(100);
lcdOut(LCD_D5 | LCD_E);
delay(100);
lcdOut(LCD_D5);
delay(100);
/* from now on display can be interfaced
* using 4bit mode */
lcd4BitOut(0x28, 0); // A5
lcd4BitOut(0x08, 0); // A6
lcd4BitOut(0x01, 0); // A7
lcd4BitOut(0x07, 0); // A8
lcd4BitOut(0x0C, 0); // display + cursor off + blink off
lcd4BitOut(0x06, 0); // increment addr
lcdClear();
}
void lcdPrintString(char *str) {
char c;
int i;
i=0;
while( (c=*str) != '\0' ) {
if(i==LCD_WIDTH) {
/* set DDRAM Addr 0x40 (beginning of 2nd line) */
lcd4BitOut(0x80 | 0x40, 0);
}
lcd4BitOut(c, 1);
str++;
i++;
}
}
Now the question is - has already someone done this?
You can buy a preprogrammed microcontroller from www.byvac.com that does exactly this. I have two of these and they work just fine. However, the Wire library occupies a good chunk of flash, my project grew 3Kb when I switched from direct 4-bit interface to I2C.