ioc changed soft spi tft

This commit is contained in:
TuxMonkey
2026-07-20 16:29:06 +08:00
parent cda936d7e0
commit f92585831a
11 changed files with 271 additions and 152 deletions

View File

@@ -1,7 +1,6 @@
#include "tft.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#define TFT_SPI_TIMEOUT_MS 100U
@@ -28,6 +27,7 @@ typedef enum
} TFT_GlyphIndex_e;
static bool tft_initialized = false;
static bool tft_transfer_ok = true;
static const uint8_t tft_font5x7[][TFT_FONT_H] = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* space */
@@ -107,15 +107,72 @@ static void tft_backlight_on(void)
HAL_GPIO_WritePin(TFT_BLK_GPIO_Port, TFT_BLK_Pin, GPIO_PIN_SET);
}
static void tft_bus_init(void)
{
#if TFT_USE_SOFT_SPI
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
GPIO_InitStruct.Pin = TFT_SCK_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(TFT_SCK_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = TFT_MOSI_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(TFT_MOSI_GPIO_Port, &GPIO_InitStruct);
HAL_GPIO_WritePin(TFT_SCK_GPIO_Port, TFT_SCK_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(TFT_MOSI_GPIO_Port, TFT_MOSI_Pin, GPIO_PIN_RESET);
#endif
}
#if TFT_USE_SOFT_SPI
static void tft_write_byte(uint8_t data)
{
for (uint8_t i = 0U; i < 8U; i++)
{
HAL_GPIO_WritePin(TFT_SCK_GPIO_Port, TFT_SCK_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(TFT_MOSI_GPIO_Port, TFT_MOSI_Pin,
(data & 0x80U) != 0U ? GPIO_PIN_SET : GPIO_PIN_RESET);
HAL_GPIO_WritePin(TFT_SCK_GPIO_Port, TFT_SCK_Pin, GPIO_PIN_SET);
data <<= 1U;
}
}
#endif
static void tft_write_bytes(const uint8_t *data, uint32_t len)
{
#if TFT_USE_SOFT_SPI
while (len > 0U)
{
tft_write_byte(*data);
data++;
len--;
}
#else
while (len > 0U)
{
#if TFT_HW_SPI_BYTE_MODE
uint16_t chunk = 1U;
#else
uint16_t chunk = len > UINT16_MAX ? UINT16_MAX : (uint16_t) len;
(void) HAL_SPI_Transmit(&TFT_SPI_UNIT, (uint8_t *) data, chunk, TFT_SPI_TIMEOUT_MS);
#endif
if (HAL_SPI_Transmit(&TFT_SPI_UNIT, (uint8_t *) data, chunk, TFT_SPI_TIMEOUT_MS) != HAL_OK)
{
tft_transfer_ok = false;
tft_cs_high();
return;
}
data += chunk;
len -= chunk;
}
#endif
}
static void lcd_write_reg(uint8_t reg)
@@ -124,6 +181,7 @@ static void lcd_write_reg(uint8_t reg)
tft_dc_command();
tft_write_bytes(&reg, 1U);
tft_cs_high();
tft_dc_data();
}
static void lcd_write_data8(uint8_t data)
@@ -157,7 +215,7 @@ static void tft_write_color_block(uint16_t color, uint32_t count)
tft_cs_low();
tft_dc_data();
while (count > 0U)
while (count > 0U && tft_transfer_ok)
{
uint32_t pixels = count > (sizeof(buf) / 2U) ? (sizeof(buf) / 2U) : count;
tft_write_bytes(buf, pixels * 2U);
@@ -281,7 +339,7 @@ static void tft_draw_char(uint16_t x, uint16_t y, char ch, uint16_t fc, uint16_t
uint32_t idx = 0U;
for (uint8_t col = 0U; col < TFT_FONT_W; col++)
{
uint16_t color = (glyph[row] & (1U << (TFT_FONT_W - 1U - col))) ? fc : bc;
uint16_t color = (glyph[row] & (1U << col)) ? fc : bc;
for (uint8_t repeat_x = 0U; repeat_x < scale; repeat_x++)
{
line[idx++] = (uint8_t) (color >> 8);
@@ -339,6 +397,8 @@ void LCD_Init(void)
return;
}
tft_transfer_ok = true;
tft_bus_init();
tft_cs_high();
tft_reset_low();
HAL_Delay(100);
@@ -429,8 +489,11 @@ void LCD_Init(void)
lcd_write_reg(0x21);
lcd_write_reg(0x29);
tft_initialized = true;
TFT_Clear(TFT_COLOR_BLACK);
if (tft_transfer_ok)
{
tft_initialized = true;
}
}
void TFT_Init(void)
@@ -438,6 +501,27 @@ void TFT_Init(void)
LCD_Init();
}
void TFT_ShowBootScreen(void)
{
if (!tft_initialized)
{
TFT_Init();
if (!tft_initialized)
{
return;
}
}
tft_transfer_ok = true;
uint16_t band_h = TFT_LCD_H / 3U;
TFT_FillRect(0U, 0U, TFT_LCD_W, band_h, TFT_COLOR_BLUE);
TFT_FillRect(0U, band_h, TFT_LCD_W, band_h, TFT_COLOR_GREEN);
TFT_FillRect(0U, (uint16_t) (band_h * 2U), TFT_LCD_W, (uint16_t) (TFT_LCD_H - band_h * 2U), TFT_COLOR_RED);
TFT_DrawString(16U, 22U, "DM LCD", TFT_COLOR_WHITE, TFT_COLOR_BLUE, 3U);
TFT_DrawString(16U, (uint16_t) (band_h + 24U), "BOOT", TFT_COLOR_BLACK, TFT_COLOR_GREEN, 3U);
TFT_DrawString(16U, (uint16_t) (band_h * 2U + 24U), "WAIT IMU", TFT_COLOR_WHITE, TFT_COLOR_RED, 2U);
}
const char *TFT_RobotModeText(RobotMode_t mode)
{
switch (mode)
@@ -487,8 +571,13 @@ static int16_t tft_temperature_to_tenths(float temperature_c)
static void tft_format_temperature(char *buf, size_t len, int16_t temperature_tenths)
{
uint16_t abs_temp;
uint16_t integer;
uint8_t decimal;
size_t idx = 0U;
char digits[5];
uint8_t digits_len = 0U;
if (buf == NULL || len == 0U)
if (buf == NULL || len < 6U)
{
return;
}
@@ -496,13 +585,33 @@ static void tft_format_temperature(char *buf, size_t len, int16_t temperature_te
if (temperature_tenths < 0)
{
abs_temp = (uint16_t) (-temperature_tenths);
(void) snprintf(buf, len, "-%u.%u C", abs_temp / 10U, abs_temp % 10U);
buf[idx++] = '-';
}
else
{
abs_temp = (uint16_t) temperature_tenths;
(void) snprintf(buf, len, "%u.%u C", abs_temp / 10U, abs_temp % 10U);
}
integer = abs_temp / 10U;
decimal = (uint8_t) (abs_temp % 10U);
do
{
digits[digits_len++] = (char) ('0' + (integer % 10U));
integer /= 10U;
} while (integer > 0U && digits_len < sizeof(digits));
while (digits_len > 0U && idx + 1U < len)
{
buf[idx++] = digits[--digits_len];
}
if (idx + 4U < len)
{
buf[idx++] = '.';
buf[idx++] = (char) ('0' + decimal);
buf[idx++] = ' ';
buf[idx++] = 'C';
}
buf[idx] = '\0';
}
static void tft_draw_status_layout(void)
@@ -526,27 +635,44 @@ void TFT_ShowStatus(float temperature_c, RobotMode_t mode)
if (!tft_initialized)
{
TFT_Init();
if (!tft_initialized)
{
return;
}
}
if (!layout_ready)
{
tft_transfer_ok = true;
tft_draw_status_layout();
if (!tft_transfer_ok)
{
return;
}
layout_ready = true;
}
if (temperature_tenths != last_temperature_tenths)
{
tft_transfer_ok = true;
uint16_t temperature_color = temperature_tenths >= 550 ? TFT_COLOR_RED : TFT_COLOR_WHITE;
tft_format_temperature(temperature_text, sizeof(temperature_text), temperature_tenths);
TFT_FillRect(96U, 68U, 168U, 32U, TFT_COLOR_BLACK);
TFT_DrawString(100U, 70U, temperature_text, temperature_color, TFT_COLOR_BLACK, 3U);
last_temperature_tenths = temperature_tenths;
if (tft_transfer_ok)
{
last_temperature_tenths = temperature_tenths;
}
}
if (mode != last_mode)
{
tft_transfer_ok = true;
TFT_FillRect(96U, 124U, 184U, 32U, TFT_COLOR_BLACK);
TFT_DrawString(100U, 126U, mode_text, tft_mode_color(mode), TFT_COLOR_BLACK, 3U);
last_mode = mode;
if (tft_transfer_ok)
{
last_mode = mode;
}
}
}

View File

@@ -10,7 +10,9 @@
extern "C" {
#endif
#define TFT_USE_HORIZONTAL 2U
#define TFT_USE_HORIZONTAL 2U
#define TFT_USE_SOFT_SPI 1U
#define TFT_HW_SPI_BYTE_MODE 1U
#if (TFT_USE_HORIZONTAL == 0U) || (TFT_USE_HORIZONTAL == 1U)
#define TFT_LCD_W 240U
@@ -24,6 +26,16 @@ extern "C" {
#define TFT_SPI_UNIT hspi1
#endif
#ifndef TFT_SCK_GPIO_Port
#define TFT_SCK_GPIO_Port GPIOB
#define TFT_SCK_Pin GPIO_PIN_3
#endif
#ifndef TFT_MOSI_GPIO_Port
#define TFT_MOSI_GPIO_Port GPIOD
#define TFT_MOSI_Pin GPIO_PIN_7
#endif
#if defined(LCD_CS_GPIO_Port) && defined(LCD_CS_Pin)
#define TFT_CS_GPIO_Port LCD_CS_GPIO_Port
#define TFT_CS_Pin LCD_CS_Pin
@@ -68,6 +80,7 @@ extern "C" {
#define TFT_COLOR_LIGHT_GRAY 0xC618U
void TFT_Init(void);
void TFT_ShowBootScreen(void);
void TFT_Clear(uint16_t color);
void TFT_FillRect(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color);
void TFT_DrawPoint(uint16_t x, uint16_t y, uint16_t color);

View File

@@ -22,6 +22,68 @@
#define WS2812_LowLevel 0xC0 // 0码
#define WS2812_HighLevel 0xF0 // 1码
static SPI_HandleTypeDef ws2812_spi;
static uint8_t ws2812_spi_initialized = 0U;
static uint8_t WS2812_SPI_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
if (ws2812_spi_initialized != 0U)
{
return 1U;
}
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI6;
PeriphClkInitStruct.Spi6ClockSelection = RCC_SPI6CLKSOURCE_HSE;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
return 0U;
}
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_SPI6_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF8_SPI6;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
ws2812_spi.Instance = SPI6;
ws2812_spi.Init.Mode = SPI_MODE_MASTER;
ws2812_spi.Init.Direction = SPI_DIRECTION_2LINES_TXONLY;
ws2812_spi.Init.DataSize = SPI_DATASIZE_8BIT;
ws2812_spi.Init.CLKPolarity = SPI_POLARITY_LOW;
ws2812_spi.Init.CLKPhase = SPI_PHASE_2EDGE;
ws2812_spi.Init.NSS = SPI_NSS_SOFT;
ws2812_spi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
ws2812_spi.Init.FirstBit = SPI_FIRSTBIT_MSB;
ws2812_spi.Init.TIMode = SPI_TIMODE_DISABLE;
ws2812_spi.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
ws2812_spi.Init.CRCPolynomial = 0x0;
ws2812_spi.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
ws2812_spi.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
ws2812_spi.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
ws2812_spi.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
ws2812_spi.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
ws2812_spi.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
ws2812_spi.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
ws2812_spi.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
ws2812_spi.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
ws2812_spi.Init.IOSwap = SPI_IO_SWAP_DISABLE;
if (HAL_SPI_Init(&ws2812_spi) != HAL_OK)
{
return 0U;
}
ws2812_spi_initialized = 1U;
return 1U;
}
/**
* @brief
* @param [in] r My Param doc
@@ -32,20 +94,26 @@ void WS2812_Ctrl(uint8_t r, uint8_t g, uint8_t b)
{
uint8_t txbuf[24];
uint8_t res = 0;
if (WS2812_SPI_Init() == 0U)
{
return;
}
for (uint8_t i = 0; i < 8U; i++)
{
txbuf[7 - i] = (((g >> i) & 0x01) ? WS2812_HighLevel : WS2812_LowLevel) >> 1;
txbuf[15 - i] = (((r >> i) & 0x01) ? WS2812_HighLevel : WS2812_LowLevel) >> 1;
txbuf[23 - i] = (((b >> i) & 0x01) ? WS2812_HighLevel : WS2812_LowLevel) >> 1;
}
if (HAL_SPI_Transmit(&WS2812_SPI_UNIT, txbuf, sizeof(txbuf), WS2812_SPI_TIMEOUT) != HAL_OK)
if (HAL_SPI_Transmit(&ws2812_spi, txbuf, sizeof(txbuf), WS2812_SPI_TIMEOUT) != HAL_OK)
{
return;
}
for (uint8_t i = 0; i < WS2812_RESET_BYTES; i++)
{
if (HAL_SPI_Transmit(&WS2812_SPI_UNIT, &res, 1U, WS2812_SPI_TIMEOUT) != HAL_OK)
if (HAL_SPI_Transmit(&ws2812_spi, &res, 1U, WS2812_SPI_TIMEOUT) != HAL_OK)
{
return;
}

View File

@@ -3,8 +3,5 @@
#include "main.h"
#define WS2812_SPI_UNIT hspi6
extern SPI_HandleTypeDef WS2812_SPI_UNIT;
void WS2812_Ctrl(uint8_t r, uint8_t g, uint8_t b);
#endif