diff --git a/Core/Src/spi.c b/Core/Src/spi.c index 4c88958..2937822 100644 --- a/Core/Src/spi.c +++ b/Core/Src/spi.c @@ -45,7 +45,10 @@ void MX_SPI1_Init(void) hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; hspi1.Init.NSS = SPI_NSS_SOFT; - hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4; + /* pll1_q=40MHz / 2 = 20MHz SPI(原来 /4=10MHz 太慢,单块刷新耗时逼近 + * 面板扫描周期导致移动错位)。ILI9341 写周期实测可稳定跑 20~40MHz; + * 若接线长/花屏,退回 SPI_BAUDRATEPRESCALER_4。 */ + hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi1.Init.TIMode = SPI_TIMODE_DISABLE; hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; diff --git a/SystemDrivers/ILI9341.c b/SystemDrivers/ILI9341.c index 376b316..a872fd0 100644 --- a/SystemDrivers/ILI9341.c +++ b/SystemDrivers/ILI9341.c @@ -242,29 +242,6 @@ static void LCD_CleanDCache(const void *addr, uint32_t size) #endif } -/* ================= 等待 SPI 移位彻底完成 ================= */ - -static void LCD_SPI_WaitShiftEmpty(void) -{ - /* HAL 在传输完成中断里已经把数据全部交给 SPI,但最后几个 bit 可能 - * 还在移位。拉高 CS 前确认 TXC/EOT,避免尾部像素被 CS 截断——尾部 - * 截断在快速移动时会表现为“擦除不干净/残留一条边”。 */ - uint32_t t0 = HAL_GetTick(); - -#if defined(SPI_FLAG_TXC) - while (__HAL_SPI_GET_FLAG(&hspi1, SPI_FLAG_TXC) == RESET) - { - if ((HAL_GetTick() - t0) > 5U) break; - } -#elif defined(SPI_FLAG_EOT) - while (__HAL_SPI_GET_FLAG(&hspi1, SPI_FLAG_EOT) == RESET) - { - if ((HAL_GetTick() - t0) > 5U) break; - } -#endif - __DSB(); -} - /* ================= 两种传输实现 ================= * 均为“同步返回”:函数返回时该块像素一定已完整写入面板。 * 返回值:0=成功,1=超时/出错(已尽力恢复)。 */ @@ -310,7 +287,9 @@ static uint8_t LCD_Xfer_DMA(const uint16_t *data, uint32_t byte_len) } } - LCD_SPI_WaitShiftEmpty(); + /* HAL 的 TxCplt 由 SPI EOT 触发,此刻数据已全部移出,直接拉高 CS。 + * 不再自旋等待 TXC——EOT 之后 HAL 会关闭 SPI,TXC 恒为 0,等待会白等 + * 满超时(实测每帧多耗约 5ms,正是移动错位的元凶之一)。 */ LCD_CS_HIGH(); return fail; } @@ -328,10 +307,10 @@ static uint8_t LCD_Xfer_Poll(const uint16_t *data, uint32_t byte_len) LCD_CS_LOW(); LCD_DC_DATA(); - /* byte_len 上限 = 单块缓冲字节数 < 65535,可一次发完 */ + /* byte_len 上限 = 单块缓冲字节数 < 65535,可一次发完。 + * HAL_SPI_Transmit 在 H7 上返回时数据已移出,直接拉高 CS。 */ st = HAL_SPI_Transmit(&hspi1, (uint8_t *)data, (uint16_t)byte_len, 100); - LCD_SPI_WaitShiftEmpty(); LCD_CS_HIGH(); return (st == HAL_OK) ? 0U : 1U;