Hell guys, i'm trying to communicate with LCD2004a with the I2C extender.

i followed this guide: https://www.youtube.com/watch?v=7mQppaEJjT4

what i did:

  1. I generated project using CUBEMX to Keil uvision
  2. configure I2C with those parameters: 100Khz CLK, slave address 0x27( i checked with I2C scanner that is actually the address)
  3. added the library i2c-lcd to my project (downladed from the link in the youtube video)
  4. change the parameter SLAVE_ADDRESS_LCD in the source code of the library to 0x27
  5. connect the SDA to PB7 and SCL to PB6 like the default pinout that CUBEMX offer me

and nothing happened. its look like the LCD not communicate with my board at all. those modules working well with Arduino so the problem is not with them.

here is my main function (simple hello world):

int main(void)

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
    lcd_send_cmd(0x80|0x00);                        // first line address
    lcd_send_string("Hello word");
  /* USER CODE END 2 */

  /* Infinite loop */
  while (1)

    /* USER CODE BEGIN 3 */
  /* USER CODE END 3 */

here is my pinout enter image description here

here is the library i use:

/** Put this in the src folder **/

#include "i2c-lcd.h"
extern I2C_HandleTypeDef hi2c1;  // change your handler here accordingly

#define SLAVE_ADDRESS_LCD 0x27 // change this according to ur setup

void lcd_send_cmd (char cmd)
  char data_u, data_l;
    uint8_t data_t[4];
    data_u = (cmd&0xf0);
    data_l = ((cmd<<4)&0xf0);
    data_t[0] = data_u|0x0C;  //en=1, rs=0
    data_t[1] = data_u|0x08;  //en=0, rs=0
    data_t[2] = data_l|0x0C;  //en=1, rs=0
    data_t[3] = data_l|0x08;  //en=0, rs=0
    HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD,(uint8_t *) data_t, 4, 100);

void lcd_send_data (char data)
    char data_u, data_l;
    uint8_t data_t[4];
    data_u = (data&0xf0);
    data_l = ((data<<4)&0xf0);
    data_t[0] = data_u|0x0D;  //en=1, rs=1
    data_t[1] = data_u|0x09;  //en=0, rs=1
    data_t[2] = data_l|0x0D;  //en=1, rs=1
    data_t[3] = data_l|0x09;  //en=0, rs=1
    HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD,(uint8_t *) data_t, 4, 100);

void lcd_clear (void)
    lcd_send_cmd (0x00);
    for (int i=0; i<100; i++)
        lcd_send_data (' ');

void lcd_init (void)
    // 4 bit initialisation
    HAL_Delay(50);  // wait for >40ms
    lcd_send_cmd (0x30);
    HAL_Delay(5);  // wait for >4.1ms
    lcd_send_cmd (0x30);
    HAL_Delay(4);  // wait for >100us
    lcd_send_cmd (0x30);
    lcd_send_cmd (0x20);  // 4bit mode

  // dislay initialisation
    lcd_send_cmd (0x28); // Function set --> DL=0 (4 bit mode), N = 1 (2 line display) F = 0 (5x8 characters)
    lcd_send_cmd (0x08); //Display on/off control --> D=0,C=0, B=0  ---> display off
    lcd_send_cmd (0x01);  // clear display
    lcd_send_cmd (0x06); //Entry mode set --> I/D = 1 (increment cursor) & S = 0 (no shift)
    lcd_send_cmd (0x0C); //Display on/off control --> D = 1, C and B = 0. (Cursor and blink, last two bits)

void lcd_send_string (char *str)
    while (*str) lcd_send_data (*str++);
  • \$\begingroup\$ Can you please add the information and links to your post, as I don't think many will want to watch the video to figure out what code you got from where. \$\endgroup\$
    – Justme
    Commented Apr 25, 2020 at 15:05
  • \$\begingroup\$ Have you tried observing the signals with an oscilloscope? That would normally be the next step in debugging. \$\endgroup\$ Commented Apr 25, 2020 at 15:11
  • \$\begingroup\$ @ElliotAlderson , yes, measured the the SDA&SCL output from board with scope and it seems they not working \$\endgroup\$
    – Oded Yosef
    Commented Apr 25, 2020 at 15:19
  • \$\begingroup\$ @Justme, hi, which information do you think could be helpful? i add the library i use to my question above \$\endgroup\$
    – Oded Yosef
    Commented Apr 25, 2020 at 15:27
  • \$\begingroup\$ Thanks, better. I see the LCD library is complete garbage and will never work unless fixed. I wonder why people call their bad code a library and put it on the web for other people to download and expecting it to work. \$\endgroup\$
    – Justme
    Commented Apr 25, 2020 at 15:46

1 Answer 1


Classic issue of getting the I2C address wrong. The address is 0x27 in the 7-bit notation which excludes the read/write bit. With STM32 I2C HAL, 8-bit addresses which include the read/write bit are used. Set the I2C address to 0x4E.

I still suggest changing the library. The LCD initialization to 4-bit mode is done incorrectly. And the LCD clear command as well. And it does not check the result of I2C write, so unless you use a debugger, you can't tell if the I2C operations succeed or fail for some reason. You might want to check that you can control the backlight to see of I2C writes fail or are OK.

  • \$\begingroup\$ could you please explain me how debug the I2C operation with the debug session? and i think the backlight control connected direct to the LCD(If you meant to the potentiometer) \$\endgroup\$
    – Oded Yosef
    Commented Apr 25, 2020 at 17:25
  • \$\begingroup\$ Potentiometer is for contrast adjustment. Backlight is controlled via the I2C expander chip. Debugging can reveal if the I2C fails or not. Just debug it. \$\endgroup\$
    – Justme
    Commented Apr 25, 2020 at 17:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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