Introduction: Printing "YOUR NAME" on LCD Using I2C Interface With STM32F401CE

In this tutorial, we will learn to interface I2C LCD with STM32 Black Pill and program it using STM32CubeIDE and HAL libraries. Firstly, we will briefly introduce you to the I2C LCD including its pinout and connection with STM32 Black Pill. Then we will move ahead and program our board in STMCube IDE to demonstrate some basic functionalities that we can display on the LCD.

Supplies

For this project we will require the following components:

  1. STM32 Blue Pill
  2. I2C LCD
  3. Connecting Wires
  4. STM32CubeIDE
  5. STM32CubeProgrammer


Follow the schematic diagram below to connect all the devices together. We will power the I2C LCD with 3.3V pin of STM32. The SCL and SDA pins of I2C LCD will be connected with the I2C1 SDA and SCL pins of the STM32 board respectively. PB7 is I2C1_SDA pin and PB6 is I2C1_SCL pin. Moreover, the grounds will be in common.

Step 1: STM32 Black Pill I2C LCD Code

We will use STM32CubeIDE to program our STM32 board, Open th eIDE and Head over to a new project.


Step 2:

Then for the target selection, specify the STM32 Black Pill board number. After that click on column as shown in the picture below. Then click the ‘Next’ button.

Step 3:

Add Name to your project and select option as shown in figure.

Step 4: Pin Selection and Clock Configuration

Goto Connectivity>>I2C1, Slect the I2C mode .

Step 5:

Now go to System Core >> RCC then select ‘Crystal/Ceramic Resonator’ in from the High Speed Clock feature.

Now goto Clock configuration and ste your clock as follows:

Step 6:

Now save Your file, press "CTRL+S". This will generate a code template for you.

Step 7: INCLUDING I2C LCD LIBRARIES

As we are working on I2C LCD we have to include liquidcrystal I2C file for displaying our name on LCD

liquidcrystal_i2c.h

liquidcrystal_i2c.c

Or copy code from files given below:

Step 8:

We will use I2C LCD library functions to display text and numbers on the I2C LCD, in static manner .

Now let us look at our main.c file that was generated. Inside the main.c file, make sure the following code is part of your script by including the lines of code given below.

#include "main.h"
#include "liquidcrystal_i2c.h"

I2C_HandleTypeDef hi2c1;

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);

int main(void)
{

HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_I2C1_Init();

HD44780_Init(2);
HD44780_Clear();
HD44780_SetCursor(0,0);
HD44780_PrintStr("Your Name");
HD44780_SetCursor(0,1);
HD44780_PrintStr("Your surname");
HAL_Delay(2000);


CODE EXPLANATION:

We start off by including the liquidcrystal_i2c.h library to access the functions to control the I2C LCD.

#include "liquidcrystal_i2c.h"

Inside the main function, first all the peripherals are initialized, system clock is configured and all the configured peripherals are initialized.

  HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_I2C1_Init();

The first step is to initialize the I2C LCD. We use the HD44780_Init() function for initialization. This function takes in only a single parameter which is the number of rows. As we are using a 16×2 LCD, hence we have specified the ‘2’ as the parameter.

HD44780_Init(2);

Next, we clear the LCD screen by calling HD44780_Clear().

 HD44780_Clear();

Before printing any text, we set the position of the cursor using the HD44780_SetCursor(). This function takes in two parameters. The first parameter is starting column and the second parameter is the starting row. Here we have specified the column as ‘0’ and row as ‘0’ which means the cursor is positioned at the extreme left side of the screen.


 HD44780_SetCursor(0,0);

After setting the cursor, we print the string “Your Name” using the function HD44780_PrintStr(). This function takes in a single argument which is an array of characters that you want to print on the screen.

HD44780_PrintStr("Your Name");

Similarly, we set the cursor at column 0 and row 1 and print “Your surname”

HD44780_SetCursor(0,1);
HD44780_PrintStr("Your surname");

Step 9:

Your Main.c file looks like this:

#include "main.h"
#include "liquidcrystal_i2c.h"
I2C_HandleTypeDef hi2c1;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);
int main(void)
{ HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_I2C1_Init();
HD44780_Init(2);
HD44780_Clear();
HD44780_PrintStr("Your Name");
HD44780_SetCursor(0,1);
HD44780_PrintStr("Your surname");
while (1)
{
/* USER CODE END WHILE */

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

void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);

/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 16;
RCC_OscInitStruct.PLL.PLLN = 192;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
RCC_OscInitStruct.PLL.PLLQ = 4;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV2;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
Error_Handler();
}
}
static void MX_I2C1_Init(void)
{
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 100000;
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
Error_Handler();
}

}
static void MX_GPIO_Init(void)
{
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */

/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();

/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}
void Error_Handler(void)
{
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}

#ifdef USE_FULL_ASSERT

void assert_failed(uint8_t *file, uint32_t line)
{
}
#endif /* USE_FULL_ASSERT */

Step 10:

we will debug the code by the debug option as shown in figure.

and your file will be saved in STM32CubeIDE>workplace. select your project and copy its file Location.

Step 11:

Now ,open STM32CubeProgrammer , and choose usb mode and connect your STM32 Blackpill with it.

Step 12:

Goto >erasing and programming.

Step 13:

In file path enter location of your saved programming file or browse for it.


Choose option as shown if figure.

Our name is show on screen succesfully


Step 14: Troubleshooting While Uploading

If it is not diplayed:

  • try to reset your STM board by pressing reset button on it .
  • or boot it by pressing snd holding BOOTO first and pressing NRST once , and reconnect your stm board and try to upload code now.

This will work for most cases .