Skip to main content

Task 10.1: 4-bit Mode LCD Interfacing

Optimize LCD interfacing by using 4-bit mode instead of 8-bit mode. This uses only 4 data lines instead of 8, saving GPIO pins.

Learning Objectives

By the end of this task, you will:

  • 🎯 Understand 4-bit vs 8-bit LCD modes
  • 🎯 Reduce GPIO usage significantly (8 pins → 4 pins)
  • 🎯 Implement nibble-based data transmission
  • 🎯 Master LCD initialization sequence for 4-bit mode
  • 🎯 Build resource-efficient display driver

Prerequisites

  • ✅ Complete Lab 10 (8-bit LCD basics)
  • ✅ Understand LCD command protocol
  • ✅ Familiar with GPIO output control

Hardware Required

ComponentDetails
MicrocontrollerSTM32F407VG
Display16x2 LCD (HD44780 compatible)
PinsD4-D7 (4 data lines), RS, EN, RW (optional)
Power5V for LCD

Theory: 4-bit Mode

4-bit vs 8-bit

8-bit mode:
├─ Uses 8 data lines (D0-D7)
├─ High GPIO pin usage
└─ Faster data transmission

4-bit mode:
├─ Uses 4 data lines (D4-D7)
├─ Lower GPIO requirement (same board versatility)
├─ Data sent in two 4-bit "nibbles"
└─ Slower but plenty fast for LCD

Nibble Transmission

To send byte 0xAB (10101011):

4-bit mode:
Step 1: Send high nibble (1010) on D4-D7
└─ RS=0 (command), EN pulse

Step 2: Send low nibble (1011) on D4-D7
└─ RS=0 (command), EN pulse

8-bit mode (for comparison):
Step 1: Send entire 0xAB at once on D0-D7
└─ Much faster but uses more pins

Initialization Sequence

The 4-bit initialization is special:

LCD powers up in 8-bit mode by default
To switch to 4-bit mode:
1. Send 0x30 three times (8-bit command)
2. Send 0x20 (switches to 4-bit mode)
3. Send 0x28 (function set: 4-bit, 2 lines, 5x8 font)
4. Send 0x0C (display ON, cursor OFF)
5. Send 0x01 (clear display)
6. Send 0x06 (entry mode: increment, no shift)

Complete Code

#define RCC_AHB1ENR *(volatile unsigned int*)(0x40023800 + 0x30)
#define GPIOD_MODER *(volatile unsigned int*)(0x40020C00 + 0x00)
#define GPIOD_ODR *(volatile unsigned int*)(0x40020C00 + 0x14)

// Pin definitions
#define RS (1<<0) // PD0
#define EN (1<<1) // PD1
// D4-D7 on PD4-PD7

void delay_ms(int ms) {
for (volatile int i = 0; i < ms * 10000; i++);
}

void lcd_pulse_enable(void) {
GPIOD_ODR |= EN;
delay_ms(1);
GPIOD_ODR &= ~EN;
delay_ms(1);
}

void send_nibble(unsigned char nibble) {
// Clear D4-D7
GPIOD_ODR &= ~(0xF << 4);
// Set high nibble bits
GPIOD_ODR |= ((nibble & 0xF) << 4);
lcd_pulse_enable();
}

void send_byte_4bit(unsigned char byte, int is_data) {
if (is_data)
GPIOD_ODR |= RS; // RS=1 for data
else
GPIOD_ODR &= ~RS; // RS=0 for command

delay_ms(1);

// Send high nibble
send_nibble((byte >> 4) & 0xF);
delay_ms(1);

// Send low nibble
send_nibble(byte & 0xF);
delay_ms(1);
}

void lcd_init_4bit(void) {
RCC_AHB1ENR |= (1 << 3); // Enable GPIOD

// Configure PD0-PD7 as outputs
GPIOD_MODER &= ~(0xFF << 0);
GPIOD_MODER |= (0x55 << 0);

delay_ms(20);

// Initialization sequence for 4-bit mode
// Must send three 0x3 commands (each time high nibble)
send_nibble(0x3);
delay_ms(5);
send_nibble(0x3);
delay_ms(5);
send_nibble(0x3);
delay_ms(1);
send_nibble(0x2); // Switch to 4-bit mode
delay_ms(1);

// Now use normal send_byte functions
send_byte_4bit(0x28, 0); // Function set: 4-bit, 2 lines, 5x8 dot
send_byte_4bit(0x0C, 0); // Display ON, cursor OFF
send_byte_4bit(0x01, 0); // Clear display
send_byte_4bit(0x06, 0); // Entry mode: increment cursor
}

void lcd_write_char(char c) {
send_byte_4bit(c, 1); // is_data = 1 (character)
}

void lcd_write_string(char *str) {
while (*str) {
lcd_write_char(*str++);
}
}

int main(void) {
lcd_init_4bit();

lcd_write_string("Hello 4-bit!");

while (1) {
// Application code
}

return 0;
}

Expected Output

LCD Display:
┌─────────────────┐
│ Hello 4-bit! │
│ │
└─────────────────┘

GPIO Savings

8-bit mode:
D0-D7: 8 pins
RS: 1 pin
EN: 1 pin
────────────────
Total: 10+ pins

4-bit mode:
D4-D7: 4 pins
RS: 1 pin
EN: 1 pin
────────────────
Total: 6 pins (40% savings)

Common Mistakes

IssueSolution
LCD doesn't initializeVerify three 0x3 commands sent
Display garbledCheck nibble order - high then low
No text displayedVerify character versus command mode (RS)
Slow communicationMay be intentional - 4-bit is inherently slower

Key Takeaways

Important:

  1. 4-bit mode uses half the GPIO pins
  2. Nibble transmission sends data twice (high, then low)
  3. Initialization sequence is special and must be exact
  4. RS pin distinguishes commands from data
  5. Performance is still adequate for LCD speeds

Challenge Exercises

Challenge 1: Multi-line Display

Display different text on line 1 and line 2 using cursor addressing.

Challenge 2: Display Sensor Data

Show temperature or ADC readings updated on display.

Challenge 3: Custom Characters

Create and display custom character patterns on LCD.

Next Steps

✨ Congratulations on completing the STM32 embedded systems course! You've mastered GPIO, timers, interrupts, and interfacing!