当前位置:首页 > 显示光电 > 显示光电
[导读]SPI小屏花屏、残影基本不是“屏坏了”,而是命令/数据时序、GRAM窗口、缓冲同步三处没接对。花屏是数据写错位置或写串了;残影是旧像素没被覆盖,或屏还在扫描时你就改了GRAM。


SPI小屏花屏、残影基本不是“屏坏了”,而是命令/数据时序、GRAM窗口、缓冲同步三处没接对。花屏是数据写错位置或写串了;残影是旧像素没被覆盖,或屏还在扫描时你就改了GRAM。

一、DC/CS时序错=花屏头号原因

SPI LCD只有四根线时,屏靠DC判断“当前字节是命令还是数据”。DC在传输途中跳变,ST7789这类控制器会把数据当命令、命令当数据,初始化直接乱掉。

规则很简单:

发命令:CS拉低 → DC拉低 → 发字节

发数据:CS保持低 → DC拉高 → 连续发

DC切换必须在SPI空闲期完成,别在SCK跳动时翻

一次连续刷屏不要每字节都切CS,开始拉低、结束拉高即可

void lcd_write_cmd(uint8_t c){

   LCD_CS_LOW();

   LCD_DC_CMD();      // DC=0

   spi_tx(&c,1);

}

void lcd_write_data(uint8_t *p, int len){

   LCD_DC_DATA();     // DC=1,CS别动

   spi_tx(p,len);

}

void lcd_end(void){ LCD_CS_HIGH(); }

上电瞬间DC别悬空,加10k下拉;RST拉低≥10ms再释放,等120ms再发Sleep Out→Display On,否则初始化不完整。

二、地址窗口设错=错位花屏

往GRAM写像素前必须先设窗口,否则写入指针按屏内部默认范围走,坐标一偏就是斜条纹。

void lcd_set_window(uint16_t x0,uint16_t y0,uint16_t x1,uint16_t y1){

   lcd_write_cmd(0x2A);            // CASET

   lcd_write_data((uint8_t[]){

       x0>>8,x0&0xFF,x1>>8,x1&0xFF},4);

   lcd_write_cmd(0x2B);            // RASET

   lcd_write_data((uint8_t[]){

       y0>>8,y0&0xFF,y1>>8,y1&0xFF},4);

   lcd_write_cmd(0x2C);            // RAMWR

}

坑点:

结束坐标是闭区间,128宽屏是0~127不是0~128

MADCTL方向换了,窗口坐标也要跟着换

RGB/BGR寄存器配错→颜色错乱不算花屏也算“伪花屏”

三、DMA刷屏:完成前别碰缓冲

用DMA搬帧数据,CPU才能脱手。但最典型的花屏是——DMA没发完,主循环已经开始改下一帧缓冲,甚至CS提前拉高截断传输。

static uint8_t fb_a[FB_SIZE], fb_b[FB_SIZE];

static uint8_t *front = fb_a, *back = fb_b;

static volatile uint8_t dma_busy = 0;


void lcd_flush(void){

   while(dma_busy);

   uint8_t *t = front; front = back; back = t;   // 换指针

   dma_busy = 1;

   lcd_set_window(0,0,W-1,H-1);

   LCD_DC_DATA(); LCD_CS_LOW();

   HAL_SPI_Transmit_DMA(&hspi, front, FB_SIZE);

}


void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef*h){

   if(h->Instance==SPI1){

       LCD_CS_HIGH();              // 只有这里能放CS

       dma_busy = 0;

   }

}

带Cache的内核还要在DMA前Clean缓冲:

SCB_CleanDCache_by_Addr(front, FB_SIZE);

单缓冲直接写GRAM=半旧半新撕裂;双缓冲才是正解。

四、残影:不是清屏命令没用,是区域没覆盖

残影常见三种:

旧文字没擦:只在新内容位置画,没把旧矩形填背景色

伪清屏:发了填充色但没重设0x2A/0x2B窗口,只刷了部分GRAM

电荷残留:下电不按序关显示/背光,液晶恢复不全

正确局部刷新:

void lcd_clear_rect(uint16_t x,uint16_t y,uint16_t w,uint16_t h,uint16_t bg){

   lcd_set_window(x,y,x+w-1,y+h-1);

   for(int i=0;i<w*h;i++) lcd_write_pixel(bg);

}

动哪里清哪里,别整屏狂刷——SPI带宽本来就紧。

字体透明、叠加图层时更容易留尾巴:每次重画前先把脏矩形填底再画新内容。

五、TE同步(带TE脚的屏才用)

屏内部扫描GRAM和MCU写GRAM撞上,就会出现一条水平撕裂线。带TE引脚的控制器发0x35开TE,MCU等TE中断再启动DMA写GRAM。

void TE_IRQHandler(void){

   if(need_flush) lcd_flush();

}

注意:TE只保证“起点错开”,整帧传输时间超过安全窗仍会追尾,所以高分辨率屏别盲目整屏刷,改局部窗口。

六、排错顺序

偶发花屏先降SPI时钟:降了就好=信号完整性/超频;不变=DC或窗口逻辑错。

白屏/颜色错:DC、MADCTL、RGB/BGR

斜条纹:CASET/RASET终点算错

半幅新旧:单缓冲、DMA没等完成

切换留影:脏矩形没清、旧区域边界算小

长期残影:VCOM、上下电时序、5V误供3.3V屏

电源上VCC/GND并100nF+10μF,SCK/MOSI别超10cm飞线,CS上拉,DC下拉,复位用GPIO别只靠RC。

七、落地原则

SPI LCD稳定刷屏就三条底线:

DC/CS切换干净、地址窗口每次重设、DMA完成前缓冲不动。

花屏查时序和窗口,残影查覆盖区和上下电;带TE就等TE,不带TE就用双缓冲+局部刷新。别在中断里做绘图,别在DMA没完就swap,别把清屏当成“发个颜色指令”就完事——GRAM指针和矩形区域都得自己管。



本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
关闭