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


#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() */