#include<reg52.h>
#include<stdio.h>
typedef unsigned char UC;
typedef unsigned int UI;
typedef unsigned long UL;
#define SCKHIGH SCK=1;
#define SCKLOW SCK=0;
#define SDAHIGH SDA=1;
#define SDALOW SDA=0;
sbit SDA = P0^1; //serial data pin
sbit SCK = P0^0; //serial clock pin
void lcd_reset();
void lcd_init(void); // Initialize LCD
void lcd_busy(void); // Check Busy
void lcd_cmd(UC);
void lcd_data(UC);
void dis_cmd(UC);
void dis_data(UC);
void wrt_string(UC*); // Sending String
void wrt_value(UC); // Sending 8-bit Decimal value
void cursorxy(UC,UC); // Bringing Cursor to (X,Y) location X -> 1,2 and Y -> 1-16
//void lcd_4bitcmd(char);
void delay_ms(int);
void delay_m(UI);
void start(void);
void stop(void);
void send_byte(UC);
UC receive_byte(UC);
void write_i2c(UC,UC,UC);
void write(UC,UC);
UC read_i2c(UC,UC);
char slave_ack;
//starts i2c, if both SCK & SDA are idle
void start(void)
{
if(SCK==0) //check SCK. if SCK busy, return else SCK idle
{
return;
}
if(SDA==0) //check SDA. if SDA busy, return else SDA idle
{
return;
}
SDALOW //data low
delay_m(1);
SCKLOW //clock low
delay_m(1);
}
//stops i2c, releasing the bus
void stop(void)
{
SDALOW //data low
SCKHIGH //clock high
delay_m(1);
SDAHIGH //data high
delay_m(1);
}
//transmits one byte of data to i2c bus
void send_byte(UC c)
{
UC mask=0x80;
do //transmits 8 bits
{
if(c&mask) //set data line accordingly(0 or 1)
{
SDAHIGH //data high
}
else
{
SDALOW //data low
}
SCKHIGH //clock high
delay_m(1);
SCKLOW //clock low
delay_m(1);
mask/=2; //shift mask
}while(mask>0);
SDAHIGH //release data line for acknowledge
SCKHIGH //send clock for acknowledge
delay_m(1);
slave_ack=SDA; //read data pin for acknowledge
SCKLOW //clock low
delay_m(1);
}
//receives one byte of data from i2c bus
UC receive_byte(UC master_ack)
{
UC c=0,mask=0x80;
do //receive 8 bits
{
SCKHIGH //clock high
delay_m(1);
if(SDA==1) //read data
{
c|=mask; //store data
}
SCKLOW //clock low
delay_m(1);
mask/=2; //shift mask
}while(mask>0);
if(master_ack==1)
{
SDAHIGH //don't acknowledge
}
else
{
SDALOW //acknowledge
}
SCKHIGH //clock high
delay_m(1);
SCKLOW //clock low
delay_m(1);
SDAHIGH //data high
return c;
}
void write(UC device_id,UC c)
{
do
{
start(); //starts i2c bus
send_byte(device_id); //select slave device
if(slave_ack==1) //if acknowledge not received, stop i2c bus
{
stop();
}
}while(slave_ack==1); //loop until acknowledge is received
//send_byte(location); //send address location
send_byte(c); //send data to i2c bus
stop(); //stop i2c bus
delay_m(4);
}
//reads one byte of data(c) from slave device(device_id) at given address(location)
UC read_i2c(UC device_id,UC location)
{
UC c=0;
do
{
start(); //starts i2c bus
send_byte(device_id); //select slave device
if(slave_ack==1) //if acknowledge not received, stop i2c bus
{
stop();
}
}while(slave_ack==1); //loop until acknowledge is received
send_byte(location); //send address location
stop(); //stop i2c bus
start(); //starts i2c bus
send_byte(device_id+1); //select slave device in read mode
c=receive_byte(1); //receive data from i2c bus
stop(); //stop i2c bus
return c;
}
void delay_m(UI vall)
{
int di=0,dj=0;
for(di=0;di<vall;di++)
for(dj=0;dj<15;dj++);
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LCD Initialization
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
void lcd_reset()
{
delay_ms(20);
write(0x40,0x03 | 0x80);
write(0x40,0x00);
delay_ms(10);
write(0x40,0x03 | 0x80);
write(0x40,0x00);
delay_ms(1);
write(0x40,0x03 | 0x80);
write(0x40,0x00);
delay_ms(1);
write(0x40,0x02| 0x80);
write(0x40,0x00);
delay_ms(1);
}
void lcd_init()
{
lcd_reset();
/*dis_cmd(0x38);
dis_cmd(0x0F);
dis_cmd(0x01);
dis_cmd(0x06);*/
dis_cmd(0x02);
dis_cmd(0x28);
dis_cmd(0x0C);
dis_cmd(0x06);
dis_cmd(0x80);
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
waiting for LCD to execute
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
void lcd_busy()
{
delay_ms(1);
}
void dis_cmd(char cmd_value)
{
char cmd_value1;
/*cmd_value1=cmd_value & 0xF0;
lcd_cmd(cmd_value);
cmd_value1=((cmd_value<<4) & 0xF0);
lcd_cmd(cmd_value1); */
cmd_value1=((cmd_value>>4) & 0x0F);
lcd_data(cmd_value1);
cmd_value1=(cmd_value & 0x0F);
lcd_data(cmd_value1);
}
void dis_data(char data_value)
{
char data_value1;
/*data_value1=data_value & 0xF0;
lcd_data(data_value);
data_value1=(data_value<<4) & 0xF0;
lcd_data(data_value1);*/
data_value1=((data_value>>4) & 0x0F);
lcd_data(data_value1);
data_value1=(data_value & 0x0F);
lcd_data(data_value1);
}
void lcd_cmd(char cmdout)
{
write(0x40,cmdout);
write(0x40,cmdout | 0x00);
write(0x40,cmdout | 0x00);
write(0x40,cmdout | 0x80);
delay_ms(1);
write(0x40,cmdout | 0x00);
}
void lcd_data(char dataout)
{
write(0x40,dataout);
write(0x40,dataout | 0x20);
write(0x40,dataout | 0x00);
write(0x40,dataout | 0x90);
delay_ms(1);
write(0x40,dataout | 0x20);
}
void wrt_string(UC *string)
{
while(*string)
{
dis_data(*string++);
}
}
void wrt_value(UC x)
{
UC temp;
temp = x/0x10;
if(temp>9)
return;
else
dis_data(temp+0x30);
temp = x%0x10;
if(temp>9)
return;
else
dis_data(temp+0x30);
}
void cursorxy(UC x, UC y)
{
if((x<1||x>2)&&(y<1||y>16))
{
x=1;
y=1;
}
if(x == 1)
dis_cmd(0x7F+y);
else
dis_cmd(0xBF+y);
}
void delay_1ms(void)
{
TMOD=0x10;
TR1=0;
TL1=0x18;
TH1=0xFC;
TR1=1;
while(TF1==0);
TF1=0;
}
void delay_ms(int delay)
{
int i=0;
for(i=0;i<delay;i++)
{
delay_1ms();
}
}
void main(void)
{
int i=0;
delay_ms(20);
write(0x40,0x00);
delay_ms(20);
lcd_init(); //Intilize LCD in 4-Bit Mode
cursorxy(1,1);
wrt_string("I2C Expander Demo");
cursorxy(2,1);
wrt_string("4 bit Mode");
while(1)
{
}
}