

Помогите найти ошибку в коде (stm32 подключение дисплея st7789 по spi)
Надеюсь, найдутся умельцы, которые шарят в вопросе))
пытаюсь подключить свой stm32h743vit6 к дисплею на базе мк st7789.
Распиновка дисплея следующая: CS(->PB4); DC(->PB5); RST(->PB6); SDA(->PA7); SCL(->PA5); VCC; GND.
Использую двуканальный режим spi, контакт MISO просто не подключаю, вроде как так можно делать.
Дисплей точно рабочий. Подключение проверил 10 раз.
Собственно, кусок кода:
void SPI_SendCommand(uint8_t cmd) {
HAL_GPIO_WritePin(GPIOB, TFT_CS_PIN, GPIO_PIN_RESET); // CS LOW
HAL_GPIO_WritePin(GPIOB, TFT_DC_PIN, GPIO_PIN_RESET); // Установите DC в 0 для команды
HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY); // Отправьте команду
HAL_GPIO_WritePin(GPIOB, TFT_CS_PIN, GPIO_PIN_SET); // CS HIGH
}
void SPI_SendData(uint8_t *data, uint16_t size) {
HAL_GPIO_WritePin(GPIOB, TFT_CS_PIN, GPIO_PIN_RESET); // CS LOW
HAL_GPIO_WritePin(GPIOB, TFT_DC_PIN, GPIO_PIN_SET); // Установите DC в 1 для данных
HAL_SPI_Transmit(&hspi1, data, size, HAL_MAX_DELAY); // Отправьте данные
HAL_GPIO_WritePin(GPIOB, TFT_CS_PIN, GPIO_PIN_RESET); // CS HIGH
}
void ST7789_Init() {
HAL_GPIO_WritePin(GPIOB, TFT_RST_PIN, GPIO_PIN_RESET); // Сброс дисплея
HAL_Delay(100);
HAL_GPIO_WritePin(GPIOB, TFT_RST_PIN, GPIO_PIN_SET);
HAL_Delay(100);
SPI_SendCommand(0x01); // SWRESET
HAL_Delay(150);
SPI_SendCommand(0x11); // SLPOUT
HAL_Delay(500);
SPI_SendCommand(0x3A); // COLMOD
uint8_t color_mode = 0x05; // 16 битный цвет (RGB 565)
SPI_SendData(&color_mode, 1);
SPI_SendCommand(0x36); // MADCTL
uint8_t madctl = 0x00; // Настройка направления (обычно 0x00)
SPI_SendData(&madctl, 1);
SPI_SendCommand(0x29); // DISPON
}
void ST7789_FillScreen(uint16_t color) {
SPI_SendCommand(0x2A); // CASET
uint8_t caset[] = {0x00, 0x00, 0x00, 0xEF}; // Установите область по X
SPI_SendData(caset, sizeof(caset));
SPI_SendCommand(0x2B); // RASET
uint8_t raset[] = {0x00, 0x00, 0x00, 0xEF}; // Установите область по Y
SPI_SendData(raset, sizeof(raset));
SPI_SendCommand(0x2C); // RAMWR
uint16_t data[240 * 240]; // Массив для заполнения экрана
for (int i = 0; i < 240 * 240; i++) {
data[i] = color; // Заполнение массива цветом
}
SPI_SendData((uint8_t*)data, sizeof(data)); // Отправка данных на дисплей
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MPU Configuration--------------------------------------------------------*/
MPU_Config();
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_SPI1_Init();
/* USER CODE BEGIN 2 */
ST7789_Init(); // инициализация дисплея
ST7789_FillScreen(0xFFFF); // Заполнение белым цветом (RGB565)
}
Ваш код в целом выглядит правильным, однако есть несколько потенциальных моментов, которые могут вызывать проблемы:
1. Неправильное состояние CS в функции SPI_SendData
В функции SPI_SendData вы устанавливаете TFT_CS_PIN в низкий уровень до передачи данных, но затем сразу же снова ставите его в высокий уровень после передачи данных, что не соответствует корректному циклу работы с SPI. После завершения передачи данных CS должен оставаться высоким до следующей команды.
Нужно изменить строку:
HAL_GPIO_WritePin(GPIOB, TFT_CS_PIN, GPIO_PIN_RESET); // CS HIGH
на:
HAL_GPIO_WritePin(GPIOB, TFT_CS_PIN, GPIO_PIN_SET); // CS HIGH
Обновлённая версия функции будет выглядеть так:
void SPI_SendData(uint8_t *data, uint16_t size) {
HAL_GPIO_WritePin(GPIOB, TFT_CS_PIN, GPIO_PIN_RESET); // CS LOW
HAL_GPIO_WritePin(GPIOB, TFT_DC_PIN, GPIO_PIN_SET); // DC в 1 для данных
HAL_SPI_Transmit(&hspi1, data, size, HAL_MAX_DELAY); // Отправка данных
HAL_GPIO_WritePin(GPIOB, TFT_CS_PIN, GPIO_PIN_SET); // CS HIGH
}
2. Массив данных для экрана
В функции ST7789_FillScreen у вас есть массив data[240 * 240], который используется для заполнения экрана цветом. Он создаёт массив целых чисел, а вы используете SPI_SendData, который ожидает данные в байтах.
Попробуйте передавать данные по одному байту за раз, а не по 16 бит. Внесите изменения, чтобы отправить данные в формате RGB565, которое ожидает дисплей.
Измените код в ST7789_FillScreen:
void ST7789_FillScreen(uint16_t color) {
SPI_SendCommand(0x2A); // CASET
uint8_t caset[] = {0x00, 0x00, 0x00, 0xEF}; // Установите область по X
SPI_SendData(caset, sizeof(caset));
SPI_SendCommand(0x2B); // RASET
uint8_t raset[] = {0x00, 0x00, 0x00, 0xEF}; // Установите область по Y
SPI_SendData(raset, sizeof(raset));
SPI_SendCommand(0x2C); // RAMWR
uint8_t data[240 * 240 * 2]; // Массив для заполнения экрана (каждый пиксель 2 байта)
for (int i = 0; i < 240 * 240; i++) {
data[2 * i] = color >> 8; // Старший байт
data[2 * i + 1] = color & 0xFF; // Младший байт
}
SPI_SendData(data, sizeof(data)); // Отправка данных на дисплей
}
В этом изменении для каждого пикселя отправляется 2 байта: старший и младший байт цвета в формате RGB565.
3. Настройки SPI
Убедитесь, что настройки SPI в вашем микроконтроллере соответствуют требуемым параметрам для работы с дисплеем ST7789. В частности, убедитесь, что:
Используется режим SPI (full-duplex).
Настройки скорости SPI, формата данных, режима полярности и фазы (CPOL, CPHA) соответствуют требованиям дисплея.
Например, для ST7789 используйте настройки, такие как:
CPOL = 0, CPHA = 0
Скорость SPI: несколько Мбит/с (зависит от частоты вашего микроконтроллера).
4. Сброс дисплея
В некоторых случаях, возможно, потребуется немного увеличить задержку после сброса дисплея. Попробуйте увеличить время задержки в этой строке:
HAL_Delay(100); // Возможно, стоит увеличить время
5. Проверка проводки
Если проблема не устраняется, убедитесь, что вы правильно подключили дисплей и что провода не повреждены. Проверка с осциллографом или логическим анализатором поможет вам увидеть, передаются ли данные через SPI.
Если вы внесете эти изменения, скорее всего, дисплей начнёт работать корректно.