Files
motor_ili9341/SystemDrivers/ILI9341.h
T
zhy200308 e4d61b19f0 重构 ILI9341+LVGL 驱动:异步 DMA + 硬件旋转,修复残影与白屏
- 硬件 MADCTL 旋转,删除软件转置,LVGL 坐标与面板 1:1,消除移动残影
- 全异步 DMA:flush 启动即返回,完成/出错由 SPI 中断收尾,去掉信号量阻塞
- DMA 缓冲经 .lcd_ram 段强制放入 AXI SRAM,规避 DTCM 不可被 DMA 访问导致的白屏
- LV_COLOR_16_SWAP=1,LVGL 直出面板字节序,省去逐像素交换/拷贝
- 看门狗超时重建 SPI 自恢复,单次异常不再级联长时间白屏
- 定制 scatter(motor_ili9341_lcd.sct) 并接入 uvprojx
- 新增 README_ILI9341.md 说明根因/设计/构建验证
2026-07-08 11:02:42 +08:00

114 lines
4.7 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.
#ifndef __ILI9341_H__
#define __ILI9341_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "main.h"
#include "spi.h"
#include <stdint.h>
#include <stddef.h>
/* ============================================================
* ILI9341 TFT-LCD 驱动 (STM32H750 + SPI1 + DMA1_Stream2)
*
* 设计要点(详见 SystemDrivers/README_ILI9341.md):
* 1. 硬件旋转:方向完全由 MADCTL 决定,软件不做转置,
* LVGL 坐标与面板坐标 1:1 对应,从根本上消除移动物体
* 残留/拖影问题。
* 2. 全异步 DMAILI9341_FlushArea_DMA() 启动 DMA 后立刻返回,
* 传输完成由 SPI 中断回调收尾并触发用户回调(=lv_disp_flush_ready)。
* 刷新任务不再阻塞,SPI/DMA 时序自同步,不依赖任何 RTOS 信号量。
* 3. DMA 源缓冲必须位于 DMA 可访问内存(AXI SRAM 0x24000000)
* 绝不能放在 DTCM(0x20000000)——DMA1 无法访问 DTCM。
* LVGL 绘制缓冲用 LCD_RAM_ATTR 强制放入 .lcd_ram 段。
* 4. 看门狗 + 出错自恢复:任何一次传输异常都会被恢复,
* 不会级联导致长时间白屏。
* ============================================================ */
/* 面板原生(未旋转)分辨率 */
#define ILI9341_NATIVE_WIDTH 240U
#define ILI9341_NATIVE_HEIGHT 320U
/* 当前工作方向下的分辨率(默认横屏 320x240,见 ILI9341_SetRotation */
#define ILI9341_WIDTH 320U
#define ILI9341_HEIGHT 240U
/* ------------------------------------------------------------
* LCD 控制引脚(与 main.h / gpio.c 保持一致,PB12=CS 已被配置为输出)
* ------------------------------------------------------------ */
#define LCD_CS_PORT GPIOB
#define LCD_CS_PIN GPIO_PIN_12
#define LCD_DC_PORT GPIOB
#define LCD_DC_PIN GPIO_PIN_7
#define LCD_RST_PORT GPIOB
#define LCD_RST_PIN GPIO_PIN_8
#define LCD_BL_PORT GPIOB
#define LCD_BL_PIN GPIO_PIN_9
/* RGB565 常用颜色(大端字节序由发送时处理) */
#define ILI9341_BLACK 0x0000
#define ILI9341_WHITE 0xFFFF
#define ILI9341_RED 0xF800
#define ILI9341_GREEN 0x07E0
#define ILI9341_BLUE 0x001F
#define ILI9341_YELLOW 0xFFE0
#define ILI9341_CYAN 0x07FF
#define ILI9341_MAGENTA 0xF81F
#define ILI9341_GRAY 0x8410
/* ------------------------------------------------------------
* DMA 可访问内存属性。
* 所有交给 ILI9341_FlushArea_DMA() 的缓冲区都必须用它修饰,
* 链接脚本(motor_ili9341_lcd.sct)会把 .lcd_ram 段放到 AXI SRAM。
* 32 字节对齐是为了配合 D-Cache 的 clean-by-address 粒度。
* ------------------------------------------------------------ */
#if defined(__GNUC__) || defined(__clang__)
#define LCD_RAM_ATTR __attribute__((section(".lcd_ram"), aligned(32)))
#else
#define LCD_RAM_ATTR
#warning "未识别的工具链:请自行确保 LCD DMA 缓冲位于 DMA 可访问内存并 32 字节对齐"
#endif
/* 传输完成回调(在 SPI 中断上下文里被调用,务必只做极短的事) */
typedef void (*ILI9341_FlushDoneCb)(void *user_data);
/* ---- 初始化 / 方向 ---- */
void ILI9341_Init(void);
void ILI9341_SetRotation(uint8_t rotation); /* 0/1/2/3,默认 1=横屏 */
/* ---- 阻塞式基础绘图(仅用于初始化清屏/自检,非 LVGL 热路径) ---- */
void ILI9341_FillScreen(uint16_t color);
void ILI9341_FillRect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color);
uint16_t ILI9341_Color565(uint8_t r, uint8_t g, uint8_t b);
/* ---- LVGL 异步刷新入口 ----
* data 必须已按面板发送顺序排列(配合 lv_conf.h 的 LV_COLOR_16_SWAP=1
* LVGL 直接产出正确字节序,无需再拷贝/交换)。
* 函数启动 DMA 后立即返回;传输完成后在中断里调用 done_cb(user_data)。
* 若参数非法或启动失败,会同步调用 done_cb 以避免 LVGL 卡死。 */
void ILI9341_FlushArea_DMA(uint16_t x, uint16_t y,
uint16_t w, uint16_t h,
const uint16_t *data,
ILI9341_FlushDoneCb done_cb,
void *user_data);
/* ---- 传输是否进行中(供上层判断) ---- */
uint8_t ILI9341_IsBusy(void);
/* ---- 看门狗:从任务上下文周期性调用(例如 lv_timer_handler 之后)。
* 绝不能从中断里调用。若一次 DMA 传输超过 timeout_ms 仍未完成,
* 强制中止、重建 SPI、恢复 CS 并触发完成回调,避免永久白屏。
* timeout_ms 建议 150~200ms。 */
void ILI9341_ServiceWatchdog(uint32_t timeout_ms);
#ifdef __cplusplus
}
#endif
#endif /* __ILI9341_H__ */