Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 4878

General • HD44780 16x2 character LCD 5V with Pico

$
0
0
I have a HD44780 driven 5V 16x2 LCD that I thought at first I would need logic level shifters, but then I learned I could use a simple voltage divider, and perhaps not even that if the HD44780 is set read-only anyway. That is, CMOS 3.3 V high logic from Pico works fine to drive TTL 5 V high, but the other direction needs a voltage divider, or logic level shifter. I wired up a RGB backlit 16x2 LCD by using the Pico VBUS to power it. I assume it is fine to steal a little VBUS for the 5V connections? I put voltage dividers on each of the lines RS, EN, D4-D7. Like I said, probably not needed, but nice to know they are there just in case. I used 2.3k ohm resistors from LCD pins, and 3.3k ohm resistors to ground to make a ~3V divider on each GP pin.

Here is a setup I did in a hurry, so messy with resistor leads and such not trimmed:
Image

General wiring of this type of display hookup guide: https://learn.adafruit.com/character-lc ... racter-lcd
Mine is RGB, but I am ony using Red at the moment.

I saw this done with Micro Python, but here is a Pico SDK example main.c, reset/power cycle after flashing.

Code:

// HD44780 driver for 16x2 character display#include "pico/stdlib.h"// GPIO mapping#define LCD_RS  10   // Register Select#define LCD_EN  11   // Enable#define LCD_D4  18   // Data pin 4#define LCD_D5  19   // Data pin 5#define LCD_D6  20   // Data pin 6#define LCD_D7  21   // Data pin 7void lcd_gpio_init(void);void lcd_pulse_enable(void);void lcd_send_nibble(uint8_t nibble);void lcd_send_byte(uint8_t rs, uint8_t data);void lcd_init(void);void lcd_set_cursor(uint8_t row, uint8_t col);void lcd_print(const char *str);int main(void) {    lcd_init();    lcd_set_cursor(0, 0);  // Row 0, Col 0    lcd_print("Hello, World!");    while (1) {        tight_loop_contents();    }}void lcd_gpio_init(void) {    gpio_init(LCD_RS);    gpio_set_dir(LCD_RS, GPIO_OUT);    gpio_init(LCD_EN);    gpio_set_dir(LCD_EN, GPIO_OUT);    gpio_init(LCD_D4);    gpio_set_dir(LCD_D4, GPIO_OUT);    gpio_init(LCD_D5);    gpio_set_dir(LCD_D5, GPIO_OUT);    gpio_init(LCD_D6);    gpio_set_dir(LCD_D6, GPIO_OUT);    gpio_init(LCD_D7);    gpio_set_dir(LCD_D7, GPIO_OUT);}void lcd_pulse_enable(void) {    gpio_put(LCD_EN, 1);    sleep_us(1);  // Enable pulse width > 450ns    gpio_put(LCD_EN, 0);    sleep_us(50); // Commands need > 37µs to settle}void lcd_send_nibble(uint8_t nibble) {    gpio_put(LCD_D4, (nibble >> 0) & 1);    gpio_put(LCD_D5, (nibble >> 1) & 1);    gpio_put(LCD_D6, (nibble >> 2) & 1);    gpio_put(LCD_D7, (nibble >> 3) & 1);    lcd_pulse_enable();}void lcd_send_byte(uint8_t rs, uint8_t data) {    gpio_put(LCD_RS, rs);  // RS=0 for command, 1 for data    lcd_send_nibble(data >> 4); // Send higher nibble    lcd_send_nibble(data & 0xF); // Send lower nibble    sleep_us(50); // Wait for the command to execute}void lcd_init(void) {    lcd_gpio_init();    sleep_ms(15); // Wait for LCD to power up    // Initialization sequence    lcd_send_nibble(0x3); // Function set in 8-bit mode    sleep_ms(5);    lcd_send_nibble(0x3);    sleep_us(150);    lcd_send_nibble(0x3);    sleep_us(50);    lcd_send_nibble(0x2); // Switch to 4-bit mode    // Function set: 4-bit mode, 2 lines, 5x8 font    lcd_send_byte(0, 0x28);    // Display ON/OFF control: Display ON, Cursor OFF, Blink OFF    lcd_send_byte(0, 0x0C);    // Clear display    lcd_send_byte(0, 0x01);    sleep_ms(2);    // Entry mode set: Increment cursor, No shift    lcd_send_byte(0, 0x06);}void lcd_set_cursor(uint8_t row, uint8_t col) {    uint8_t address = (row == 0 ? 0x00 : 0x40) + col;    lcd_send_byte(0, 0x80 | address); // Set DDRAM address}void lcd_print(const char *str) {    while (*str) {        lcd_send_byte(1, *str++);    }}
CMakeLists.txt for reference

Code:

# Minimum required CMake versioncmake_minimum_required(VERSION 3.13)# Pull in SDK (must be before project)include(pico_sdk_import.cmake)project(lcd C CXX ASM)set(CMAKE_C_STANDARD 11)set(CMAKE_CXX_STANDARD 17)if (PICO_SDK_VERSION_STRING VERSION_LESS "1.3.0")    message(FATAL_ERROR "Raspberry Pi Pico SDK version 1.3.0 (or later) required. Your version is ${PICO_SDK_VERSION_STRING}")endif()# Initialize the SDKpico_sdk_init()add_compile_options(        -Wall                # Enable most warning messages        -Wno-format          # int != int32_t as far as the compiler is concerned because gcc has int32_t as long int        -Wno-unused-function # we have some for the docs that aren't called        )if (CMAKE_C_COMPILER_ID STREQUAL "GNU")   add_compile_options(-Wno-maybe-uninitialized)endif()# name target executableadd_executable(lcd main.c)# pull in common dependencies and additional i2c hardware supporttarget_link_libraries(lcd pico_stdlib)# enable usb output, disable uart outputpico_enable_stdio_usb(lcd 1)pico_enable_stdio_uart(lcd 0)# create map/bin/hex file etc.pico_add_extra_outputs(lcd)
So, yay, my old 5V 16x2 LCD with the HD44780 chip works with the Pico!

Statistics: Posted by breaker — Sun Jan 05, 2025 6:00 am



Viewing all articles
Browse latest Browse all 4878

Trending Articles