1

I've been doing fine with my LCD1602 I2C configuration but I discovered that command and data functions are the same even though I change the RS command/data bit, but the result is the same.

This is really strange, I really can't do anything about it??!

#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(0x0E); /* I commented this line because it has the same effect as sendCMD(0x0F); in sendCMD function */
}

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

void sendCMD(uint8_t CMD)
{
  bitmask = 0x08;
  I2C_start(LCDadd_WR);
  I2C_tx(bitmask &= ~(1<<RS));
  Serial.println("CMD");
  Serial.println(bitmask, HEX);
  I2C_tx(bitmask &= ~(1<<RW));
  I2C_tx(bitmask = CMD & 0xF0 | 0x08);
  _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);
  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;  
}
  • You might want to try a more specific / complete Arduino library specifically for LCDs and, perhaps, specifically for the LCD1602. That way, if that works, you can eliminate hardware problems. Then return to your raw i2c code and feel more assured the problem is in the code. Also, you can check the library solutions against your own and see if there is anything you might have missed. The i2c protocol allows for some flexibility and, unfortunately, that leads to some confusion from time to time. – st2000 May 13 '17 at 13:49
  • Yes, I used a very good Arduino library which works fine, the problem is in my code. And specifically in the sendData function because it works as sendCMD the same, so if I changed the function calls in LCD_init function from sendCMD to sendData, then it works the same, even I set the RS in sendData to 1 !!? But I don't know where is the problem. – R1S8K May 13 '17 at 14:35
  • You might like to try attaching a logic analyser to examine precisely what is being sent from the Arduino to the LCD. – Majenko May 13 '17 at 23:20
  • Hello friends :) I discovered the problem!! One member told me about. Which is that I override the bitmask for the RS in data function, so it would still work as a command function, he solved that for me by adding the RS bitmask with I2C_tx(bitmask = (data<<4) & 0xF0 | 0x08 |= (1<<RS)); – R1S8K May 14 '17 at 9:11
1
I2C_tx(bitmask |= (1<<RS));
I2C_tx(bitmask &= ~(1<<RW));
I2C_tx(bitmask = data & 0xF0 | 0x08);

RS is overridden in the third line, so the solution is:

I2C_tx(bitmask = data & 0xF0 | 0x08 | (1<<RS));

And delete the first two lines :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.