From 43e710eb8c0f771f29990144b313353f8437a66d Mon Sep 17 00:00:00 2001 From: Mikhail Date: Sun, 21 Jun 2026 21:45:38 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B2=D0=B0=D1=8F=20=D0=B8?= =?UTF-8?q?=D1=82=D0=B5=D1=80=D0=B0=D1=86=D0=B8=D1=8F.=20=D0=91=D0=B0?= =?UTF-8?q?=D0=B7=D0=BE=D0=B2=D0=B0=D1=8F=20=D0=B8=D0=BD=D0=B8=D1=86=D0=B8?= =?UTF-8?q?=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F,=20=D0=B8=20?= =?UTF-8?q?=D0=BE=D1=82=D1=80=D0=B8=D1=81=D0=BE=D0=B2=D0=BA=D0=B0=20=D0=BF?= =?UTF-8?q?=D1=80=D1=8F=D0=BC=D0=BE=D1=83=D0=B3=D0=BE=D0=BB=D1=8C=D0=BD?= =?UTF-8?q?=D0=B8=D0=BA=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Inc/DS_ST7789V.h | 83 +++++++++++++++++++++++++ Src/DS_ST7789V.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 239 insertions(+) create mode 100644 Inc/DS_ST7789V.h create mode 100644 Src/DS_ST7789V.c diff --git a/Inc/DS_ST7789V.h b/Inc/DS_ST7789V.h new file mode 100644 index 0000000..3eb746f --- /dev/null +++ b/Inc/DS_ST7789V.h @@ -0,0 +1,83 @@ +#ifndef DS_ST7789V_H +#define DS_ST7789V_H + +#include + +#ifdef STM32G030xx +#include "stm32g0xx_hal.h" +#endif + +#ifdef STM32G0B1xx +#include "stm32g0xx_hal.h" +#endif + +#ifdef STM32F030xx +#include "stm32f0xx_hal.h" +#endif + +/* Параметры дисплея */ +#define DS_ST7789V_WIDTH 240 +#define DS_ST7789V_HEIGHT 320 + +/* Основные команды контроллера ST7789V */ +#define ST7789V_CMD_NOP 0x00 +#define ST7789V_CMD_SWRESET 0x01 +#define ST7789V_CMD_SLPOUT 0x11 +#define ST7789V_CMD_INVOFF 0x20 +#define ST7789V_CMD_INVON 0x21 +#define ST7789V_CMD_DISPOFF 0x28 +#define ST7789V_CMD_DISPON 0x29 +#define ST7789V_CMD_CASET 0x2A +#define ST7789V_CMD_RASET 0x2B +#define ST7789V_CMD_RAMWR 0x2C +#define ST7789V_CMD_MADCTL 0x36 +#define ST7789V_CMD_COLMOD 0x3A + +/* Варианты ориентации экрана */ +typedef enum { + DS_ST7789V_ORIENTATION_PORTRAIT = 0, + DS_ST7789V_ORIENTATION_LANDSCAPE, + DS_ST7789V_ORIENTATION_PORTRAIT_REV, + DS_ST7789V_ORIENTATION_LANDSCAPE_REV +} DS_ST7789V_Orientation_t; + +/* Структура конфигурации пинов (аналогично DS_Button) */ +typedef struct { + GPIO_TypeDef *Port; + uint16_t Pin; +} DS_ST7789V_Pin_t; + +/* Главная управляющая структура дисплея */ +typedef struct DS_ST7789V { + SPI_HandleTypeDef *hspi; // Указатель на аппаратный SPI + DS_ST7789V_Pin_t CS; // Пин выбора чипа + DS_ST7789V_Pin_t DC; // Пин выбор Команда/Данные + DS_ST7789V_Pin_t RES; // Пин аппаратного сброса + uint16_t Width; // Текущая ширина с учетом поворота + uint16_t Height; // Текущая высота с учетом поворота + DS_ST7789V_Orientation_t Orientation; // Текущая ориентация +} DS_ST7789V; + +/**@brief Инициализация дескриптора дисплея и передача начальных команд +@param lcd Указатель на структуру дисплея +@param hspi Указатель на сгенерированный CubeMX интерфейс SPI*/ +void DS_ST7789V_Init(DS_ST7789V *lcd, SPI_HandleTypeDef *hspi, + GPIO_TypeDef *cs_port, uint16_t cs_pin, + GPIO_TypeDef *dc_port, uint16_t dc_pin, + GPIO_TypeDef *res_port, uint16_t res_pin); + +/**@brief Установка ориентации экрана*/ +void DS_ST7789V_SetOrientation(DS_ST7789V *lcd, + DS_ST7789V_Orientation_t orientation); + +/**@brief Заливка экрана или выделенной области цветом (RGB565)*/ +void DS_ST7789V_FillRect(DS_ST7789V *lcd, uint16_t x, uint16_t y, uint16_t w, + uint16_t h, uint16_t color); + +/**@brief Низкоуровневые функции отправки (могут использоваться для кастомных + * оптимизаций)*/ +void DS_ST7789V_WriteCommand(DS_ST7789V *lcd, uint8_t cmd); + +void DS_ST7789V_WriteData(DS_ST7789V *lcd, uint8_t *data, uint16_t size); + +#endif // DS_ST7789V_H \ No newline at end of file diff --git a/Src/DS_ST7789V.c b/Src/DS_ST7789V.c new file mode 100644 index 0000000..295efb2 --- /dev/null +++ b/Src/DS_ST7789V.c @@ -0,0 +1,156 @@ +#include "../inc/DS_ST7789V.h" + +/* Вспомогательные статические макросы для локального управления линиями GPIO */ +#define CS_ACTIVE(lcd) \ + HAL_GPIO_WritePin(lcd->CS.Port, lcd->CS.Pin, GPIO_PIN_RESET) +#define CS_IDLE(lcd) HAL_GPIO_WritePin(lcd->CS.Port, lcd->CS.Pin, GPIO_PIN_SET) +#define DC_COMMAND(lcd) \ + HAL_GPIO_WritePin(lcd->DC.Port, lcd->DC.Pin, GPIO_PIN_RESET) +#define DC_DATA(lcd) HAL_GPIO_WritePin(lcd->DC.Port, lcd->DC.Pin, GPIO_PIN_SET) +#define RES_ACTIVE(lcd) \ + HAL_GPIO_WritePin(lcd->RES.Port, lcd->RES.Pin, GPIO_PIN_RESET) +#define RES_IDLE(lcd) \ + HAL_GPIO_WritePin(lcd->RES.Port, lcd->RES.Pin, GPIO_PIN_SET) + +void DS_ST7789V_WriteCommand(DS_ST7789V *lcd, uint8_t cmd) { + DC_COMMAND(lcd); + CS_ACTIVE(lcd); + HAL_SPI_Transmit(lcd->hspi, &cmd, 1, HAL_MAX_DELAY); + CS_IDLE(lcd); +} + +void DS_ST7789V_WriteData(DS_ST7789V *lcd, uint8_t *data, uint16_t size) { + DC_DATA(lcd); + CS_ACTIVE(lcd); + HAL_SPI_Transmit(lcd->hspi, data, size, HAL_MAX_DELAY); + CS_IDLE(lcd); +} + +static void DS_ST7789V_SetAddressWindow(DS_ST7789V *lcd, uint16_t x0, + uint16_t y0, uint16_t x1, uint16_t y1) { + uint8_t data[4]; + + /* Настройка столбцов (X) */ + DS_ST7789V_WriteCommand(lcd, ST7789V_CMD_CASET); + data[0] = (x0 >> 8) & 0xFF; + data[1] = x0 & 0xFF; + data[2] = (x1 >> 8) & 0xFF; + data[3] = x1 & 0xFF; + DS_ST7789V_WriteData(lcd, data, 4); + + /* Настройка строк (Y) */ + DS_ST7789V_WriteCommand(lcd, ST7789V_CMD_RASET); + data[0] = (y0 >> 8) & 0xFF; + data[1] = y0 & 0xFF; + data[2] = (y1 >> 8) & 0xFF; + data[3] = y1 & 0xFF; + DS_ST7789V_WriteData(lcd, data, 4); + + /* Готовность к записи в RAM */ + DS_ST7789V_WriteCommand(lcd, ST7789V_CMD_RAMWR); +} + +void DS_ST7789V_Init(DS_ST7789V *lcd, SPI_HandleTypeDef *hspi, + GPIO_TypeDef *cs_port, uint16_t cs_pin, + GPIO_TypeDef *dc_port, uint16_t dc_pin, + GPIO_TypeDef *res_port, uint16_t res_pin) + { + lcd->hspi = hspi; + + /* Автоматическая привязка портов на основе сгенерированных CubeMX меток (User + * Labels) */ + lcd->CS.Port = cs_port; + lcd->CS.Pin = cs_pin; + lcd->DC.Port = dc_port; + lcd->DC.Pin = dc_pin; + lcd->RES.Port = res_port; + lcd->RES.Pin = res_pin; + lcd->Width = DS_ST7789V_WIDTH; + lcd->Height = DS_ST7789V_HEIGHT; + + /* Аппаратный сброс матрицы */ + RES_ACTIVE(lcd); + HAL_Delay(25); + RES_IDLE(lcd); + HAL_Delay(120); + + /* Программный сброс контроллера */ + DS_ST7789V_WriteCommand(lcd, ST7789V_CMD_SWRESET); + HAL_Delay(150); + + /* Выход из спящего режима */ + DS_ST7789V_WriteCommand(lcd, ST7789V_CMD_SLPOUT); + HAL_Delay(120); + + /* Установка цветового режима: 16-бит/пиксель (RGB565) */ + DS_ST7789V_WriteCommand(lcd, ST7789V_CMD_COLMOD); + uint8_t color_mode = 0x55; + DS_ST7789V_WriteData(lcd, &color_mode, 1); + + /* Установка дефолтной ориентации */ + DS_ST7789V_SetOrientation(lcd, DS_ST7789V_ORIENTATION_PORTRAIT); + + /* Инверсия цвета дисплея (требуется для большинства IPS матриц этой серии) */ + DS_ST7789V_WriteCommand(lcd, ST7789V_CMD_INVON); + + /* Включение дисплея */ + DS_ST7789V_WriteCommand(lcd, ST7789V_CMD_DISPON); + HAL_Delay(50); + + /* Первоначальная очистка экрана черным цветом */ + DS_ST7789V_FillRect(lcd, 0, 0, lcd->Width, lcd->Height, 0x0000); +} + +void DS_ST7789V_SetOrientation(DS_ST7789V *lcd, + DS_ST7789V_Orientation_t orientation) { + lcd->Orientation = orientation; + uint8_t madctl_val = 0; + switch (orientation) { + case DS_ST7789V_ORIENTATION_PORTRAIT: + madctl_val = 0x00; // Развертка сверху-вниз, слева-направо + lcd->Width = DS_ST7789V_WIDTH; + lcd->Height = DS_ST7789V_HEIGHT; + break; + case DS_ST7789V_ORIENTATION_LANDSCAPE: + madctl_val = 0x60; // Обмен строк и столбцов (поворот на 90°) + lcd->Width = DS_ST7789V_HEIGHT; + lcd->Height = DS_ST7789V_WIDTH; + break; + case DS_ST7789V_ORIENTATION_PORTRAIT_REV: + madctl_val = 0xC0; // Отражение по осям X и Y + lcd->Width = DS_ST7789V_WIDTH; + lcd->Height = DS_ST7789V_HEIGHT; + break; + case DS_ST7789V_ORIENTATION_LANDSCAPE_REV: + madctl_val = 0xA0; // Альтернативный альбомный режим + lcd->Width = DS_ST7789V_HEIGHT; + lcd->Height = DS_ST7789V_WIDTH; + break; + } + DS_ST7789V_WriteCommand(lcd, ST7789V_CMD_MADCTL); + DS_ST7789V_WriteData(lcd, &madctl_val, 1); +} + +void DS_ST7789V_FillRect(DS_ST7789V *lcd, uint16_t x, uint16_t y, uint16_t w, + uint16_t h, uint16_t color) { + if ((x >= lcd->Width) || (y >= lcd->Height)) + return; + if ((x + w) > lcd->Width) + w = lcd->Width - x; + if ((y + h) > lcd->Height) + h = lcd->Height - y; + DS_ST7789V_SetAddressWindow(lcd, x, y, x + w - 1, y + h - 1); + + uint8_t color_bytes[2]; + color_bytes[0] = (color >> 8) & 0xFF; // Старший байт цвета (MSB) + color_bytes[1] = color & 0xFF; // Младший байт цвета (LSB) + uint32_t total_pixels = w * h; + DC_DATA(lcd); + CS_ACTIVE(lcd); + + /* Передача массива пикселей через HAL блоками для экономии ОЗУ */ + for (uint32_t i = 0; i < total_pixels; i++) { + HAL_SPI_Transmit(lcd->hspi, color_bytes, 2, HAL_MAX_DELAY); + } + CS_IDLE(lcd); +} \ No newline at end of file