//-----------------------------------------------------------------------------
// Title: i2c_Flex_LCD
// Description: Driver for common LCD with 1/2/3 or 4 row modules using PCF8574T interface board with I2C protocol.
// Date: Nov-2013
// Ver.Rev.: 1.0
// Author: Hugo Silva (sergio-hugo@bol.com.br) #Based on the routines of 20X4_LCD_I2C_DRIVER.h from Pumrin S.
//-----------------------------------------------------------------------------
//
// lcd_init() Must be called before any other function.
//
// lcd_putc(c) Will display c on the next position of the LCD.
//
// \f Clear LCD dispay
// \1 Set write position on LCD Line 1
// \2 Set write position on LCD Line 2
// \3 Set write position on LCD Line 3
// \4 Set write position on LCD Line 4
//
// lcd_gotoxy(x,y) Set write position on LCD (upper left is 1,1)
//
//-----------------------------------------------------------------------------
// LCD pins D0-D3 are not used.
//-----------------------------------------------------------------------------
//
// Commment : Control of a compatible LCD HITACHI from a bus I2C with
// an EXPANDER of I/O with connection I2C. The tests of these
// routines have been programmed using the IC PCF8574T of Phillips.
// I used 4 bits mode programming. The 8 bits mode programming
// is possible if you use 2 x PCF8574T.
//
// As defined in the following structure the pin connection is as follows:
//
// PCF8574P LCD
// ======== ======
// P0 RS
// P1 RW
// P2 Enable
// P3 Led Backlight
// P4 D4
// P5 D5
// P6 D6
// P7 D7
//
// The SCL and SDA pins should be pull-up resistor as shown below:
//
// +5v
// |
// <
// > 4.7K
// <
//To PIC | To i2c slave
//pin xx ------------------ SDA pin
//(SDA)
// +5v
// |
// <
// > 4.7K
// <
//To PIC | To i2c slave
//pin xx ------------------ SCL pin
//(SCL)
//
//To PIC To i2c slave
//Vss pin ----------------- Vss or ground pin
// |
// -----
// --- Ground
// -
//
// THIS DOCUMENT IS PROVIDED TO THE USER "AS IS"
//-----------------------------------------------------------------------------
//For PCF8574T the addressing is:
//Jp3 Jp2 Jp1
//A2 A1 A0 Hex
//L L L 0x40
//L L H 0x42
//L H L 0x44
//L H H 0x46
//H L L 0x48
//H L H 0x4A
//H H L 0x4C
//H H H 0x4E
/* OJoooooooo */
/*Para el PCF8574AT son estas direcciones:
//Jp3 Jp2 Jp1
//A2 A1 A0 Hex
//L L L 0x70
//L L H 0x72
//L H L 0x74
//L H H 0x76
//H L L 0x78
//H L H 0x7A
//H H L 0x7C
//H H H 0x7E
*/
// http://www.ccsinfo.com/forum/viewtopic.php?t=51351&start=24
//http://www.todopic.com.ar/foros/index.php?topic=13780.msg81633#msg81633
//----------------------------------------------------------------------------
extern void DelayMsec(unsigned int n_ms);
#define LCD_ADDR 0x7E //I2C slave address for LCD module El PCF8574AT y
//el PCF8574T tienen direcciones distintas.
#define ON 1
#define OFF 0
#define LCD_MODO_DATO 1
#define LCD_MODO_COMANDO 0
#define RS 0b00000001 //P0 - PCF8574T Pin connected to RS
#define RW 0b00000010 //P1 - PCF8574T Pin connected to RW
#define EN 0b00000100 //P2 - PCF8574T Pin connected to EN
#define BACKLIGHT_LED 0b00001000 //P3 - PCF8574T Pin connected to BACKLIGHT LED
#define lcd_line_one 0x80 // LCD RAM address for line 1
#define lcd_line_two 0xC0 // LCD RAM address for line 2
#define lcd_line_three 0x94 // LCD RAM address for line 3
#define lcd_line_four 0xD4 // LCD RAM address for line 4
bit lcd_backlight;
void i2c_send_nibble(unsigned char data) {
StartI2C(); // begin I2C communications
__delay_us(20);
IdleI2C();
WriteI2C(LCD_ADDR); // addresses the chip
__delay_us(20);
IdleI2C();
WriteI2C(data);
__delay_us(20);
IdleI2C();
StopI2C();
__delay_us(20);
}
void lcd_send_byte(unsigned char data) {
if (lcd_backlight) data = data | EN | BACKLIGHT_LED;
else data = data | EN; //set pin EN
i2c_send_nibble(data);
data = data & 0B11111011; //toggle EN back to 0
i2c_send_nibble(data);
}
void lcd_SendCommand(unsigned char command) {
unsigned char data;
data = command & 0xF0;
lcd_send_byte(data);
data = command & 0x0F;
data = data << 4;
lcd_send_byte(data);
}
void lcd_SendData(unsigned char in_data) {
unsigned char data;
data = in_data & 0xF0;
data = data | RS; //set RS pin to 1
lcd_send_byte(data);
data = in_data & 0x0F;
data = data << 4;
data = data | RS; //set RS pin to 1
lcd_send_byte(data);
}
void lcd_clear() {
lcd_send_byte(0x00);
lcd_send_byte(0x10);
DelayMsec(12);
}
void lcd_init() {
DelayMsec(200); //LCD power up delay
//Request works on the command by set the RS = 0 R/W = 0 write
lcd_send_byte(0x00);
lcd_send_byte(0x10);
lcd_send_byte(0x00);
lcd_send_byte(0x00);
lcd_send_byte(0x10);
//First state in 8 bit mode
lcd_send_byte(0x30);
lcd_send_byte(0x30);
//Then set to 4-bit mode
lcd_send_byte(0x30);
lcd_send_byte(0x20);
//mode 4 bits, 2 lines, characters 5 x 7 (28 h)
lcd_send_byte(0x20);
lcd_send_byte(0x80);
//no need cursor on (0Ch)
lcd_send_byte(0x00);
lcd_send_byte(0xC0);
//the cursor moves to the left (06 h)
lcd_send_byte(0x00);
lcd_send_byte(0x60);
//clears the display
lcd_clear();
}
void lcd_gotoxy(unsigned char x, unsigned char y) {
unsigned int address;
switch (y) {
case 1: address = lcd_line_one;
break;
case 2: address = lcd_line_two;
break;
case 3: address = lcd_line_three;
break;
case 4: address = lcd_line_four;
break;
default: address = lcd_line_one;
break;
}
address += x - 1;
lcd_SendCommand(address);
}
void i2c_lcd_backlight_On() {
lcd_backlight = ON;
}
void i2c_lcd_backlight_Off() {
lcd_backlight = OFF;
}
//Display the character on LCD screen.
void LCD_PUTC(char in_data) {
switch (in_data) {
case '\f': lcd_clear();
break;
case '\1': lcd_gotoxy(1, 1);
break;
case '\2': lcd_gotoxy(1, 2);
break;
case '\3': lcd_gotoxy(1, 3);
break;
case '\4': lcd_gotoxy(1, 4);
break;
default:
lcd_SendData(in_data);
break;
}
}
void LCDprint(char * buff, unsigned char len) {
unsigned char i;
for (i = 0; i < len; i++) {
LCD_PUTC(*(buff++));
}
}