FPGA中级项目7———TFT显示与驱动

FPGA中级项目7———TFT显示与驱动

老样子,啥是TFT?


TFT(Thin - Film Transistor)即薄膜晶体管,是一种用于液晶显示器(LCD)等显示设备的技术


        TFT 显示屏由大量的像素组成,每个像素包含一个液晶盒以及与之对应的 TFT 开关元件等。当没有电场作用时,液晶分子的排列使得光线能够通过液晶盒,并在经过偏振片等光学元件后,呈现出特定的亮度和颜色。当有电场施加时,液晶分子会在电场作用下发生旋转或扭曲,改变其对光线的偏振方向和透过率。通过控制每个像素点上液晶分子的旋转角度,可以精确控制该像素点的透光量,进而实现不同的灰度和颜色显示。例如,在彩色 TFT 显示屏中,通过在每个像素点上设置红、绿、蓝三种颜色的子像素,并分别控制它们的亮度,就可以组合出各种不同的颜色,最终形成完整的图像。
        有着40 Pin排针接线能提供丰富的功能和稳定的数据传输,这种 TFT 显示屏可应用于多种场景,如工业控制设备的人机交互界面、汽车电子的仪表盘显示、智能家居设备的显示屏等。

TFT 显示屏有诸多重要参数


分辨率:指屏幕上像素的数量,通常用水平像素数乘以垂直像素数来表示,如 1920×1080;800×480等。较高的分辨率意味着屏幕能够显示更清晰、更细腻的图像和文字。
尺寸:以屏幕对角线的长度来衡量,单位一般为英寸。常见的尺寸有 3.5 英寸、5 英寸、7 英寸等。
色彩深度:表示每个像素点能够显示的颜色数量,常见的有 18 位(26 万色)和 24 位(1677 万色)。色彩深度越高,显示的颜色越丰富、越逼真。
亮度:单位是尼特(nit),它反映了屏幕的发光强度。高亮度的屏幕在明亮的环境下也能清晰显示内容,一般户外使用的显示屏需要较高的亮度。
对比度:是屏幕上最亮区域与最暗区域的亮度比值。较高的对比度能够使图像的亮部更亮,暗部更暗,从而呈现出更鲜明的色彩和更丰富的细节。
响应时间:指像素点从一种颜色转换到另一种颜色所需的时间,单位为毫秒(ms)。响应时间越短,在显示动态画面时越不容易出现拖影现象,适合用于播放视频和游戏等场景。

        真彩色为RGB888(在上一节内容便是),但是为了节约布线与硬件资源,可以进行简化为RGB565,便是取红绿蓝的各高565位,也称为伪真彩色。两者可相互转化

        像素点是构成图像的最小单位,每个像素点的颜色由红(R)、绿(G)、蓝(B)三种基本颜色按照不同比例混合而成。RGB888 和 RGB565 决定了每个像素点中这三种颜色的表示方式和精度。
        RGB888 比 RGB565 能表示的颜色种类更多。RGB888 格式中,红色、绿色、蓝色三个通道各用 8 位来表示,每个通道都有(2^8 = 256)种不同的取值,那么总共能表示的颜色数量为(256×256×256 = 16777216)种。RGB565 格式中,红色通道用 5 位表示,有(2^5 = 32)种取值;绿色通道用 6 位表示,有(2^6 = 64)种取值;蓝色通道用 5 位表示,有(2^5 = 32)种取值。所以 RGB565 能表示的颜色数量是(32×64×32 = 65536)种。两者可表示的颜色数量相差(16777216 - 65536 = 16711680)种。因此,RGB888 比 RGB565 多了 16711680 种颜色。


非常幸运的是:TFT的显示无需另外的代码。只需要将上一节VGA的内容相应地方根据排线接口修改即可

TFT代码如下

TFT模块代码如下:

//定义输入输出端口
module TFT(
        clk,
        reset_n,
        data_in,//用户输入数据
        TFT_HS,//行同步信号
        TFT_VS,//场同步信号
        hcount,//行扫描位置
        vcount,//场扫描位置
        TFT_DE,//数据输出时间段
        TFT_CLK,
        data_out,
        TFT_BL
    );
        input clk;
        input reset_n;
        input [23:0]data_in;
        output TFT_HS;
        output TFT_VS;
        output [10:0]hcount;//行同步的信号最大值为1056
        output [10:0]vcount;
        output TFT_DE;
        output TFT_CLK;
        output [23:0]data_out;
        output TFT_BL;



// 定义不同的分辨率
//`define resolution_480x272 1 // 时钟为9MHz
//`define resolution_640x480 1 // 时钟为25MHz
`define resolution_800x480 1 // 时钟为33MHz
//`define resolution_800x600 1 // 时钟为40MHz
//`define resolution_1024x600 1 // 时钟为51MHz
//`define resolution_1024x768 1 // 时钟为65MHz
//`define resolution_1280x720 1 // 时钟为74.25MHz
//`define resolution_1920x1080 1 // 时钟为148.5MHz

`ifdef resolution_480x272
    `define h_right_border 0
    `define h_front_porch 2
    `define h_sync_time 41
    `define h_back_porch 2
    `define h_left_border 0
    `define h_data_time 480
    `define h_total_time 525

    `define v_bottom_border 0
    `define v_front_porch 2
    `define v_sync_time 10
    `define v_back_porch 2
    `define v_top_border 0
    `define v_data_time 272
    `define v_total_time 286

`elsif resolution_640x480
    `define h_right_border 0
    `define h_front_porch 16
    `define h_sync_time 96
    `define h_back_porch 48
    `define h_left_border 0
    `define h_data_time 640
    `define h_total_time 800

    `define v_bottom_border 0
    `define v_front_porch 10
    `define v_sync_time 2
    `define v_back_porch 33
    `define v_top_border 0
    `define v_data_time 480
    `define v_total_time 525

`elsif resolution_800x480
    `define h_right_border 0
    `define h_front_porch 40
    `define h_sync_time 128
    `define h_back_porch 88
    `define h_left_border 0
    `define h_data_time 800
    `define h_total_time 1056

    `define v_bottom_border 8
    `define v_front_porch 2
    `define v_sync_time 2
    `define v_back_porch 25
    `define v_top_border 8
    `define v_data_time 480
    `define v_total_time 525

`elsif resolution_800x600
    `define h_right_border 0
    `define h_front_porch 40
    `define h_sync_time 128
    `define h_back_porch 88
    `define h_left_border 0
    `define h_data_time 800
    `define h_total_time 1056

    `define v_bottom_border 0
    `define v_front_porch 1
    `define v_sync_time 4
    `define v_back_porch 23
    `define v_top_border 0
    `define v_data_time 600
    `define v_total_time 628

`elsif resolution_1024x600
    `define h_right_border 0
    `define h_front_porch 24
    `define h_sync_time 136
    `define h_back_porch 160
    `define h_left_border 0
    `define h_data_time 1024
    `define h_total_time 1344

    `define v_bottom_border 0
    `define v_front_porch 1
    `define v_sync_time 3
    `define v_back_porch 28
    `define v_top_border 0
    `define v_data_time 600
    `define v_total_time 632

`elsif resolution_1024x768
    `define h_right_border 0
    `define h_front_porch 24
    `define h_sync_time 136
    `define h_back_porch 160
    `define h_left_border 0
    `define h_data_time 1024
    `define h_total_time 1344

    `define v_bottom_border 0
    `define v_front_porch 3
    `define v_sync_time 6
    `define v_back_porch 29
    `define v_top_border 0
    `define v_data_time 768
    `define v_total_time 806

`elsif resolution_1280x720
    `define h_right_border 0
    `define h_front_porch 110
    `define h_sync_time 40
    `define h_back_porch 220
    `define h_left_border 0
    `define h_data_time 1280
    `define h_total_time 1650

    `define v_bottom_border 0
    `define v_front_porch 5
    `define v_sync_time 5
    `define v_back_porch 36
    `define v_top_border 0
    `define v_data_time 720
    `define v_total_time 750

`elsif resolution_1920x1080
    `define h_right_border 0
    `define h_front_porch 88
    `define h_sync_time 44
    `define h_back_porch 148
    `define h_left_border 0
    `define h_data_time 1920
    `define h_total_time 2200

    `define v_bottom_border 0
    `define v_front_porch 4
    `define v_sync_time 5
    `define v_back_porch 36
    `define v_top_border 0
    `define v_data_time 1080
    `define v_total_time 1125

`endif    

 
 //定义时序中相关信号       
        //parameter VGA_HS_end =  11'd127;
        //parameter hdat_begin = 11'd216;//行数据开始输出位置
        //parameter hdat_end = 11'd1016;//行数据停止输出位置
        //parameter hpixel_end = 11'd1055;//行扫描的最大位置处
        
        //parameter VGA_VS_end =  11'd1;
        //parameter vdat_begin = 11'd35;
        //parameter vdat_end = 11'd515;
        //parameter vpixel_end = 11'd524; 
                   
//将上述的parameter定义改为参数定义,便于适配
        parameter  TFT_HS_end = `h_sync_time - 1,
                    hdat_begin = `h_sync_time + `h_back_porch + `h_left_border,
                    hdat_end = `h_sync_time + `h_back_porch + `h_left_border + `h_data_time,
                    hpixel_end = `h_total_time - 1,
                    TFT_VS_end = `v_sync_time - 1,
                    vdat_begin = `v_sync_time + `v_back_porch + `v_top_border,
                    vdat_end = `v_sync_time + `v_back_porch + `v_top_border + `v_data_time,
                    vpixel_end = `v_total_time - 1;
                  
                  
 
 //定义计数器,开始行扫描信号,场扫描信号计数       
        reg [10:0]hcount_r;
        reg [10:0]vcount_r;
always@(posedge clk or negedge reset_n)
if(!reset_n)
        hcount_r <= 11'd0;
else if(hcount_r  == hpixel_end)       
        hcount_r <= 11'd0;
else
        hcount_r <= hcount_r + 1'd1;
    
    
always@(posedge clk or negedge reset_n)
if(!reset_n) 
        vcount_r <= 11'd0;
else if(hcount_r  == hpixel_end)  begin
        if(vcount_r == vpixel_end)  
        vcount_r <= 11'd0;
        else
        vcount_r <= vcount_r + 1'd1;
        end
else
        vcount_r <= vcount_r;
                
                
              
//定义相关信号    
assign  TFT_HS = (hcount_r > TFT_HS_end) ?1'b1:1'b0;
assign  TFT_VS = (vcount_r > TFT_VS_end) ?1'b1:1'b0;  
assign  TFT_DE =((hcount_r >= hdat_begin) &&(hcount_r < hdat_end ) &&(vcount_r >= vdat_begin )&&(vcount_r < vdat_end))?1'b1:1'b0;
assign  hcount = TFT_DE ? (hcount_r - hdat_begin) :10'd0;
assign  vcount = TFT_DE ? (vcount_r - vdat_begin) :10'd0;
assign  data_out = (TFT_DE) ? data_in : 24'h000000;
assign  TFT_CLK = ~clk; 
assign  TFT_BL = 1;   
    

    
endmodule

TFT显示的顶层代码如下:

//定义输入输出端口
module TFT_CTRL(
        clk_50M,
        reset_n,
        TFT_HS,//行同步信号
        TFT_VS,//场同步信号
        TFT_DE,//数据输出时间段
        TFT_CLK,
        data_out,
        TFT_BL
    );
        input clk_50M;
        input reset_n;
        output TFT_HS;
        output TFT_VS;
        output TFT_DE;
        output TFT_CLK;
        output [23:0]data_out;
        output TFT_BL;
        
//定义相关信号        
        reg [23:0]data_in;
        wire locked;
        wire clk;
        wire [11:0]hcount;
        wire [11:0]vcount;
 
        
//定义计数器counter0
        reg [31:0]counter0;
always@(posedge clk_50M or negedge reset_n)
if(!reset_n)
        counter0 <= 0;
else if(counter0 == 99_999_999)
        counter0 <= 0;
else
        counter0 <= counter0 + 1'd1;
        
        
//定义使能信号
        reg en ;
always@(posedge clk_50M or negedge reset_n)
if(!reset_n)
        en <= 0;
else if(counter0 >= 49_999_999)
        en <= 1;
else
        en <= 0;
                        
//定义颜色代码
localparam   black = 24'h000000,
             blue = 24'h0000FF,
             red = 24'hFF0000,
             purpple = 24'hFF00FF,
             green = 24'h00FF00,
             cyan = 24'h00FFFF,
             yellow = 24'hFFFF00,
             white = 24'hFFFFFF;
             
             
//例化时钟IP核 33M                         
            clk_33 clk_33
   (
    // Clock out ports
    .clk_out1(clk),     // output clk_out1
    // Status and control signals
    .reset(!reset_n), // input reset
    .locked(locked),       // output locked
   // Clock in ports
    .clk_in1(clk_50M));  



//例化已经写好的TFT块
         TFT(
                 .clk(clk),
                 .reset_n(reset_n),
                 .data_in(data_in),//用户输入数据
                 .TFT_HS(TFT_HS),//行同步信号
                 .TFT_VS(TFT_VS),//场同步信号
                 .hcount(hcount),//行扫描位置
                 .vcount(vcount),//场扫描位置
                 .TFT_DE(TFT_DE),//数据输出时间段
                 .TFT_CLK(TFT_CLK),
                 .data_out(data_out),
                 .TFT_BL(TFT_BL)
             );
         



//定义扫描像素块
        wire c0_act = hcount >= 0 && hcount <400;//扫描第0列
        wire c1_act = hcount >= 400 && hcount <800;//扫描第1列
        wire r0_act = vcount >= 0 && vcount < 120;//扫描第0行
        wire r1_act = vcount >= 120 && vcount < 240;//扫描第1行
        wire r2_act = vcount >= 240 && vcount < 360;//扫描第2行
        wire r3_act = vcount >= 360 && vcount < 480;//扫描第3行
        wire r0_c0_act = r0_act & c0_act;//定位第0列,第0行像素块扫描
        wire r0_c1_act = r0_act & c1_act;//定位第0列,第1行像素块扫描
        wire r1_c0_act = r1_act & c0_act;//定位第1列,第0行像素块扫描
        wire r1_c1_act = r1_act & c1_act;//定位第1列,第1行像素块扫描
        wire r2_c0_act = r2_act & c0_act;//定位第2列,第0行像素块扫描
        wire r2_c1_act = r2_act & c1_act;//定位第2列,第1行像素块扫描
        wire r3_c0_act = r3_act & c0_act;//定位第3列,第0行像素块扫描
        wire r3_c1_act = r3_act & c1_act;//定位第3列,第1行像素块扫描
        
        
//定义像素块显示颜色
always@(posedge clk)
if(en == 1) begin
case({r3_c1_act, r3_c0_act,r2_c1_act,r2_c0_act,r1_c1_act,r1_c0_act,r0_c1_act,r0_c0_act})
        8'b0000_0001 :  data_in <= black;
        8'b0000_0010 :  data_in <= blue;    
        8'b0000_0100 :  data_in <= red;    
        8'b0000_1000 :  data_in <= purpple;    
        8'b0001_0000 :  data_in <= green;    
        8'b0010_0000 :  data_in <= cyan;    
        8'b0100_0000 :  data_in <= yellow;    
        8'b1000_0000 :  data_in <= white;            
        endcase
        end
else
        data_in <= 24'h0000FF;        
        

endmodule

需要指出的是,进行TFT显示和VGA显示的原理一致,回扫时间,行同步脉冲信号,行同步结束信号,行扫描最大位置等按照芯片手册规定的时钟周期来定义

视频效果呈现

TFT显示


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值