[SOLVED] LCD1602 with Arduino I2C, RS override in data function

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:

#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() {
I2C_init();
LCD_Init();
}

void loop() {
  //sendData(0x10);
  
}

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

void sendCMD(uint8_t CMD)
{
  I2C_start(LCDadd_WR);
  I2C_tx(bitmask &= ~(1<<RS));
  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)
{
  I2C_start(LCDadd_WR);
  I2C_tx(bitmask |= (1<<RS));
  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,

Look at your sendData() function. You set up RS correctly and then AND with 0xF0 before you wobble the Enable line.

There are several examples of working code for driving an LCD with a PCF8574.
But if you want to do everything yourself, hand-trace the functions with pencil and paper.
.
You have the Simulator in AS7.
If you have XMINI or ATMEL-ICE you can follow the hardware.

Quite honestly, pencil and paper do just as good a job.

David.

david_prentice:
Look at your sendData() function. You set up RS correctly and then AND with 0xF0 before you wobble the Enable line.

There are several examples of working code for driving an LCD with a PCF8574.
But if you want to do everything yourself, hand-trace the functions with pencil and paper.
.
You have the Simulator in AS7.
If you have XMINI or ATMEL-ICE you can follow the hardware.

Quite honestly, pencil and paper do just as good a job.

David.

I do the "pencil and paper" in some times on my Galaxy Note 10.1 and store the sketches, which is helpful when I feel to but not all the times.

Here in my code, .... what??! wait a minute !

Look at your sendData() function. You set up RS correctly and then AND with 0xF0 before you wobble the Enable line.

OMG you so true :slight_smile:

Thank you very much,