Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

LCD1602 with Arduino I2C, RS is working for command calls but not for data

Status
Not open for further replies.

eagle1109

Full Member level 6
Joined
Nov 20, 2014
Messages
390
Helped
4
Reputation
10
Reaction score
7
Trophy points
1,298
Location
Saudi Arabia
Activity points
5,928
Hello,

My configuration is:
LCD1602, I2C adapter and Arduino nano.

Sending commands works fine but I can't display chars by sending data.

That happens when set the RS pin to high for data and low for commands.

So what's happening is that the two functions for sending commands and data works the same.

I concluded that I have a problem with sending data, if I edit the RS bit in command function to high or low the function is the same.

So, the problem is with RS pin.

This is my code:

Code:
#define E   2   // E  bit
#define RW  1   // RW bit
#define RS  0   // RS bit

#define LCDadd_WR  0x4E
#define LCDadd_RD  0x4F

uint8_t bitmask = 0x08;
uint8_t i, arr[]={0x48,0x65,0x6c,0x6c,0x6f ,0x10 ,0x3a,0x29 ,0x10 ,0x48,0x6f,0x77,0x10 
,0x61,0x72,0x65,0x10,0x79,0x6f,0x75,0x65,0x76,0x65,0x72,0x79,0x10,0x6f,0x6e,0x65};

// LCD prototypes
void LCD_Init(void);
void sendCMD(uint8_t CMD);
void sendData(uint8_t data);
void LCD_string(uint8_t arr1[]);
void move_cursor (uint8_t row, uint8_t col);

// I2C prototypes
void I2C_init(void);
void I2C_start(uint8_t address);
void I2C_stop(void);
void I2C_tx(uint8_t data);
void I2C_TWSR_Check(void);




void setup() {
  Serial.begin(9600);
I2C_init();
LCD_Init();
}

void loop() {
//sendData("H");
}

///////////////////////////////////////////////////
///////////////////////////////////////////////////
void LCD_Init(void)
{
  sendCMD(0x33);
  sendCMD(0x32);
  sendCMD(0x28);
  sendCMD(0x0E);
  sendCMD(0x01);
}

void sendCMD(uint8_t CMD)
{
  bitmask = 0x08;
  I2C_start(LCDadd_WR);
  I2C_tx(bitmask |= (1<<RS));
  I2C_tx(bitmask &= ~(1<<RW));
  I2C_tx(bitmask = CMD & 0xF0 | 0x08);
  Serial.println("CMD high");
  Serial.println(bitmask, HEX);  
  _delay_ms(5);
  I2C_tx(bitmask |= (1<<E));
  _delay_ms(1);
  I2C_tx(bitmask &= ~(1<<E));
  _delay_ms(1);
  I2C_tx(bitmask = (CMD<<4) & 0xF0 | 0x08);
  Serial.println("CMD low");
  Serial.println(bitmask, HEX);
  I2C_tx(bitmask |= (1<<E));
  _delay_ms(1);
  I2C_tx(bitmask &= ~(1<<E));
  I2C_stop();
}

void sendData(uint8_t data)
{
  bitmask = 0x08;
  I2C_start(LCDadd_WR);
  I2C_tx(bitmask |= (1<<RS));
  Serial.println("data");
  Serial.println(bitmask, HEX);
  I2C_tx(bitmask &= ~(1<<RW));
  I2C_tx(bitmask = data & 0xF0 | 0x08);
  _delay_ms(5);
  I2C_tx(bitmask |= (1<<E));
  _delay_ms(1);
  I2C_tx(bitmask &= ~(1<<E));
  _delay_ms(1);
  I2C_tx(bitmask = (data<<4) & 0xF0 | 0x08);
  I2C_tx(bitmask |= (1<<E));
  _delay_ms(1);
  I2C_tx(bitmask &= ~(1<<E));
  I2C_stop();
}

uint8_t BF(void)
{
  I2C_start(LCDadd_WR);
  I2C_tx(bitmask &= ~(1<<RS));
  I2C_tx(bitmask |= (1<<RW));
  I2C_stop();
  I2C_start(LCDadd_RD);
  I2C_rx();
  while (!(TWDR == (bitmask & (bitmask<<3))));
  I2C_stop();
  I2C_start(LCDadd_WR); 
  I2C_tx(bitmask |= (1<<RS));
  _delay_ms(500);
  I2C_tx(bitmask &= ~(1<<RS));
  _delay_ms(500);
  I2C_stop();
}

void move_cursor (uint8_t row, uint8_t col)
{
  if (row==1)
  sendCMD(0x80+col);
  if (row==2)
  sendCMD(0xC0+col);
}

void LCD_string(uint8_t arr1[])
{
uint8_t cnt=0;
  for (i=0;i<29;i++)
  {
    sendData(arr1[i]);
    _delay_ms(500); 
    cnt++;
    if (cnt==16)
    sendCMD(0xC0);
  }
  sendData(0x10);
}

///////////////////////////////////////////////////
///////////////////////////////////////////////////

void I2C_init(void)
{
  //set SCL to 100kHz
  TWSR = 0x00;
  TWBR = 0x48;
  //enable TWI
  TWCR = (1<<TWEN);
}

void I2C_start(uint8_t address)
{
  TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
  while (!(TWCR & (1<<TWINT)));
  TWDR = address;
  TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA);
  while (!(TWCR & (1<<TWINT)));
}

void I2C_stop(void)
{
  TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN);
}

void I2C_tx(uint8_t data)
{
  TWDR = data;
  TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA);
  while (!(TWCR & (1<<TWINT)));
}

uint8_t I2C_rx(void)
{
  TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA);
  while (!(TWCR & (1<<TWINT))); 
  return TWDR;  
}

Regards,
 

You should set RS low in sendCMD() and high in sendData(), but you don't.

It's set low in both routines because the control line state is overwritten by
Code:
I2C_tx(bitmask = CMD & 0xF0 | 0x08)
respectively
Code:
I2C_tx(bitmask = data & 0xF0 | 0x08);

The bit pattern should be set in a single I2C_tx() action before pulsing E line.

Code can be simplified like below. I2C_tx() is providing more delay than necessary if busy polling is performed.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void sendCMD(uint8_t CMD)
{
  I2C_start(LCDadd_WR);
  I2C_tx(bitmask = CMD & 0xF0 | 0x08);
  I2C_tx(bitmask |= (1<<E));
  I2C_tx(bitmask &= ~(1<<E));
  I2C_tx(bitmask = (CMD<<4) & 0xF0 | 0x08);
  I2C_tx(bitmask |= (1<<E));
  I2C_tx(bitmask &= ~(1<<E));
  I2C_stop();
}
 
void sendData(uint8_t data)
{
  I2C_start(LCDadd_WR);
  I2C_tx(bitmask = data & 0xF0 | 0x08 |= (1<<RS));
  I2C_tx(bitmask |= (1<<E));
  I2C_tx(bitmask &= ~(1<<E));
  I2C_tx(bitmask = (data<<4) & 0xF0 | 0x08 |= (1<<RS));
  I2C_tx(bitmask |= (1<<E));
  I2C_tx(bitmask &= ~(1<<E));
  I2C_stop();
}

 
Thank you very much, that solved the problem.

Now I have another issue, which is how to read a command or data from the LCD?

I'm developing this new function, but with the serial print, I don't see the values I'm expecting.

Code:
void lcdCMD_read (void)
{
  Serial.println("enter function");
  I2C_start(LCDadd_WR);           // write PCF8574 address
  I2C_tx(bitmask |= 0x0B);        // RS, RW = 1 read data
  I2C_stop();
  Serial.println("i2c stop");
  I2C_start(LCDadd_RD);           // read PCF8574 address
  I2C_rx();                       // receive I2C and get TWDR
  Serial.println(TWDR, HEX);      // print TWDR
  //while (!(TWDR == (bitmask & (bitmask<<7))));  // This function never ends
  Serial.println("CMD from LCD");
  Serial.println(bitmask, HEX);
  I2C_stop();
}
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top