lcd屏幕
液晶是一种介于固体和液体之间的特殊物质,它是一种有机化合物,常态下呈液态,但是它的分子排列却和固体晶体一样非常规则,因此取名液晶。如果给液晶施加电场,会改变它的分子排列,从而改变光线的传播方向,配合偏振光片,它就具有控制光线透过率的作用,再配合彩色滤光片,改变加给液晶电压大小,就能改变某一颜色透光量 的多少。用可控红、绿、蓝光输出强度的显示结构,把三种显示结构组成一个显示单位,通过控制红绿蓝的强度,可以使该单位混合输出不同的色彩,这样的一个显示单位就是我们所说的像素。
TFT-LCD(薄膜晶体管液晶显示器),其中TFT就是Thin Film Transistor的简称,指的是薄膜晶体管(矩阵),可以“主动的”对屏幕上的各个独立的像素进行控制,这也就是所谓的主动矩阵TFT(active matrix TFT)的来历。图像产生的基本原理很简单:显示屏由许多可以发出任意颜色的光线的像素组成,只要控制各个像素显示相应的颜色就能达到目的了。在TFT LCD中一般采用背光技术,为了能精确地控制每一个像素的颜色和亮度就需要在每一个像素之后安装一个半导体开关,以此做到完全的单独的控制一个像素点,液晶材料被夹在TFT玻璃层和颜色过滤层之间,通过改变刺激液晶的电压值就可以控制最后出现的光线强度与色彩。
lcd屏幕在代码中是通过对r7、g7、b7寄存器的读取来确定分辨率的。
采用RGB888的像素格式,一个像素点占用3个字节,共需要24位,bit23-bit16是RED通道,bit15-bit8是GREEN通道,bit7-bit0是BLUE通道。
HV同步模式下,图像的显示需要行同步信号(hsync)和场同步信号(vsync)来确定显示时序。此时,RGB接口的TFT-LCD液晶显示屏的显示时序和VGA时序标准类似。
时间参数:
行场扫描时序:
de:当为高电平时此时输出值到屏幕的对应像素点上。
LCD的显示和VGA的显示时序基本一致,都是从屏幕的左上角开始(从左往右,从上往下)经过Hor_sync_time和H_back_porch时间,屏幕开始显示,到H_front_porch时间后结束一行的显示,然后回到下一行左侧,循环到屏幕的最后一行扫描。在竖直方向上,经过 ver_sync_time和v_back_porch时间竖直方向屏幕开始显示,到ver_front_porch竖直方向显示结束。一帧显示完成。
在一个完整的行扫描周期中,RGB图像信息在HSync行同步信号的同步下完成一行图像的显示,在VSync行同步信号的同步下完成一帧图像的显示。RGB图像信息在有效图像阶段,图像信息有效,其他阶段图像信息无效;HSync和VSync行同步信号在同步阶段,维持高电平,其他阶段均保持低电平。在下一个行扫描周期的同步阶段,HSync和VSync行扫描信号拉高,其他阶段拉低,周而复始 。DE数据使能信号为高电平时,表示TFT显示屏扫描到了有效显示区域,此时输入到TFT显示屏的图像信息能够显示出来;当数据使能信号为低电平时,表示TFT显示屏未扫描到有效显示区域。
HSPW(行同步,是HSYNC信号持续时间。HSYNC信号不是一个脉冲,而是需要持续一段时间才是有效的,单位为CLK。)、HBP(行显示后沿)、HOZVAL(行有效显示区域,即显示一行数据所需的时间,假如屏幕分辨率为1024600,那么HOZVAL 就是1024,单位为CLK)、HFP(行显示前沿)、VSPW(场同步,帧同步信号宽度,也就是VSYNC信号持续时间,单位为1行的时间。)、VBP(场显示后沿)、LINE(场有效显示区域,显示一帧数据所需的时间,假如屏幕分辨率为1024600,那么LINE就是600行的时间)和VFP(场显示后沿)。
LCD屏(分辨率:1024*600)刷新一帧的时间
= (场同步+场显示后沿+场有效显示区域+场显示后沿) * (行同步 + 行显示后沿 + 行有效显示区域 + 行显示前沿)
先使用ZYNQ开发板上的RGB TFT-LCD接口,驱动RGB LCD液晶屏显示出彩条。
时钟模块:
module clk_div(input clk,input rstn,input [23:0]rgb_reg,
output reg lcd_pclk,output reg[15:0]lcd_id);
reg rd_flag,clk_25m,clk_12_5m,div_4_cnt;
always @(posedge clk or negedge rstn) begin
if(!rstn)
clk_25m<='d0;
else clk_25m<=~clk_25m;
end
always @(posedge clk or negedge rstn) begin
if(!rstn)
begin
div_4_cnt<='d0;
clk_12_5m<='d0;
end
else begin
div_4_cnt<=div_4_cnt+'d1;
if(div_4_cnt=='d1)
clk_12_5m=~clk_12_5m;
end
end
always @(*) begin
case(lcd_id)
16'h4342:lcd_pclk=clk_12_5m;
16'h7084:lcd_pclk=clk_25m;
16'h7016:lcd_pclk=clk;
16'h4384:lcd_pclk=clk_25m;
16'h1018:lcd_pclk=clk;
default:lcd_pclk='d0;
endcase
end
always @(posedge clk or negedge rstn) begin
if(!rstn) begin
rd_flag<='d0;
lcd_id<='d0;
end
else begin
if(rd_flag=='d0)begin
rd_flag<=~rd_flag;
case({
rgb_reg[7],rgb_reg[15],rgb_reg[23]})
3'b000:lcd_id<=16'h4342;
3'b001:lcd_id<=16'h7084;
3'b010:lcd_id<=16'h7016;
3'b100:lcd_id<=16'h4384;
3'b101:lcd_id<=16'h1018;
default:lcd_id<='d0;
endcase
end
end
end
endmodule
lcd驱动模块:
module lcd_driver
(input pclk,input rstn,input [15:0]lcd_id,
input[23:0] display_data,output reg[10:0] h_disp,
output reg[10:0]v_disp,
output [10:0]xpos,output[10:0] ypos,
output de,hs,vs,bl,lcd_clk,lcd_rst,
output[23:0] lcd_rgb);
parameter H_SYNC_4342 = 11'd41; //行同步
parameter H_BACK_4342 = 11'd2; //行显示后沿
parameter H_DISP_4342 = 11'd480; //行有效数据
parameter H_FRONT_4342 = 11'd2; //行显示前沿
parameter H_TOTAL_4342 = 11'd525; //行扫描周期
parameter V_SYNC_4342 = 11'd10; //场同步
parameter V_BACK_4342 = 11'd2; //场显示后沿
parameter V_DISP_4342 = 11'd272; //场有效数据
parameter V_FRONT_4342 = 11'd2; //场显示前沿
parameter V_TOTAL_4342 = 11'd286; //场扫描周期
// 7' 800*480
parameter H_SYNC_7084 = 11'd128; //行同步
parameter H_BACK_7084 = 11'd88; //行显示后沿
parameter H_DISP_7084 = 11'd800; //行有效数据
parameter H_FRONT_7084 = 11'd40; //行显示前沿
parameter H_TOTAL_7084 = 11'd1056; //行扫描周期
parameter V_SYNC_7084 = 11'd2; //场同步
parameter V_BACK_7084 = 11'd33; //场显示后沿
parameter V_DISP_7084 = 11'd480; //场有效数据
parameter V_FRONT_7084 = 11'd10; //场显示前沿
parameter V_TOTAL_7084 = 11'd525; //场扫描周期
// 7' 1024*600
parameter H_SYNC_7016 = 11'd20; //行同步
parameter H_BACK_7016 = 11'd140; //行显示后沿
parameter H_DISP_7016 = 11'd1024; //行有效数据
parameter H_FRONT_7016 = 11'd160; //行显示前沿
parameter H_TOTAL_7016 = 11'd1344; //行扫描周期
parameter V_SYNC_7016 = 11'd3; //场同步
parameter V_BACK_7016 = 11'd20; //场显示后沿
parameter V_DISP_7016 = 11'd600; //场有效数据
parameter V_FRONT_7016 = 11'd12; //场显示前沿
parameter V_TOTAL_7016 = 11'd635; //场扫描周期
// 10.1' 1280*800
parameter H_SYNC_1018 = 11'd10; //行同步
parameter H_BACK_1018 = 11'd80; //行显示后沿
parameter H_DISP_1018 = 11'd1280; //行有效数据
parameter H_FRONT_1018 = 11'd70; //行显示前沿
parameter H_TOTAL_1018 = 11'd1440; //行扫描周期
parameter V_SYNC_1018 = 11'd3; //场同步
parameter V_BACK_1018 = 11'd10; //场显示后沿
parameter V_DISP_1018 = 11'd800; //场有效数据
parameter V_FRONT_1018 = 11'd10; //场显示前沿
parameter V_TOTAL_1018 = 11'd823; //场扫描周期
// 4.3' 800*480
parameter H_SYNC_4384 = 11'd128; //行同步
parameter H_BACK_4384 = 11'd88; //行显示后沿
parameter H_DISP_4384 = 11'd800; //行有效数据
parameter H_FRONT_4384 = 11'd40; //行显示前沿
parameter H_TOTAL_4384 = 11'd1056; //行扫描周期
parameter V_SYNC_4384 = 11'd2; //场同步
parameter V_BACK_4384 = 11'd33; //场显示后沿
parameter V_DISP_4384 = 11'd480; //场有效数据
parameter V_FRONT_4384 = 11'd10; //场显示前沿
parameter V_TOTAL_4384 = 11'd525; //场扫描周期
reg[10:0]h_sync,h_back,h_total,
v_sync,v_back,v_total,h_cnt,v_cnt;
wire en,data_req;
assign hs='d1,vs='d1,bl='d1,lcd_rst='d1;
assign lcd_clk=pclk,de=en,lcd_rgb=de?display_data:'d0;
assign xpos=data_req?(h_cnt-(h_sync+h_back-1)):'d0,
ypos=data_req?(v_cnt-(v_sync+v_back-1)):'d0;
assign en=((h_cnt>=h_sync+h_back)&&(h_cnt<h_sync+h_back+h_disp)&&
(v_cnt>=v_sync+v_back)&&(v_cnt<v_sync+v_back+v_disp));
assign data_req=((h_cnt>=h_sync+h_back-'d1)&&(h_cnt<h_sync+h_back+h_disp-'d1)
&&(v_cnt>=v_sync+v_back)&&(v_cnt<v_sync+v_back+v_disp));
always @(*) begin
case(lcd_id)
16'h4342 : begin
h_sync = H_SYNC_4342;
h_back = H_BACK_4342;
h_disp = H_DISP_4342;
h_total = H_TOTAL_4342;
v_sync = V_SYNC_4342;
v_back = V_BACK_4342;
v_disp = V_DISP_4342;
v_total = V_TOTAL_4342;
end
16'h7084 : begin
h_sync = H_SYNC_7084;
h_back = H_BACK_7084;
h_disp = H_DISP_7084;
h_total = H_TOTAL_7084;
v_sync = V_SYNC_7084;
v_back = V_BACK_7084;
v_disp = V_DISP_7084;
v_total = V_TOTAL_7084;
end
16'h7016 : begin
h_sync = H_SYNC_7016;
h_back = H_BACK_7016;
h_disp = H_DISP_7016;
h_total = H_TOTAL_7016;
v_sync = V_SYNC_7016;
v_back = V_BACK_7016;
v_disp = V_DISP_7016;
v_total = V_TOTAL_7016;
end
16'h4384 : begin
h_sync = H_SYNC_4384;
h_back = H_BACK_4384;
h_disp = H_DISP_4384;
h_total = H_TOTAL_4384;
v_sync = V_SYNC_4384;
v_back = V_BACK_4384;
v_disp = V_DISP_4384;
v_total = V_TOTAL_4384;
end
16'h1018 : begin
h_sync = H_SYNC_1018;
h_back = H_BACK_1018;
h_disp = H_DISP_1018;
h_total = H_TOTAL_1018;
v_sync = V_SYNC_1018;
v_back = V_BACK_1018;
v_disp = V_DISP_1018;
v_total = V_TOTAL_1018;
end
default : begin
h_sync = H_SYNC_4342;
h_back = H_BACK_4342;
h_disp = H_DISP_4342;
h_total = H_TOTAL_4342;
v_sync = V_SYNC_4342;
v_back = V_BACK_4342;
v_disp = V_DISP_4342;
v_total = V_TOTAL_4342;
end
endcase
end
always @(posedge pclk or negedge rstn) begin
if(!rstn)begin
h_cnt<='d0;
v_cnt<='d0;
end
else if(h_cnt==h_total-'d1)begin
h_cnt<='d0;
if(v_cnt==v_total-'d1)
v_cnt<='d0;
else v_cnt<=v_cnt+'d1;
end
else begin
h_cnt<=h_cnt+'d1;
end
end
endmodule
顶层模块:
module colorbar_top(input clk,input rstn,inout [23:0]lcd_rgb,
output de,hs,vs,bl,lcd_clk,lcd_rst);
wire pclk;
wire[23:0]display_data