Загрузка данных
#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>
#include <string.h>
#define MSG_SIZE 16
#define QUEUE_MAX_MSGS 10
#define LCD_THREAD_STACK 1024
#define LCD_THREAD_PRIORITY 13
#ifdef MY_CODE
/* Извлекаем спецификации пинов напрямую из DeviceTree */
static const struct gpio_dt_spec lcd_rs = GPIO_DT_SPEC_GET(DT_NODELABEL(lcd), rs_gpios);
static const struct gpio_dt_spec lcd_rw = GPIO_DT_SPEC_GET(DT_NODELABEL(lcd), rw_gpios);
static const struct gpio_dt_spec lcd_e = GPIO_DT_SPEC_GET(DT_NODELABEL(lcd), e_gpios);
static const struct gpio_dt_spec lcd_bl = GPIO_DT_SPEC_GET(DT_NODELABEL(lcd), bl_gpios);
/* Массив для удобного побитового выставления шины данных D4-D7 */
static const struct gpio_dt_spec lcd_data[4] = {
GPIO_DT_SPEC_GET(DT_NODELABEL(lcd), d4_gpios),
GPIO_DT_SPEC_GET(DT_NODELABEL(lcd), d5_gpios),
GPIO_DT_SPEC_GET(DT_NODELABEL(lcd), d6_gpios),
GPIO_DT_SPEC_GET(DT_NODELABEL(lcd), d7_gpios)
};
#endif
// Флаги управления для совместимости
#define LCD_RS_PIN 1
#define LCD_CMD_PIN 0
/* Глобальная переменная подсветки */
static uint8_t backlight_state = 1;
struct lcd_msg_t {
char text[MSG_SIZE];
uint8_t row;
uint8_t col;
uint8_t mode;
uint8_t text_size;
};
K_MSGQ_DEFINE(lcd_msgq, sizeof(struct lcd_msg_t), QUEUE_MAX_MSGS, 4);
/* Отправка 4 бит данных на физические пины */
void lcd_send_nibble(uint8_t nibble, uint8_t rs_flag)
{
#ifdef MY_CODE
// 1. Выставляем сигналы управления RS и RW (RW всегда в 0 - запись)
gpio_pin_set_dt(&lcd_rs, rs_flag);
gpio_pin_set_dt(&lcd_rw, 0);
gpio_pin_set_dt(&lcd_bl, backlight_state);
// 2. Раскладываем тетраду (4 бита) по независимым линиям данных
for (int i = 0; i < 4; i++) {
gpio_pin_set_dt(&lcd_data[i], (nibble >> i) & 0x01);
}
k_busy_wait(1); // Время на установку данных (Address setup time)
// 3. Формируем строб-импульс Enable (E = 1 -> E = 0)
gpio_pin_set_dt(&lcd_e, 1);
k_busy_wait(1); // Минимальная ширина импульса E (высокий уровень)
gpio_pin_set_dt(&lcd_e, 0);
k_busy_wait(5); // Время удержания данных после спада E
#endif
}
/* Отправка полного байта (Старший полубайт, затем младший) */
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, LCD_CMD_PIN); }
void lcd_data(uint8_t data) { lcd_send_byte(data, LCD_RS_PIN); }
/* Инициализация дисплея в режиме 4 бит по новой схеме */
int lcd_init(void)
{
#ifdef MY_CODE
// Проверяем готовность всех GPIO контроллеров
if (!gpio_is_ready_dt(&lcd_rs) || !gpio_is_ready_dt(&lcd_rw) ||
!gpio_is_ready_dt(&lcd_e) || !gpio_is_ready_dt(&lcd_bl)) {
printf("Error: Control GPIO devices are not ready\n");
return -ENODEV;
}
// Конфигурируем управляющие пины на выход
gpio_pin_configure_dt(&lcd_rs, GPIO_OUTPUT_INACTIVE);
gpio_pin_configure_dt(&lcd_rw, GPIO_OUTPUT_INACTIVE);
gpio_pin_configure_dt(&lcd_e, GPIO_OUTPUT_INACTIVE);
gpio_pin_configure_dt(&lcd_bl, GPIO_OUTPUT_ACTIVE); // Включаем бэклайт на старте
// Конфигурируем пины данных на выход
for (int i = 0; i < 4; i++) {
if (!gpio_is_ready_dt(&lcd_data[i])) {
printf("Error: Data GPIO pin D%d is not ready\n", i+4);
return -ENODEV;
}
gpio_pin_configure_dt(&lcd_data[i], GPIO_OUTPUT_INACTIVE);
}
// Стандартный тайм-аут HD44780 после подачи питания
k_msleep(50);
// Процедура инициализации 4-битного режима (согласно даташиту HD44780)
lcd_send_nibble(0x03, LCD_CMD_PIN);
k_msleep(5);
lcd_send_nibble(0x03, LCD_CMD_PIN);
k_busy_wait(150);
lcd_send_nibble(0x03, LCD_CMD_PIN);
k_busy_wait(150);
lcd_send_nibble(0x02, LCD_CMD_PIN); // Переключение на 4 бита
k_msleep(2);
// Настройка параметров дисплея
lcd_command(0x28); // Режим 4 бит, 2 строки, шрифт 5x8
lcd_command(0x0C); // Дисплей включен, курсор выключен
lcd_command(0x06); // Автоинкремент курсора (сдвиг вправо)
lcd_command(0x01); // Очистить дисплей
k_msleep(2);
#endif
return 1;
}
/* Остальные функции (lcd_set_cursor, lcd_print, lcd_render_thread, safe_lcd_print)
остаются без изменений, так как они используют абстрактные lcd_command() и lcd_data() */