This library provides a complete driver for HD44780-compatible 16x2 alphanumeric LCD displays. It supports both 4-bit and 8-bit communication modes, offering flexibility for different hardware configurations and project requirements.
The library is available in two versions located in separate folders:
STM32_HAL_aLCD_GPIO
└── source/
├── 4-bit mode/
│ ├── alcd.h
│ └── alcd.c
└── 8-bit mode/
├── alcd.h
└── alcd.c
Description:
Data is transmitted through 4 pins (DB4-DB7). Each byte is sent in two stages (upper and lower nibble).
Advantages:
- Fewer pins required (6 pins total: RS, EN, DB4-DB7)
- Ideal for microcontrollers with limited GPIO
- Simplified wiring and reduced hardware complexity
- Backlight control available (optional 7th pin)
Disadvantages:
- Slower communication speed (two cycles per byte)
Pin Requirements:
- 2 Control pins: RS, EN
- 4 Data pins: DB4, DB5, DB6, DB7
- 1 Optional pin: Backlight (BL)
Use Cases:
- Projects with limited GPIO availability
- Simple applications where speed is not critical
- Battery-powered devices (fewer active pins)
Description:
All 8 data bits (DB0-DB7) are transmitted in parallel simultaneously.
Advantages:
- Faster communication speed (complete byte sent in one cycle)
- Simpler implementation and timing
- More reliable data transmission
Disadvantages:
- More pins required (10 pins total: RS, EN, DB0-DB7)
- More complex wiring
Pin Requirements:
- 2 Control pins: RS, EN
- 8 Data pins: DB0, DB1, DB2, DB3, DB4, DB5, DB6, DB7
- 1 Optional pin: Backlight (BL)
Use Cases:
- Performance-critical applications
- Projects with abundant GPIO resources
- Industrial applications requiring high reliability
- Systems with frequent LCD updates
You can reassign LCD pins to any desired microcontroller GPIO pins by modifying the User Labels in STM32CubeMX.
You MUST configure all LCD pins in STM32CubeMX before using this library. The GPIO definitions are automatically generated by CubeMX when you assign User Labels to the pins.
- Open Pinout & Configuration tab
- Select desired GPIO pins
- Set GPIO mode to
GPIO_Output - Set GPIO output level to
Push Pull - Set GPIO speed to
LoworMedium - Enter the exact User Labels as shown above (e.g., __alcd_RS, __alcd_EN, etc.)
- Generate code to create the GPIO definitions
Set these User Labels in CubeMX:
- Control Pins:
- RS pin →
__alcd_RS - EN pin →
__alcd_EN
- RS pin →
- Data Pins:
- DB4 pin →
__alcd_DB4 - DB5 pin →
__alcd_DB5 - DB6 pin →
__alcd_DB6 - DB7 pin →
__alcd_DB7
- DB4 pin →
/* Control Pins */
RS -> PA15
EN -> PA8
/* Data Pins */
DB4 -> PA7
DB5 -> PB0
DB6 -> PB1
DB7 -> PA9The backlight feature is optional for both modes. To enable it:
- Optional Backlight:
- BL pin →
__alcd_BL
- BL pin →
/* Optional Backlight */
BL -> PB12Set these User Labels in CubeMX:
- Control Pins:
- RS pin →
__alcd_RS - EN pin →
__alcd_EN
- RS pin →
- Data Pins:
- DB0 pin →
__alcd_DB0 - DB1 pin →
__alcd_DB1 - DB2 pin →
__alcd_DB2 - DB3 pin →
__alcd_DB3 - DB4 pin →
__alcd_DB4 - DB5 pin →
__alcd_DB5 - DB6 pin →
__alcd_DB6 - DB7 pin →
__alcd_DB7
- DB0 pin →
/* Control Pins */
RS -> PA9
EN -> PA11
/* Data Pins */
DB0 -> PA1
DB1 -> PA2
DB2 -> PA3
DB3 -> PA4
DB4 -> PA5
DB5 -> PA6
DB6 -> PA7
DB7 -> PA8Important
The backlight pin (typically LCD pin 16, LED-) should be driven through an NPN transistor to handle the current properly and protect the microcontroller.
Description:
Initializes the LCD module. This function must be called first before using any other LCD function.
Operation:
- Confirms GPIO pins are configured as outputs (this is done in CubeMX)
- Executes HD44780 initialization sequence
- Sets 4-bit or 8-bit interface mode
- Enables the display
- Clears the screen
Parameters:
None
Returns:
None
Example:
#include "aKaReZa.h"
#include "alcd.h"
int main(void)
{
alcd_init(); // Initialize LCD - Must be called first
// Your code here
while(1)
{
// Main loop
}
}Important
Currently, this library supports only 16×2 LCD displays. For different sizes, library modifications may be required.
Description:
Clears the entire display and returns the cursor to the home position (0, 0).
Parameters:
None
Returns:
None
Execution Time:
~1.52ms (longest command execution time)
Example:
alcd_clear(); // Clear display and reset cursorDescription:
Controls the display, cursor, and blink settings.
Parameters:
_alcd_Display- Display statetrue: Turn display ONfalse: Turn display OFF
_alcd_Cursor- Cursor visibilitytrue: Show cursor (underline)false: Hide cursor
_alcd_Blink- Cursor blink statetrue: Enable blinking (block cursor)false: Disable blinking
Returns:
None
Default State:
Display ON, Cursor OFF, Blink OFF
Examples:
// Display ON, cursor and blink OFF (default)
alcd_display(true, false, false);
// Display ON, cursor ON (underline), blink OFF
alcd_display(true, true, false);
// Display ON, cursor OFF, blink ON (block blink)
alcd_display(true, false, true);
// Display ON, cursor ON with blink (underline + block)
alcd_display(true, true, true);
// Turn off display completely
alcd_display(false, false, false);Note
By default, the display is ON. You don't need to explicitly enable it after initialization.
Description:
Moves the cursor to the specified position on the LCD.
Parameters:
_alcd_x- Column position (0 to 15)_alcd_y- Row position (0 or 1)
Returns:
None
Valid Ranges:
- Column: 0-15 (16 columns)
- Row: 0-1 (2 rows)
Examples:
alcd_gotoxy(0, 0); // First column, first row (home position)
alcd_gotoxy(5, 1); // Sixth column, second row
alcd_gotoxy(15, 0); // Last column, first row
alcd_gotoxy(0, 1); // First column, second rowWarning
- First row index is
0, second row index is1(not 1 and 2) - Exceeding valid ranges may cause unexpected behavior
Description:
Low-level function to send a command or data byte to the LCD.
Parameters:
_data- 8-bit value to send (command or data)_alcd_cmdData- Byte type selector__alcd_writeCmd(false): Send as command__alcd_writeData(true): Send as data
Returns:
None
Execution Time:
Minimum 37μs per command
Examples:
// Write character 'A' (ASCII 0x41)
alcd_write(0x41, __alcd_writeData);
// Send clear display command
alcd_write(__alcd_Display_Clear, __alcd_writeCmd);
// Move cursor to second line
alcd_write(__alcd_Line2_Start, __alcd_writeCmd);
// Write character 'Z'
alcd_write('Z', __alcd_writeData);Note
This is a low-level function. For normal text display, use alcd_putc() or alcd_puts() instead.
Description:
Displays a single character at the current cursor position.
Parameters:
_char- Character to display (ASCII character)
Returns:
None
Examples:
alcd_putc('A'); // Display 'A'
alcd_putc('9'); // Display '9'
alcd_putc(' '); // Display space
alcd_putc(0); // Display custom character 0 (from CGRAM)Description:
Displays a null-terminated string starting at the current cursor position.
Parameters:
_str- Pointer to null-terminated string
Returns:
None
Examples:
alcd_puts("Hello"); // Display "Hello"
alcd_puts("LCD Display"); // Display "LCD Display"
char message[] = "STM32 MCU";
alcd_puts(message); // Display "STM32 MCU"Complete Example:
#include "aKaReZa.h"
#include "alcd.h"
int main(void)
{
alcd_init();
alcd_gotoxy(0, 0); // First row
alcd_putc('X'); // Single character
alcd_gotoxy(0, 1); // Second row
alcd_puts("Hello, World!"); // String
while(1)
{
// Main loop
}
}Description:
Controls the LCD backlight (if enabled via __alcd_useBL macro).
Parameters:
_alcd_BL- Backlight statetrue: Turn backlight ONfalse: Turn backlight OFF
Returns:
None
Availability:
Only available when #define __alcd_useBL true is set in alcd.h
Examples:
// Turn backlight ON
alcd_backLight(true);
// Turn backlight OFF
alcd_backLight(false);
// Blinking backlight example
while(1)
{
alcd_backLight(true);
HAL_Delay(500);
alcd_backLight(false);
HAL_Delay(500);
}Important
- The backlight pin should be connected through an NPN transistor
- Typical LCD backlight current: 20-150mA
- Direct connection to MCU pin may damage the microcontroller
- Consider power consumption in battery-powered applications
Description:
Creates a custom character and stores it in the LCD's CGRAM (Character Generator RAM).
Parameters:
_alcd_CGRAMadd- CGRAM address (0-7)_alcd_CGRAMdata- Pointer to 8-byte array defining the character pattern
Returns:
None
Character Format:
- Each byte represents one row (8 rows total)
- Only lower 5 bits are used (5×8 pixel characters)
- Top to bottom arrangement
CGRAM Limits:
- Maximum 8 custom characters (addresses 0-7)
- Custom characters accessible via ASCII codes 0-7
Examples:
#include "aKaReZa.h"
#include "alcd.h"
// Define custom characters
uint8_t heart[8] =
{
0b00000, // Row 1: .....
0b01010, // Row 2: .#.#.
0b11111, // Row 3: #####
0b11111, // Row 4: #####
0b01110, // Row 5: .###.
0b00100, // Row 6: ..#..
0b00000, // Row 7: .....
0b00000 // Row 8: .....
};
uint8_t smiley[8] =
{
0b00000, // Row 1: .....
0b01010, // Row 2: .#.#.
0b01010, // Row 3: .#.#.
0b00000, // Row 4: .....
0b10001, // Row 5: #...#
0b01110, // Row 6: .###.
0b00000, // Row 7: .....
0b00000 // Row 8: .....
};
uint8_t arrow[8] =
{
0b00100, // Row 1: ..#..
0b00110, // Row 2: ..##.
0b00111, // Row 3: ..###
0b00110, // Row 4: ..##.
0b00100, // Row 5: ..#..
0b00000, // Row 6: .....
0b00000, // Row 7: .....
0b00000 // Row 8: .....
};
int main(void)
{
alcd_init();
// Store custom characters in CGRAM
alcd_customChar(0, heart); // Address 0
alcd_customChar(1, smiley); // Address 1
alcd_customChar(2, arrow); // Address 2
// Display custom characters
alcd_gotoxy(0, 0);
alcd_putc(0); // Display heart
alcd_putc(' ');
alcd_putc(1); // Display smiley
alcd_putc(' ');
alcd_putc(2); // Display arrow
while(1)
{
// Main loop
}
}Tip
Online Custom Character Generators:
These tools provide visual character design and generate the byte arrays automatically.
Best Practices:
- Define custom characters during initialization
- Store frequently used characters
- CGRAM data persists until power off or reinitialization
- Use descriptive names for character arrays
| Function | Purpose | Mode Support |
|---|---|---|
alcd_init() |
Initialize LCD module | 4-bit / 8-bit |
alcd_clear() |
Clear display and reset cursor | 4-bit / 8-bit |
alcd_display(d, c, b) |
Control display, cursor, blink | 4-bit / 8-bit |
alcd_gotoxy(x, y) |
Move cursor to position | 4-bit / 8-bit |
alcd_write(data, type) |
Send command or data byte | 4-bit / 8-bit |
alcd_putc(char) |
Display single character | 4-bit / 8-bit |
alcd_puts(string) |
Display string | 4-bit / 8-bit |
alcd_backLight(state) |
Control backlight | 4-bit / 8-bit |
alcd_customChar(addr, data) |
Create custom character | 4-bit / 8-bit |
#include "aKaReZa.h"
#include "alcd.h"
int main(void)
{
// Initialize LCD
alcd_init();
// Clear display
alcd_clear();
// Turn on backlight
alcd_backLight(true);
// Display text on first row
alcd_gotoxy(0, 0);
alcd_puts("Hello, World!");
// Display text on second row
alcd_gotoxy(0, 1);
alcd_puts("aKaReZa");
while(1)
{
// Main loop
}
}- Always call
alcd_init()first before using any other LCD function - Wait for power stabilization (50ms) before initialization
- Initialization sequence differs between 4-bit and 8-bit modes
- Verify pin definitions in
alcd.hmatch your actual hardware connections - Most LCD modules have a contrast potentiometer - adjust for optimal visibility
- Use appropriate current-limiting resistors for backlight LED
- Backlight transistor is recommended for current handling
- Maximum 8 custom characters (addresses 0-7)
- ASCII codes 0-7 display custom characters
- Character data is 5×8 pixels (only 5 bits used per byte)
- CGRAM is volatile - lost on power off
- First row: index
0(not 1) - Second row: index
1(not 2) - First column: index
0(not 1) - Last column: index
15(not 16)
- Command execution: Minimum 37μs
- Clear display: 1.52ms (longest command)
- 4-bit mode: Slower than 8-bit (two cycles per byte)
- 8-bit mode: Faster but uses more pins
- CGRAM writes: Perform during initialization
- Backlight: May significantly affect power consumption
Choose 4-Bit Mode when:
- GPIO pins are limited
- Speed is not critical
- Simpler wiring is preferred
- Battery power efficiency matters
Choose 8-Bit Mode when:
- High-speed updates required
- Abundant GPIO available
- Maximum performance needed
- Reliability is critical
Problem: Display shows random characters
- Solution: Check contrast potentiometer adjustment
- Solution: Verify power supply voltage (typically 5V)
Problem: No display output
- Solution: Confirm
alcd_init()is called first - Solution: Check all pin connections
Problem: Garbled text
- Solution: Verify timing delays are adequate
- Solution: Check for correct mode (4-bit vs 8-bit)
Problem: Backlight not working
- Solution: Ensure
__alcd_useBLis set totrue - Solution: Check transistor and current-limiting resistor
| Feature | 4-Bit Mode | 8-Bit Mode |
|---|---|---|
| Pins Required | 6 (+1 backlight) | 10 (+1 backlight) |
| Speed | Slower (2 cycles/byte) | Faster (1 cycle/byte) |
| Wiring Complexity | Simple | Complex |
| Best Use Case | GPIO-limited projects | Performance-critical apps |
| Power Consumption | Lower | Higher |
| Reliability | Good | Excellent |
The library implements precise timing according to HD44780 specifications:
| Operation | Time | Constant |
|---|---|---|
| Standard Command | 50μs | __alcd_delay_CMD |
| Mode Setting | 5ms | __alcd_delay_modeSet |
| Power-On Delay | 50ms | __alcd_delay_powerON |
| Clear Display | 1.52ms | Special handling |
Symptom: Blank screen (backlight on)
- Check contrast adjustment (turn potentiometer)
- Verify
alcd_init()is called - Check power supply voltage (4.5-5.5V)
- Verify EN pin toggling
Symptom: Display shows blocks/squares
- Incorrect initialization sequence
- Wrong mode selected (4-bit vs 8-bit)
- Timing issues (clock speed mismatch)
- Verify the system clock configuration in STM32CubeMX.
Symptom: Partial or corrupted characters
- Loose connections on data lines
- Incorrect pin definitions in alcd.h
- Ground connection issues
- Voltage fluctuations
Symptom: Characters appear in wrong positions
- DDRAM address calculation error
- Check
alcd_gotoxy()parameters - Row index confusion (0/1 vs 1/2)
Symptom: Backlight won't turn on
- Check
__alcd_useBLis set totrue - Verify transistor connection
- Check current-limiting resistor value
- Test transistor with multimeter
Symptom: Backlight flickers
- Insufficient current capacity
- Weak power supply
- Poor transistor selection
- Check ground connections
Symptom: Random characters after power-on
- Insufficient power-on delay
- Increase
__alcd_delay_powerON - Check power supply rise time
Symptom: Occasional missed characters
- Timing too fast for LCD
- Increase
__alcd_delay_CMD - Check crystal/oscillator accuracy (and ensure the correct source is selected in CubeMX)
-
Copy the correct source files:
Copy from: source/8-bit mode/ Replace: alcd.h and alcd.c -
Update hardware connections:
- Connect DB0-DB3 pins
- Update pin definitions in alcd.h
-
Recompile and test:
- No code changes required
- API remains identical
-
Copy the correct source files:
Copy from: source/4-bit mode/ Replace: alcd.h and alcd.c -
Update hardware connections:
- Disconnect DB0-DB3 pins
- Update pin definitions in alcd.h
-
Recompile and test:
- No code changes required
- Performance may be slower
Q: Can I use this library with LCD displays larger than 16x2?
A: Currently, the library is optimized for 16×2 displays. For 20×4 or other sizes, you'll need to modify the alcd_gotoxy() function and DDRAM address calculations.
Q: Why is my text scrolling automatically?
A: This happens when you write beyond column 15. The LCD has 40 bytes of DDRAM per line, but only 16 are visible. Use alcd_gotoxy() to position correctly.
Q: Can I connect the LCD directly to 3.3V microcontrollers?
A: Most HD44780 LCDs require 5V. For 3.3V systems, use a level shifter or find a 3.3V-compatible LCD module.
Q: How do I display numbers?
A: Use sprintf() or convert manually:
#include <stdio.h>
int value = 123;
char buffer[16];
sprintf(buffer, "Value: %d", value);
alcd_puts(buffer);Q: Why does my custom character look wrong?
A: Ensure you're using only the lower 5 bits of each byte. Bits 5-7 are ignored. Use online generators for accuracy.
Q: Can I read data from the LCD?
A: This library is write-only. Reading requires connecting the RW pin to a GPIO (currently tied to GND) and implementing read functions.
Q: How do I create animated characters?
A: Update CGRAM data periodically:
while(1)
{
alcd_customChar(0, frame1);
_delay_ms(200);
alcd_customChar(0, frame2);
_delay_ms(200);
}Q: What's the maximum update rate?
A: Approximately 1000 characters/second in 8-bit mode, 500 in 4-bit mode. Actual rate depends on MCU clock and delays.
Q: Why doesn't my backlight control work?
A: Ensure:
- Only available when the backlight pin is defined in your CubeMX configuration (e.g., __alcd_BL_GPIO_Port).
- Transistor is correctly connected
- Current-limiting resistor is appropriate
- Pin definition matches hardware
If you found this repository useful:
- Subscribe to my YouTube Channel.
- Share this repository with others.
- Give this repository and my other repositories a star.
- Follow my GitHub account.
Feel free to reach out to me through any of the following platforms:

