当前位置:首页 > 显示光电 > 显示光电
[导读]高分辨率MIPI屏“卡顿/撕裂”通常不是时钟不够,而是显示扫描和CPU写帧缓冲没同步。驱动写法先分两种模式:带GRAM的屏走Command Mode,主机写显存、屏自己刷;不带GRAM的大屏走Video Mode,主机按时序持续推像素流。


高分辨率MIPI屏“卡顿/撕裂”通常不是时钟不够,而是显示扫描和CPU写帧缓冲没同步。驱动写法先分两种模式:带GRAM的屏走Command Mode,主机写显存、屏自己刷;不带GRAM的大屏走Video Mode,主机按时序持续推像素流。

一、先定模式再写代码

Command Mode:

初始化发厂家的sleep-out、像素格式、display on

画面变化才写GRAM,支持局部刷新

防撕裂靠TE信号

Video Mode:

主机必须持续发像素流,停发就黑屏

无GRAM,无TE概念,靠VSYNC/时序边界

高分辨率要算带宽:分辨率×位深×帧率×通道开销

配错模式最典型现象:命令屏当视频屏配→只亮一帧;视频屏当命令屏配→无持续流、画面丢。

二、双缓冲:绘制和扫描分离

单帧缓冲下CPU改到一半,LCD控制器正好扫到该行,就出撕裂线。正确开前后缓冲:

static uint8_t *fb_front;

static uint8_t *fb_back;


void gui_render(void){

   draw_ui(fb_back);          // CPU只写back buffer

}


void swap_buffers(void){

   uint8_t *tmp = fb_front;

   fb_front = fb_back;

   fb_back = tmp;             // 只换指针

}

双缓冲解决“同时写同一块”,但不解决“什么时候换”——换早了照样撕。

三、Command Mode:TE同步写GRAM

TE脚接MCU外部中断,屏进入垂直消隐时拉脉冲,MCU收到后才启动DMA写下一帧:

volatile int te_flag = 0;


void EXTI_TE_IRQHandler(void){

   te_flag = 1;

}


void display_flush(void){

   if(!te_flag) return;            // 不在扫描安全窗不写

   te_flag = 0;

   dsi_dcs_write(0x2C, NULL, 0);   // write_memory_start

   dma_start(fb_back, LCD_WIDTH*LCD_HEIGHT*2);

}


void DMA_Complete_IRQ(void){

   lv_disp_flush_ready(disp);     // 或置flush_done

}

初始化里开TE:

uint8_t te = 0x00;

dsi_dcs_write(0x35, &te, 1);       // TE on

注意:TE只把“写GRAM”错开到屏不读的时刻;单GRAM屏如果一帧写入时间大于屏扫描周期,仍可能套圈撕裂,这时候要降分辨率/局部刷新/上视频模式。

四、Video Mode:VSYNC或行中断切缓冲

视频模式屏没GRAM,缓冲在MCU侧,LCDC/DMA持续搬:

RGB/LTDC屏用控制器VSYNC中断切前后缓冲

MIPI DPI视频流由DSI主机按时序推,CPU别中途换fb指针

切换只在帧边界,扫描中换=撕裂

五、高分辨率带宽优化

720p/1080p下卡顿多是搬运瓶颈,不是绘制慢:

帧缓冲放外部RAM/PSRAM,DMA直读,CPU不碰像素

减少memcpy:解码器直接输出到fb_back,别SRAM→PSRAM→DSI再拷一遍

Cache一致性:DMA读前Invalidate,CPU写后Clean,否则屏收到旧数据

像素格式:车机仪表用RGB565省一半带宽,主屏才RGB888

lane数匹配:高分辨率开2/4 lane,单lane硬顶会掉帧

局部刷新:命令模式只刷变化矩形,仪表指针区/告警条单独更新

DMA完成和链路完成分开:源缓冲DMA读完才能复用,DSI包发完才能起下一笔

六、flush_cb写法(LVGL场景)

void lv_flush_cb(lv_disp_t*d, const lv_area_t*a, uint8_t*px){

   if(te_mode) wait_te();                 // 命令屏等TE

   dsi_set_column(a->x1, a->x2);

   dsi_set_page(a->y1, a->y2);

   dsi_dcs_write(0x2C, NULL, 0);

   dma_start(px, (a->x2-a->x1+1)*(a->y2-a->y1+1)*2);

   // DMA ISR里再调 lv_disp_flush_ready

}

别在flush_cb里阻塞等发完,也别DMA没完成就重用draw buffer。

七、落坑清单

模式配反:命令屏当视频屏,亮一下不动

双缓冲但随时swap:撕裂照旧

命令屏不开TE:写GRAM撞扫描

DMA没完成就改back buffer:新旧帧混屏

Cache没清:MIPI偶发花屏

高分辨率单lane:带宽不够掉帧

初始化顺序错:0x11后延时不够、0x29前开TE反而无脉冲

局部刷新区域算错:写入区和扫描区重叠仍撕

按“确认GRAM→命令模式开TE/视频模式靠VSYNC→前后双缓冲→DMA搬帧→Cache清理→flush完成回调”落地,MIPI屏高分辨率下才能无卡顿无撕裂。核心就一句:显示控制器在读的那一刻,你写的缓冲不能是同一块,也不能在中途换指针。



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