diff --git a/Core/Inc/LCD16x2.h b/Core/Inc/LCD16x2.h
new file mode 100644
index 0000000000000000000000000000000000000000..54566b5f8b94f157dbc3c258b5e468a0dd78621b
--- /dev/null
+++ b/Core/Inc/LCD16x2.h
@@ -0,0 +1,33 @@
+#ifndef LCD16X2_H_
+#define LCD16X2_H_
+
+#include "stm32f4xx_hal.h"
+
+typedef struct
+{
+    GPIO_TypeDef * LCD_GPIO;
+    uint16_t D4_PIN;
+    uint16_t D5_PIN;
+    uint16_t D6_PIN;
+    uint16_t D7_PIN;
+    uint16_t EN_PIN;
+    uint16_t RS_PIN;
+    uint16_t LCD_EN_Delay;
+}LCD16x2_CfgType;
+
+
+//-----[ Prototypes For All Functions ]-----
+
+
+void LCD_Init();                  // Initialize The LCD For 4-Bit Interface
+void LCD_Clear();                 // Clear The LCD Display
+void LCD_SL();                    // Shift The Entire Display To The Left
+void LCD_SR();                    // Shift The Entire Display To The Right
+void LCD_CMD(unsigned char);      // Send Command To LCD
+void LCD_DATA(unsigned char);     // Send 4-Bit Data To LCD
+void LCD_Set_Cursor(unsigned char, unsigned char);  // Set Cursor Position
+void LCD_Write_Char(char);        // Write Character To LCD At Current Position
+void LCD_Write_String(char*);     // Write A String To LCD
+
+
+#endif /* LCD16X2_H_ */
\ No newline at end of file
diff --git a/Core/Inc/LCD16x2_cfg.h b/Core/Inc/LCD16x2_cfg.h
new file mode 100644
index 0000000000000000000000000000000000000000..4c6a199dbaa6493c6d372f98d1f1a246850c5711
--- /dev/null
+++ b/Core/Inc/LCD16x2_cfg.h
@@ -0,0 +1,9 @@
+
+#ifndef LCD16X2_CFG_H_
+#define LCD16X2_CFG_H_
+
+#include "LCD16x2.h"
+
+extern const LCD16x2_CfgType LCD16x2_CfgParam;
+
+#endif /* LCD16X2_CFG_H_ */
diff --git a/Core/Src/DWT_Delay.c b/Core/Src/DWT_Delay.c
new file mode 100644
index 0000000000000000000000000000000000000000..93076e586163e99278d7dae5eecd773ccf60797d
--- /dev/null
+++ b/Core/Src/DWT_Delay.c
@@ -0,0 +1,46 @@
+/*
+ * File: DWT_Delay.c
+ * Driver Name: [[ DWT Delay ]]
+ * SW Layer:   ECUAL
+ * Created on: Jun 28, 2020
+ * Author:     Khaled Magdy
+ * -------------------------------------------
+ * For More Information, Tutorials, etc.
+ * Visit Website: www.DeepBlueMbedded.com
+ *
+ */
+
+#include "DWT_Delay.h"
+
+
+uint32_t DWT_Delay_Init(void)
+{
+    /* Disable TRC */
+    CoreDebug->DEMCR &= ~CoreDebug_DEMCR_TRCENA_Msk; // ~0x01000000;
+    /* Enable TRC */
+    CoreDebug->DEMCR |=  CoreDebug_DEMCR_TRCENA_Msk; // 0x01000000;
+
+    /* Disable clock cycle counter */
+    DWT->CTRL &= ~DWT_CTRL_CYCCNTENA_Msk; //~0x00000001;
+    /* Enable  clock cycle counter */
+    DWT->CTRL |=  DWT_CTRL_CYCCNTENA_Msk; //0x00000001;
+
+    /* Reset the clock cycle counter value */
+    DWT->CYCCNT = 0;
+
+    /* 3 NO OPERATION instructions */
+    __ASM volatile ("NOP");
+    __ASM volatile ("NOP");
+    __ASM volatile ("NOP");
+
+    /* Check if clock cycle counter has started */
+    if(DWT->CYCCNT)
+    {
+       return 0; /*clock cycle counter started*/
+    }
+    else
+    {
+      return 1; /*clock cycle counter not started*/
+    }
+}
+
diff --git a/Core/Src/LCD16x2.c b/Core/Src/LCD16x2.c
new file mode 100644
index 0000000000000000000000000000000000000000..8d197a22aa5aaf6107ba3ae8fede3aa4cec526c7
--- /dev/null
+++ b/Core/Src/LCD16x2.c
@@ -0,0 +1,153 @@
+
+
+#include "LCD16x2.h"
+#include "LCD16x2_cfg.h"
+#include "DWT_Delay.h"
+
+
+//-----[ Alphanumeric LCD 16x2 Routines ]-----
+
+void LCD_DATA(unsigned char Data)
+{
+    if(Data & 1)
+    	HAL_GPIO_WritePin(LCD16x2_CfgParam.LCD_GPIO, LCD16x2_CfgParam.D4_PIN, 1);
+    else
+    	HAL_GPIO_WritePin(LCD16x2_CfgParam.LCD_GPIO, LCD16x2_CfgParam.D4_PIN, 0);
+    if(Data & 2)
+    	HAL_GPIO_WritePin(LCD16x2_CfgParam.LCD_GPIO, LCD16x2_CfgParam.D5_PIN, 1);
+    else
+    	HAL_GPIO_WritePin(LCD16x2_CfgParam.LCD_GPIO, LCD16x2_CfgParam.D5_PIN, 0);
+    if(Data & 4)
+    	HAL_GPIO_WritePin(LCD16x2_CfgParam.LCD_GPIO, LCD16x2_CfgParam.D6_PIN, 1);
+    else
+    	HAL_GPIO_WritePin(LCD16x2_CfgParam.LCD_GPIO, LCD16x2_CfgParam.D6_PIN, 0);
+    if(Data & 8)
+    	HAL_GPIO_WritePin(LCD16x2_CfgParam.LCD_GPIO, LCD16x2_CfgParam.D7_PIN, 1);
+    else
+    	HAL_GPIO_WritePin(LCD16x2_CfgParam.LCD_GPIO, LCD16x2_CfgParam.D7_PIN, 0);
+}
+void LCD_CMD(unsigned char a_CMD)
+{
+    // Select Command Register
+    HAL_GPIO_WritePin(LCD16x2_CfgParam.LCD_GPIO, LCD16x2_CfgParam.RS_PIN, 0);
+    // Move The Command Data To LCD
+    LCD_DATA(a_CMD);
+    // Send The EN Clock Signal
+    HAL_GPIO_WritePin(LCD16x2_CfgParam.LCD_GPIO, LCD16x2_CfgParam.EN_PIN, 1);
+    DWT_Delay_us(LCD16x2_CfgParam.LCD_EN_Delay);
+    HAL_GPIO_WritePin(LCD16x2_CfgParam.LCD_GPIO, LCD16x2_CfgParam.EN_PIN, 0);
+    DWT_Delay_us(LCD16x2_CfgParam.LCD_EN_Delay);
+}
+void LCD_Clear()
+{
+    LCD_CMD(0);
+    LCD_CMD(1);
+    DWT_Delay_us(70);
+}
+void LCD_Set_Cursor(unsigned char r, unsigned char c)
+{
+    unsigned char Temp,Low4,High4;
+    if(r == 1)
+    {
+      Temp  = 0x80 + c - 1; //0x80 is used to move the cursor
+      High4 = Temp >> 4;
+      Low4  = Temp & 0x0F;
+      LCD_CMD(High4);
+      LCD_CMD(Low4);
+    }
+    if(r == 2)
+    {
+      Temp  = 0xC0 + c - 1;
+      High4 = Temp >> 4;
+      Low4  = Temp & 0x0F;
+      LCD_CMD(High4);
+      LCD_CMD(Low4);
+    }
+    DWT_Delay_ms(2);
+}
+void LCD_Init()
+{
+	GPIO_InitTypeDef GPIO_InitStruct = {0};
+	// Initialize The DWT Delay Function Which Will Be Used Later On
+	DWT_Delay_Init();
+    // IO Pin Configurations
+	if(LCD16x2_CfgParam.LCD_GPIO == GPIOA)
+	    __HAL_RCC_GPIOA_CLK_ENABLE();
+	else if(LCD16x2_CfgParam.LCD_GPIO == GPIOB)
+	    __HAL_RCC_GPIOB_CLK_ENABLE();
+	else if(LCD16x2_CfgParam.LCD_GPIO == GPIOC)
+		__HAL_RCC_GPIOC_CLK_ENABLE();
+	else if(LCD16x2_CfgParam.LCD_GPIO == GPIOD)
+		__HAL_RCC_GPIOD_CLK_ENABLE();
+	HAL_GPIO_WritePin(LCD16x2_CfgParam.LCD_GPIO, LCD16x2_CfgParam.D4_PIN, GPIO_PIN_RESET);
+	HAL_GPIO_WritePin(LCD16x2_CfgParam.LCD_GPIO, LCD16x2_CfgParam.D5_PIN, GPIO_PIN_RESET);
+	HAL_GPIO_WritePin(LCD16x2_CfgParam.LCD_GPIO, LCD16x2_CfgParam.D6_PIN, GPIO_PIN_RESET);
+	HAL_GPIO_WritePin(LCD16x2_CfgParam.LCD_GPIO, LCD16x2_CfgParam.D7_PIN, GPIO_PIN_RESET);
+	HAL_GPIO_WritePin(LCD16x2_CfgParam.LCD_GPIO, LCD16x2_CfgParam.RS_PIN, GPIO_PIN_RESET);
+	HAL_GPIO_WritePin(LCD16x2_CfgParam.LCD_GPIO, LCD16x2_CfgParam.EN_PIN, GPIO_PIN_RESET);
+	GPIO_InitStruct.Pin = LCD16x2_CfgParam.D4_PIN | LCD16x2_CfgParam.D5_PIN |
+			LCD16x2_CfgParam.D6_PIN |LCD16x2_CfgParam.D7_PIN | LCD16x2_CfgParam.RS_PIN |
+			LCD16x2_CfgParam.EN_PIN;
+	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+	GPIO_InitStruct.Pull = GPIO_NOPULL;
+	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
+	HAL_GPIO_Init(LCD16x2_CfgParam.LCD_GPIO, &GPIO_InitStruct);
+
+	// The Init. Procedure As Described In The Datasheet
+    HAL_GPIO_WritePin(LCD16x2_CfgParam.LCD_GPIO, LCD16x2_CfgParam.RS_PIN, GPIO_PIN_RESET);
+    HAL_GPIO_WritePin(LCD16x2_CfgParam.LCD_GPIO, LCD16x2_CfgParam.EN_PIN, GPIO_PIN_RESET);
+    LCD_DATA(0x00);
+    DWT_Delay_ms(150);
+    LCD_CMD(0x03);
+    DWT_Delay_ms(5);
+    LCD_CMD(0x03);
+    DWT_Delay_us(150);
+    LCD_CMD(0x03);
+    LCD_CMD(0x02);
+    LCD_CMD(0x02);
+    LCD_CMD(0x08);
+    LCD_CMD(0x00);
+    LCD_CMD(0x0C);
+    LCD_CMD(0x00);
+    LCD_CMD(0x06);
+    LCD_CMD(0x00);
+    LCD_CMD(0x01);
+}
+void LCD_Write_Char(char Data)
+{
+   char Low4,High4;
+   Low4  = Data & 0x0F;
+   High4 = Data & 0xF0;
+
+   HAL_GPIO_WritePin(LCD16x2_CfgParam.LCD_GPIO, LCD16x2_CfgParam.RS_PIN, 1);
+
+   LCD_DATA(High4>>4);
+   HAL_GPIO_WritePin(LCD16x2_CfgParam.LCD_GPIO, LCD16x2_CfgParam.EN_PIN, 1);
+   DWT_Delay_us(LCD16x2_CfgParam.LCD_EN_Delay);
+   HAL_GPIO_WritePin(LCD16x2_CfgParam.LCD_GPIO, LCD16x2_CfgParam.EN_PIN, 0);
+   DWT_Delay_us(LCD16x2_CfgParam.LCD_EN_Delay);
+
+   LCD_DATA(Low4);
+   HAL_GPIO_WritePin(LCD16x2_CfgParam.LCD_GPIO, LCD16x2_CfgParam.EN_PIN, 1);
+   DWT_Delay_us(LCD16x2_CfgParam.LCD_EN_Delay);
+   HAL_GPIO_WritePin(LCD16x2_CfgParam.LCD_GPIO, LCD16x2_CfgParam.EN_PIN, 0);
+   DWT_Delay_us(LCD16x2_CfgParam.LCD_EN_Delay);
+}
+void LCD_Write_String(char *str)
+{
+    int i;
+    for(i=0;str[i]!='\0';i++)
+       LCD_Write_Char(str[i]);
+}
+void LCD_SL()
+{
+    LCD_CMD(0x01);
+    LCD_CMD(0x08);
+    DWT_Delay_us(35);
+}
+void LCD_SR()
+{
+    LCD_CMD(0x01);
+    LCD_CMD(0x0C);
+    DWT_Delay_us(35);
+}
diff --git a/Core/Src/LCD16x2_cfg.c b/Core/Src/LCD16x2_cfg.c
new file mode 100644
index 0000000000000000000000000000000000000000..cd91767975c1361371e4d5c1e826ec052d1cf0c6
--- /dev/null
+++ b/Core/Src/LCD16x2_cfg.c
@@ -0,0 +1,15 @@
+
+
+#include "LCD16x2.h"
+
+const LCD16x2_CfgType LCD16x2_CfgParam =
+{
+	GPIOB,
+	GPIO_PIN_5,
+	GPIO_PIN_6,
+	GPIO_PIN_7,
+	GPIO_PIN_8,
+	GPIO_PIN_3,
+	GPIO_PIN_4,
+	20
+};