Interfacing 16X2 LCD With STM32 & Cube IDE

by vanshika4566_be23 in Circuits > Microcontrollers

592 Views, 1 Favorites, 0 Comments

Interfacing 16X2 LCD With STM32 & Cube IDE

Screenshot 2024-03-17 181301.png
lcd.jpeg

Hello!

In this tutorial, you’ll learn how to interface STM32 with LCD 16×2 display and integrate the STM32 LCD library into your project. 

Supplies

  • STM32 Black pill board
  • STM32 Cube IDE Software
  • 16*2 LCD Display
  • Jumper wires (M-M, F-M)
  • USB –Type C cable
  • Potentiometer- 10K
  • Breadboard

MAKE CONNECTIONS

Screenshot 2024-05-05 024815.png
  • The first step is to make connections between the components.
  • Make pin connection between LCD display and STM32 black pill board as shown in the images.
  • Also use breadboard to connect potentiometer and resistor to LCD display and STM32 board.
  • The project will work without making use of potentiometer and resistor but it is better to use potentiometer for display quality and resistor for durability.

STM32 Cube IDE Pin Settings

Screenshot 2024-05-05 032029.png
  • Open Cube IDE and go to Pinout and Configuration
  • Now in Pinout view select the pins that you used in the hardware connections
  • Here from the above step set PA1, PA3, PB0, PB1, PB10 and PB11 to GPIO_Output
  • Now, to setup timer to create delay in microseconds, click on clock configuration >>HSE>>PLL CLK
  • Now, select resolve clock issues from the top in the center
  • Save the settings

Program : Code for Libraries(Inside Core/Inc Folder)

  • Add code in Inc folder that is inside Core
  • The code is given below:

/*

 * lcd.h

 *

 * Created on: 10/06/2018

 *   Author: Olivier Van den Eede

 */

#ifndef LCD_H_

#define LCD_H_

#include "stm32f1xx_hal.h"

#include "string.h"

#include "stdio.h"

#include "main.h"

// #define LCD20xN // For 20xN LCDs

#define LCD16xN // For 16xN LCDs

// For row start addresses

extern const uint8_t ROW_16[];

extern const uint8_t ROW_20[];

/************************************* Command register **************************************/

#define CLEAR_DISPLAY 0x01

#define RETURN_HOME 0x02

#define ENTRY_MODE_SET 0x04

#define OPT_S 0x01 // Shift entire display to right

#define OPT_INC 0x02 // Cursor increment

#define DISPLAY_ON_OFF_CONTROL 0x08

#define OPT_D 0x04 // Turn on display

#define OPT_C 0x02 // Turn on cursor

#define OPT_B 0x01 // Turn on cursor blink

#define CURSOR_DISPLAY_SHIFT 0x10 // Move and shift cursor

#define OPT_SC 0x08

#define OPT_RL 0x04

#define FUNCTION_SET 0x20

#define OPT_DL 0x10 // Set interface data length

#define OPT_N 0x08 // Set number of display lines

#define OPT_F 0x04 // Set alternate font

#define SETCGRAM_ADDR 0x040

#define SET_DDRAM_ADDR 0x80 // Set DDRAM address

/************************************** Helper macros **************************************/

#define DELAY(X) HAL_Delay(X)

/************************************** LCD defines **************************************/

#define LCD_NIB 4

#define LCD_BYTE 8

#define LCD_DATA_REG 1

#define LCD_COMMAND_REG 0

/************************************** LCD typedefs **************************************/

#define Lcd_PortType GPIO_TypeDef*

#define Lcd_PinType uint16_t

typedef enum {

LCD_4_BIT_MODE,

LCD_8_BIT_MODE

} Lcd_ModeTypeDef;

typedef struct {

Lcd_PortType * data_port;

Lcd_PinType * data_pin;

Lcd_PortType rs_port;

Lcd_PinType rs_pin;

Lcd_PortType en_port;

Lcd_PinType en_pin;

Lcd_ModeTypeDef mode;}

Lcd_HandleTypeDef;

/************************************** Public functions **************************************/

void Lcd_init(Lcd_HandleTypeDef * lcd);

void Lcd_int(Lcd_HandleTypeDef * lcd, int number);

void Lcd_string(Lcd_HandleTypeDef * lcd, char * string);

void Lcd_cursor(Lcd_HandleTypeDef * lcd, uint8_t row, uint8_t col);

Lcd_HandleTypeDef Lcd_create(

Lcd_PortType port[], Lcd_PinType pin[],

Lcd_PortType rs_port, Lcd_PinType rs_pin,

Lcd_PortType en_port, Lcd_PinType en_pin, Lcd_ModeTypeDef mode);

void Lcd_define_char(Lcd_HandleTypeDef * lcd, uint8_t code, uint8_t bitmap[]);

void Lcd_clear(Lcd_HandleTypeDef * lcd);

#endif /* LCD_H_ */

Program : Code for Libraries(Inside Core/Src Folder)

/*

 * lcd.c

 *

 * Created on: 10/06/2018

 *   Author: Olivier Van den Eede

 */

#include "lcd.h"

const uint8_t ROW_16[] = {0x00, 0x40, 0x10, 0x50};

const uint8_t ROW_20[] = {0x00, 0x40, 0x14, 0x54};

/************************************** Static declarations **************************************/

static void lcd_write_data(Lcd_HandleTypeDef * lcd, uint8_t data);

static void lcd_write_command(Lcd_HandleTypeDef * lcd, uint8_t command);

static void lcd_write(Lcd_HandleTypeDef * lcd, uint8_t data, uint8_t len);

/************************************** Function definitions **************************************/

/**

 * Create new Lcd_HandleTypeDef and initialize the Lcd

 */

Lcd_HandleTypeDef Lcd_create(

Lcd_PortType port[], Lcd_PinType pin[],

Lcd_PortType rs_port, Lcd_PinType rs_pin,

Lcd_PortType en_port, Lcd_PinType en_pin, Lcd_ModeTypeDef mode)

{

Lcd_HandleTypeDef lcd;

lcd.mode = mode;

lcd.en_pin = en_pin;

lcd.en_port = en_port;

lcd.rs_pin = rs_pin;

lcd.rs_port = rs_port;

lcd.data_pin = pin;

lcd.data_port = port;

Lcd_init(&lcd);

return lcd;

}

/**

 * Initialize 16x2-lcd without cursor

 */

void Lcd_init(Lcd_HandleTypeDef * lcd)

{if(lcd->mode == LCD_4_BIT_MODE)

{lcd_write_command(lcd, 0x33);

lcd_write_command(lcd, 0x32);

lcd_write_command(lcd, FUNCTION_SET | OPT_N); // 4-bit mode

}

else

lcd_write_command(lcd, FUNCTION_SET | OPT_DL | OPT_N);

lcd_write_command(lcd, CLEAR_DISPLAY); // Clear screen

lcd_write_command(lcd, DISPLAY_ON_OFF_CONTROL | OPT_D); // Lcd-on, cursor-off, no-blink

lcd_write_command(lcd, ENTRY_MODE_SET | OPT_INC); // Increment cursor

}

/**

 * Write a number on the current position

 */

void Lcd_int(Lcd_HandleTypeDef * lcd, int number)

{

char buffer[11];

sprintf(buffer, "%d", number);

Lcd_string(lcd, buffer);

}

/**

 * Write a string on the current position

 */

void Lcd_string(Lcd_HandleTypeDef * lcd, char * string)

{

for(uint8_t i = 0; i < strlen(string); i++)

{lcd_write_data(lcd, string[i]);

}

}

/**

 * Set the cursor position

 */

void Lcd_cursor(Lcd_HandleTypeDef * lcd, uint8_t row, uint8_t col)

{

#ifdef LCD20xN

lcd_write_command(lcd, SET_DDRAM_ADDR + ROW_20[row] + col);

#endif

#ifdef LCD16xN

lcd_write_command(lcd, SET_DDRAM_ADDR + ROW_16[row] + col);

#endif

}

/**

 * Clear the screen

 */

void Lcd_clear(Lcd_HandleTypeDef * lcd) {

lcd_write_command(lcd, CLEAR_DISPLAY);

}

void Lcd_define_char(Lcd_HandleTypeDef * lcd, uint8_t code, uint8_t bitmap[]){

lcd_write_command(lcd, SETCGRAM_ADDR + (code << 3));

for(uint8_t i=0;i<8;++i){

lcd_write_data(lcd, bitmap[i]);

}

}

/************************************** Static function definition **************************************/

/**

 * Write a byte to the command register

 */

void lcd_write_command(Lcd_HandleTypeDef * lcd, uint8_t command)

{

HAL_GPIO_WritePin(lcd->rs_port, lcd->rs_pin, LCD_COMMAND_REG); // Write to command register

if(lcd->mode == LCD_4_BIT_MODE)

{lcd_write(lcd, (command >> 4), LCD_NIB);

lcd_write(lcd, command & 0x0F, LCD_NIB);}

else

{lcd_write(lcd, command, LCD_BYTE);}

}

/**

 * Write a byte to the data register

 */

void lcd_write_data(Lcd_HandleTypeDef * lcd, uint8_t data)

{

HAL_GPIO_WritePin(lcd->rs_port, lcd->rs_pin, LCD_DATA_REG); // Write to data register

if(lcd->mode == LCD_4_BIT_MODE)

{lcd_write(lcd, data >> 4, LCD_NIB);

lcd_write(lcd, data & 0x0F, LCD_NIB);}

else

{lcd_write(lcd, data, LCD_BYTE);}


}

/**

 * Set len bits on the bus and toggle the enable line

 */

void lcd_write(Lcd_HandleTypeDef * lcd, uint8_t data, uint8_t len

{

for(uint8_t i = 0; i < len; i++)

{HAL_GPIO_WritePin(lcd->data_port[i], lcd->data_pin[i], (data >> i) & 0x01);}

HAL_GPIO_WritePin(lcd->en_port, lcd->en_pin, 1);

DELAY(1);

HAL_GPIO_WritePin(lcd->en_port, lcd->en_pin, 0); // Data receive on falling edge

}


  • Save and close the files

Program for Main.c

Screenshot 2024-05-05 031939.png
  • Add #include "lcd.h" under /* USER CODE BEGIN Includes */
  • Additional code on top of STM32CubeIDE generated code is given below:

// Lcd_PortType ports[] = { D4_GPIO_Port, D5_GPIO_Port, D6_GPIO_Port, D7_GPIO_Port };

Lcd_PortType ports[] = { GPIOB, GPIOB, GPIOB, GPIOB };

// Lcd_PinType pins[] = {D4_Pin, D5_Pin, D6_Pin, D7_Pin};

Lcd_PinType pins[] = {GPIO_PIN_0, GPIO_PIN_1, GPIO_PIN_10, GPIO_PIN_11};

Lcd_HandleTypeDef lcd;

// Lcd_create(ports, pins, RS_GPIO_Port, RS_Pin, EN_GPIO_Port, EN_Pin, LCD_4_BIT_MODE);

lcd = Lcd_create(ports, pins, GPIOA, GPIO_PIN_1, GPIOA, GPIO_PIN_3, LCD_4_BIT_MODE);

Lcd_cursor(&lcd, 0,1);

Lcd_string(&lcd, "Vanshika Rana");

for ( int x = 1; x <= 200 ; x++ )

{

Lcd_cursor(&lcd, 1,7);

Lcd_int(&lcd, x);

HAL_Delay (1000);}



Cube Programmer

Screenshot 2024-05-05 033420.png
  • Now, copy path of project file generated
  • Open STM32 cube programmer>>main.c (beside Device memory)>> Open file
  • Enter file path and connect the STM32 black pill via USB cable
  • Click on Download and fill the blank space with file path. Check the boxes and click on Start Automatic Mode
  • The LCD displays your name