Загрузка данных


#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>

/* Получаем устройство PCF8574 напрямую по метке из devicetree */
static const struct device *pcf_dev = DEVICE_DT_GET(DT_NODELABEL(pcf8574));

/* Маски для управления ножками согласно вашей распиновке */
#define LCD_RS        (1 << 0) // Port 0
#define LCD_RW        (1 << 1) // Port 1
#define LCD_E         (1 << 2) // Port 2
#define LCD_BL        (1 << 3) // Port 3 (Backlight)
#define LCD_DATA_MASK 0xF0     // Port 4-7 (D4-D7)

/* Глобальная переменная состояния подсветки */
static uint8_t backlight_state = LCD_BL;

/* Функция передачи 4 бит (полубайта) */
void lcd_send_nibble(uint8_t nibble, uint8_t rs_flag)
{
    // Формируем байт: старшие 4 бита - данные, младшие - управление и подсветка
    uint8_t port_val = (nibble << 4) | rs_flag | backlight_state;
    
    // RW всегда держим в 0 (режим записи)
    port_val &= ~LCD_RW; 

    // 1. Выставляем данные и RS, линию E держим в 0
    gpio_port_set_masked_raw(pcf_dev, 0xFF, port_val);
    k_busy_wait(1);

    // 2. Импульс Enable (E = 1) для фиксации данных дисплеем
    gpio_port_set_masked_raw(pcf_dev, 0xFF, port_val | LCD_E);
    k_busy_wait(1); // Длина импульса строба > 450 нс

    // 3. Сброс Enable (E = 0)
    gpio_port_set_masked_raw(pcf_dev, 0xFF, port_val);
    k_busy_wait(50); // Пауза для обработки команды дисплеем
}

/* Функция передачи полноценного байта (по 4 бита) */
void lcd_send_byte(uint8_t value, uint8_t rs_flag)
{
    lcd_send_nibble(value >> 4, rs_flag);   // Старший полубайт
    lcd_send_nibble(value & 0x0F, rs_flag); // Младший полубайт
}

void lcd_command(uint8_t cmd)  { lcd_send_byte(cmd, 0); }
void lcd_data(uint8_t data)   { lcd_send_byte(data, LCD_RS); }

/* Функция инициализации дисплея 1602A в 4-битном режиме */
void lcd_init(void)
{
    k_msleep(50); // Ждем стабилизации питания дисплея после включения
    
    // Перевод контроллера HD44780 в 4-битный режим (особая процедура)
    lcd_send_nibble(0x03, 0);
    k_msleep(5);
    lcd_send_nibble(0x03, 0);
    k_busy_wait(150);
    lcd_send_nibble(0x03, 0);
    k_busy_wait(150);
    lcd_send_nibble(0x02, 0); // Окончательный переход на 4 бита
    k_msleep(2);

    // Настройка параметров дисплея
    lcd_command(0x28); // 4-битный режим, 2 строки, шрифт 5x8
    lcd_command(0x0C); // Включить дисплей, курсор выключен, мигание выключено
    lcd_command(0x06); // Автоинкремент курсора при печати
    lcd_command(0x01); // Очистка дисплея
    k_msleep(2);       // Длинная пауза после очистки
}

/* Функция позиционирования курсора */
void lcd_set_cursor(uint8_t col, uint8_t row)
{
    uint8_t row_offsets[] = {0x00, 0x40};
    lcd_command(0x80 | (col + row_offsets[row]));
}

/* Функция печати строки */
void lcd_print(const char *str)
{
    while (*str) {
        lcd_data(*str++);
    }
}