CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

LCD (HD44780) device on an I2C MCP23016 I/O expander.

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
hatanet



Joined: 08 Sep 2003
Posts: 9
Location: South Africa

View user's profile Send private message Visit poster's website

LCD (HD44780) device on an I2C MCP23016 I/O expander.
PostPosted: Tue Sep 30, 2003 8:01 am     Reply with quote

Ole,

I am trying to implement an LCD (HD44780) device on an I2C MCP23016 I/O expander, using a PIC18F452. I have gone through Microchip AN245, tried to change most of the Hi-Tech code to CCS... But no luck!

Has anyone ever tried such a thing and how do I make mine work?

Regards
Hatanet
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Tue Sep 30, 2003 9:33 am     Reply with quote

Post what you have and maybe someone can spot what is wrong.
hatanet



Joined: 08 Sep 2003
Posts: 9
Location: South Africa

View user's profile Send private message Visit poster's website

PostPosted: Wed Oct 01, 2003 1:49 am     Reply with quote

I have included two files...

Here is the MCP23016.C file:

#use standard_io(C)
#use i2c(master,sda=PIN_C4,scl=PIN_C3)

// COMMAND BYTE TO REGISTER RELATIONSHIP : Table: 1-3 of Microchip MCP23016 - DS20090A
#define GP0 0x00
#define GP1 0x01
#define OLAT0 0x02
#define OLAT1 0x03
#define IPOL0 0x04 // INPUT POLARITY PORT REGISTER 0
#define IPOL1 0x05 // INPUT POLARITY PORT REGISTER 1
#define IODIR0 0x06 // I/O DIRECTION REGISTER 0
#define IODIR1 0x07 // I/O DIRECTION REGISTER 1
#define INTCAP0 0x08 // INTERRUPT CAPTURE REGISTER 0
#define INTCAP1 0x09 // INTERRUPT CAPTURE REGISTER 1
#define IOCON0 0x0A // I/O EXPANDER CONTROL REGISTER 0
#define IOCON1 0x0B // I/O EXPANDER CONTROL REGISTER 1

// BLOCK VARIABLE REGISTER
unsigned char MCP23016_Device_Address; // MCP23016 Assigned Device Address.
int GPIO_port; // MCP23016 Data Port Register.

// MCP23016 - I2C constants for selecting type of data transfer.
#define I2C_MCP23016_GP0_READ 0x9F // 1001 1111
#define I2C_MCP23016_GP0_WRITE 0x9E // 1001 1110
#define I2C_MCP23016_GP1_READ 0x9F // 1001 1111
#define I2C_MCP23016_GP1_WRITE 0x9E // 1001 1110

void write2Expander(unsigned char WriteAddress, unsigned char cmdByte, unsigned char lsbData, unsigned char msbData)
{
short int status;

i2c_start(); // start condition
delay_us(20);
i2c_write(WriteAddress); // Send slave address and clear (R/W_)
delay_us(20);
i2c_write(cmdByte); // Command byte and register to be written.
delay_us(20);
i2c_write(lsbData); // First data byte pair as per command byte(cmd)
delay_us(20);
i2c_write(msbData); // Second data byte pair as per command byte(cmd)
delay_us(20);
i2c_stop(); // stop condition
delay_us(50); // delay to allow write (12us)min.

// FORCE WRITING
/* i2c_start(); // restart condition
status=i2c_write(WriteAddress);
while(status==1)
{
i2c_start(); // restart condition
status=i2c_write(WriteAddress); // force writing
delay_us(50); // delay to allow write (12us)min.
}
*/
}

unsigned char readExpander(unsigned char WriteAddress, unsigned char ReadAddress, unsigned char cmdByte)
{
unsigned char Data, lsbData, msbData;
short int status,count;

startRead:
count=0; // Initialize read attempts counter.

i2c_start(); // start condition
i2c_write(WriteAddress); // Send slave address and clear (R/W_)
i2c_write(cmdByte); // Command byte and register to be written.
i2c_start(); // restart condition
i2c_write(ReadAddress); // Send slave address and clear (R_/W)
lsbData = i2c_read(1); // Data from LSB or MSB of register
msbData = i2c_read(0); // Data from MSB or LSB of register
i2c_stop(); // stop condition
delay_us(50); // delay to allow read (12us)min.

// There is no limitation on the no. of data bytes in one read transmission, so wait until all is read.
i2c_start(); // restart condition
status=i2c_read(1);
while(status==1)
{
i2c_start(); // restart condition
status=i2c_read(1); // force reading

// Otherwise start reading process all over again after 100 read attempts
if (status==1 && count==100 )
goto startRead; // timeout restart
count+=1;
}

// Combine two 8-bit data lengths into one 16-bit word length as a return value.
combiner:
data=lsbData;
data=data*9;
if((msbData&0x80)!=0)
data=data+4;

data=(data/5)+32;
msbData=data;

return(msbData); // return read value
}

void init_mcp23016(unsigned char MCP23016_Device_Address)
{
// Wait for MCP23016 Expander Device to power-up.
delay_ms(250);
delay_ms(250);
delay_ms(250);

// Set-up selected I/O expander unit
//write2Expander(MCP23016_Device_Address, IPOL0, 0xFF, 0xFF); // Invert all input polarities if active low.
//write2Expander(MCP23016_Device_Address, IPOL1, 0xFF, 0xFF); // Invert all input polarities if active low.
write2Expander(MCP23016_Device_Address, IPOL0, 0x00, 0x00); // NonInvert all input polarities if active low.
write2Expander(MCP23016_Device_Address, IPOL1, 0x00, 0x00); // NonInvert all input polarities if active low.

write2Expander(MCP23016_Device_Address, IOCON0, 0x01, 0x01); // IARES(1) to max. activity detection time.
write2Expander(MCP23016_Device_Address, IOCON0, 0x01, 0x01); // IARES(1) to max. activity detection time.

write2Expander(MCP23016_Device_Address, IODIR0, 0x00, 0x00); // Direction of all data is output.
write2Expander(MCP23016_Device_Address, IODIR1, 0x00, 0x00); // Direction of all data is output.

write2Expander(MCP23016_Device_Address, OLAT0, 0xFF, 0xFF); // Update o/p latch that controls the output.
write2Expander(MCP23016_Device_Address, OLAT1, 0xFF, 0xFF); // Update o/p latch that controls the output.

//write2Expander(MCP23016_Device_Address, IODIR0, 0x00, 0x00); // Direction of all data is output.
//write2Expander(MCP23016_Device_Address, IODIR1, 0x00, 0x00); // Direction of all data is output.
}

Here is the LCD23016.C File

struct lcd_pin_map { // This hatanet structure is overlayed
boolean unused; // on to an I/O port to gain
boolean enable; // access to the LCD pins.
boolean rw; // The bits are allocated from
boolean rs; // low order up. ENABLE will
int data : 4; // be pin B1.
} lcd;

#if defined(__PCH__)
#byte lcd = 0xF81 // This puts the entire structure
#else // on to port B (at address 6)
#byte lcd = 6
#endif
/


#define lcd_type 2 // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40 // LCD RAM address for the second line

byte CONST LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6};
// These bytes need to be sent to the LCD
// to start it up.

// The following are used for setting
// the I/O port direction register.

//STRUCT lcd_pin_map const LCD_WRITE = {0,0,0,0,0}; // For write mode all pins are out
//STRUCT lcd_pin_map const LCD_READ = {0,0,0,0,15}; // For read mode data pins are in

byte lcd_read_byte(int GPIO_port) {
byte low,high,runx;

if (GPIO_port=0) {
//set_tris_b(LCD_READ);
// write2Expander(MCP23016_Device_Address, IODIR0, LCD_READ, 0x00); // Direction of all data is output.
write2Expander(MCP23016_Device_Address, IODIR0, 0xF0, 0x00); // Direction of all data is output.

//lcd.rw = 1;
runx = runx | 0x03;
write2Expander(MCP23016_Device_Address, GP0, runx, 0x00); // Enable lcd module.

delay_cycles(1);

//lcd.enable = 1;
runx = runx | 0x02;
write2Expander(MCP23016_Device_Address, GP0, runx, 0x00); // Enable lcd module.

delay_cycles(1);

high = lcd.data;

//lcd.enable = 0;
runx = runx & 0xfd;
write2Expander(MCP23016_Device_Address, GP0, runx, 0x00); // Disable lcd module.

delay_cycles(1);

//lcd.enable = 1;
runx = runx | 0x02;
write2Expander(MCP23016_Device_Address, GP0, runx, 0x00); // Enable lcd module.

delay_us(1);

low = lcd.data;

//lcd.enable = 0;
runx = runx & 0xfd;
write2Expander(MCP23016_Device_Address, GP0, runx, 0x00); // Disable lcd module.

//set_tris_b(LCD_WRITE);
write2Expander(MCP23016_Device_Address, IODIR0, LCD_WRITE, 0x00); // Direction of all data is output.

return( (high<<4) | low);
} Else if (GPIO_port=1) {
//set_tris_b(LCD_READ);
write2Expander(MCP23016_Device_Address, IODIR1, LCD_READ, 0x00); // Direction of all data is output.

//lcd.rw = 1;
runx = runx | 0x03;
write2Expander(MCP23016_Device_Address, GP1, runx, 0x00); // Enable lcd module.

delay_cycles(1);

//lcd.enable = 1;
runx = runx | 0x02;
write2Expander(MCP23016_Device_Address, GP1, runx, 0x00); // Enable lcd module.

delay_cycles(1);

high = lcd.data;

//lcd.enable = 0;
runx = runx & 0xfd;
write2Expander(MCP23016_Device_Address, GP1, runx, 0x00); // Disable lcd module.

delay_cycles(1);

//lcd.enable = 1;
runx = runx | 0x02;
write2Expander(MCP23016_Device_Address, GP1, runx, 0x00); // Enable lcd module.

delay_us(1);

low = lcd.data;

//lcd.enable = 0;
runx = runx & 0xfd;
write2Expander(MCP23016_Device_Address, GP1, runx, 0x00); // Disable lcd module.

//set_tris_b(LCD_WRITE);
write2Expander(MCP23016_Device_Address, IODIR1, LCD_WRITE, 0x00); // Direction of all data is output.

return( (high<<4) | low);

}
}

void lcd_send_nibble(byte n, int GPIO_port) {
byte runx;

if (GPIO_port=0) {

//lcd.data = n;
runx = n & 0xff;
write2Expander(MCP23016_Device_Address, GP0, runx, 0x00); // Send actual data.

delay_cycles(1);

//lcd.enable = 1;
runx = runx | 0x02;
write2Expander(MCP23016_Device_Address, GP0, runx, 0x00); // Enable lcd module.

delay_us(2);

//lcd.enable = 0;
runx = runx & 0xfd;
write2Expander(MCP23016_Device_Address, GP0, runx, 0x00); // Disable lcd module.
} Else if (GPIO_port=1) {
//lcd.data = n;
runx = n & 0xff;
write2Expander(MCP23016_Device_Address, GP1, runx, 0x00); // Send actual data.

delay_cycles(1);

//lcd.enable = 1;
runx = runx | 0x02;
write2Expander(MCP23016_Device_Address, GP1, runx, 0x00); // Enable lcd module.

delay_us(2);

//lcd.enable = 0;
runx = runx & 0xfd;
write2Expander(MCP23016_Device_Address, GP1, runx, 0x00); // Disable lcd module.
} //else
}


void lcd_send_byte( byte address, byte n, int GPIO_port) {
/*
lcd.rs = 0;
while ( bit_test(lcd_read_byte(),7) ) ;
lcd.rs = address;
delay_cycles(1);
lcd.rw = 0;
delay_cycles(1);
lcd.enable = 0;
lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0xf);
*/

byte runx;

if (GPIO_port=0) {
//lcd.rs = 0;
runx = runx & 0xf7;
write2Expander(MCP23016_Device_Address, GP0, runx, 0x00); // Disable lcd module.

while ( bit_test(lcd_read_byte(0),7) ) ;

//lcd.rs = address;
runx = runx | (address >> 3);
write2Expander(MCP23016_Device_Address, GP0, runx, 0x00); // Disable lcd module.

delay_cycles(1);

//lcd.rw = 0;
runx = runx & 0xfb;
write2Expander(MCP23016_Device_Address, GP0, runx, 0x00); // Disable lcd module.

delay_cycles(1);

//lcd.enable = 0;
runx = runx & 0xfd;
write2Expander(MCP23016_Device_Address, GP0, runx, 0x00); // Disable lcd module.

lcd_send_nibble(n >> 4, GPIO_port);

lcd_send_nibble(n & 0xf, GPIO_port);
} Else if (GPIO_port=1) {
//lcd.rs = 0;
runx = runx & 0xf7;
write2Expander(MCP23016_Device_Address, GP1, runx, 0x00); // Disable lcd module.

while ( bit_test(lcd_read_byte(0),7) ) ;

//lcd.rs = address;
runx = runx | (address >> 3);
write2Expander(MCP23016_Device_Address, GP1, runx, 0x00); // Disable lcd module.

delay_cycles(1);

//lcd.rw = 0;
runx = runx & 0xfb;
write2Expander(MCP23016_Device_Address, GP1, runx, 0x00); // Disable lcd module.

delay_cycles(1);

//lcd.enable = 0;
runx = runx & 0xfd;
write2Expander(MCP23016_Device_Address, GP1, runx, 0x00); // Disable lcd module.

lcd_send_nibble(n >> 4, GPIO_port);

lcd_send_nibble(n & 0xf, GPIO_port);

} //else
}


void init_exp_lcd(unsigned char MCP23016_Device_Address, int GPIO_port) {
byte i, runx=0;
// -------------------------------------
if (GPIO_port=0) {
// Set-up expander port.
write2Expander(MCP23016_Device_Address, IPOL0, 0x00, 0x00); // NonInvert all input polarities if active low.
write2Expander(MCP23016_Device_Address, OLAT0, 0x00, 0x00); // Update o/p latch that controls the output.
// write2Expander(MCP23016_Device_Address, IODIR0, 0x00, 0x00); // Direction of all data is output.

// Set-up LCD orientation.
// write2Expander(MCP23016_Device_Address, IODIR0, LCD_WRITE, 0x00); // Direction of all data is output.
write2Expander(MCP23016_Device_Address, IODIR0, 0x00, 0x00); // Send actual data.
//lcd.rs = 0;
// runx = runx & 0xf7;
// write2Expander(MCP23016_Device_Address, GP0, runx, 0x00); // Disable lcd module.

//lcd.rw = 0;
// runx = runx & 0xfb;
// write2Expander(MCP23016_Device_Address, GP0, runx, 0x00); // Disable lcd module.

//lcd.enable = 0;
// runx = runx & 0xfd;
// write2Expander(MCP23016_Device_Address, GP0, runx, 0x00); // Disable lcd module.

write2Expander(MCP23016_Device_Address, GP0, 0x00, 0x00); // Send actual data.
delay_ms(15);
for(i=1;i<=3;++i) {
// lcd_send_nibble(3,GPIO_port);
lcd_send_nibble(3 >> 4,GPIO_port);
delay_ms(5);
}

lcd_send_nibble(2 >> 4,GPIO_port);

for(i=0;i<=3;++i)
lcd_send_byte(0,LCD_INIT_STRING[i],GPIO_port);

} else if (GPIO_port=1) {
// Set-up expander port.
write2Expander(MCP23016_Device_Address, IPOL1, 0x00, 0x00); // NonInvert all input polarities if active low.
write2Expander(MCP23016_Device_Address, OLAT1, 0x00, 0x00); // Update o/p latch that controls the output.
// write2Expander(MCP23016_Device_Address, IODIR1, 0x00, 0x00); // Direction of all data is output.

// Set-up LCD orientation.
// write2Expander(MCP23016_Device_Address, IODIR1, LCD_WRITE, 0x00); // Direction of all data is output.
write2Expander(MCP23016_Device_Address, IODIR1, 0x00, 0x00); // Direction of all data is output.

//lcd.rs = 0;
// runx = runx & 0xf7;
// write2Expander(MCP23016_Device_Address, GP1, runx, 0x00); // Disable lcd module.

//lcd.rw = 0;
// runx = runx & 0xfb;
// write2Expander(MCP23016_Device_Address, GP1, runx, 0x00); // Disable lcd module.

//lcd.enable = 0;
// runx = runx & 0xfd;
// write2Expander(MCP23016_Device_Address, GP1, runx, 0x00); // Disable lcd module.

write2Expander(MCP23016_Device_Address, GP1, 0x00, 0x00); // Send actual data.
delay_ms(15);

for(i=1;i<=3;++i) {
// lcd_send_nibble(3,GPIO_port);
lcd_send_nibble(3 >> 4,GPIO_port);

delay_ms(5);
}

lcd_send_nibble(2 >> 4,GPIO_port);

for(i=0;i<=3;++i)
lcd_send_byte(0,LCD_INIT_STRING[i],GPIO_port);

} //else if
}

/*
void lcd_gotoxy( byte x, byte y) {
byte address;

if(y!=1)
address=lcd_line_two;
else
address=0;
address+=x-1;
lcd_send_byte(0,0x80|address);
}

void lcd_putc( char c) {
switch (c) {
case '\f' : lcd_send_byte(0,1);
delay_ms(2);
break;
case '\n' : lcd_gotoxy(1,2); break;
case '\b' : lcd_send_byte(0,0x10); break;
default : lcd_send_byte(1,c); break;
}
}
*/

void lcd_gotoxy( byte x, byte y, int GPIO_port) {
byte address;

if(y!=1)
address=lcd_line_two;
else
address=0;
address+=x-1;
lcd_send_byte(0, 0x80|address, GPIO_port);
}

void expander_lcd_putc( char c, int GPIO_port) {
switch (c) {
case '\f' : lcd_send_byte(0, 1, GPIO_port);
delay_ms(2);
break;
case '\n' : lcd_gotoxy(1,2, GPIO_port); break;
case '\b' : lcd_send_byte(0,0x10, GPIO_port); break;
default : lcd_send_byte(1,c, GPIO_port); break;
}
1}


char lcd_getc( byte x, byte y, int GPIO_port) {
char value;

lcd_gotoxy(x,y,GPIO_port);
lcd.rs=1;
value = lcd_read_byte(0);
lcd.rs=0;
return(value);
}
MGLSOFT
Guest







PostPosted: Wed Jan 05, 2005 4:42 pm     Reply with quote

unsigned char readExpander(unsigned char WriteAddress, unsigned char ReadAddress, unsigned char cmdByte)
{
unsigned char Data, lsbData, msbData;
short int status,count;

startRead:
count=0; // Initialize read attempts counter.

i2c_start(); // start condition
i2c_write(WriteAddress); // Send slave address and clear (R/W_)
i2c_write(cmdByte); // Command byte and register to be written.
i2c_stop();//here is the problem. sorry no speak english
i2c_start(); // restart condition
i2c_write(ReadAddress); // Send slave address and clear (R_/W)
lsbData = i2c_read(1); // Data from LSB or MSB of register
msbData = i2c_read(0); // Data from MSB or LSB of register
i2c_stop(); // stop condition
delay_us(50); // delay to allow read (12us)min.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group