Files
DS_ST7789V/Src/DS_ST7789V.c
Mikhail 43e710eb8c Первая итерация.
Базовая инициализация, и отрисовка прямоугольников
2026-06-21 21:45:38 +03:00

156 lines
5.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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);
}