????????液晶是一种介于液体和固体之间的有机化合物。液晶分子在不同电场作用下能够改变其排列状态,进而影响光的透过程度。典型的LCD由两片玻璃之间夹着一层液晶材料构成。这两片玻璃上涂有透明导电层,形成了像素。每个像素由三个互补色的次像素(红、绿、蓝)组成。当电场施加在液晶上时,液晶分子重新排列,使光无法通过。这种状态称为“散射状态”或“阻挡状态”。通过在液晶屏上对每个像素的电场进行调控,可以控制像素的透明度,形成图像。
? ? ? ? 像素:Pixel,是图像的最小单位,由图像的小方格组成的,这些小方块都有一个明确的位置和被分配的色彩数值
? ? ? ? 分辨率:指的是图像中每个方向上的像素数量。例如,1920x1080的分辨率表示图像有1920个像素宽,1080个像素高。
????????像素格式:将 RGB 三种颜色进行量化,每种颜色用 8Bit 表示, RGB 共需要 24 位,即 RGB888 格式。
? ? ? ? 刷新率:即刷新一帧所用的时间。= (VSPW+VBP+LINE+VFP) * (HSPW + HBP + HOZVAL + HFP)。
????????HSYNC信号是用于同步每行像素的刷新的信号。它告诉显示设备何时开始新的行。在水平扫描线的末尾,HSYNC信号会触发屏幕回到下一行的开头,准备显示下一行的像素。当HSYNC被拉高,经过一个行显示前沿HBP后,标志位像素有效信号DE被拉高,此时开始对LCD显示屏传输数据
? ? ? ? 当所有的行都被扫描后,开始显示下一帧。VSYNC信号是用于同步整个图像帧刷新的信号。它告诉显示设备何时开始新的帧。在每个帧的末尾,VSYNC信号会触发显示设备回到图像的顶部,准备开始显示下一个图像帧。其中HSYNC的每一个高电平代表一行
? ? ? ? 在RGB LCD显示屏上显示红黑绿蓝白的彩条。
????????对于不同分辨率的显示屏,需要不同的时钟来进行驱动,时钟频率=分辨率的宽度×分辨率的高度×每像素的位数×帧率。本次实验需要的时钟频率为50MHz,25MHz,12.5MHz。因此需要进行2分频和四分频。对于偶分频,设进行NUM_DIV倍分频,使用一个分频计数器div_cnt,若div_cnt<NUM_DIV / 2 - 1,则div_clk保持不变,否则div_clk = ~div_clk。
//时钟2分频 输出25MHz时钟
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
clk_25m <= 1'b0;
else
clk_25m <= ~clk_25m;
end
//时钟4分频 输出12.5MHz时钟
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
div_4_cnt <= 1'b0;
clk_12_5m <= 1'b0;
end
else begin
div_4_cnt <= div_4_cnt + 1'b1;
if(div_4_cnt == 1'b1)
clk_12_5m <= ~clk_12_5m;
end
end
????????本次实验使用5种不同分辨率的显示屏。480x272,800x480,1024x600,800x480,1280x800。
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
rd_flag <= 1'b0;
lcd_id <= 16'd0;
end
else begin
if(rd_flag == 1'b0) begin
rd_flag <= 1'b1;
case({lcd_rgb[4],lcd_rgb[10],lcd_rgb[15]})
3'b000 : lcd_id <= 16'h4342; //4.3' RGB LCD RES:480x272
3'b001 : lcd_id <= 16'h7084; //7' RGB LCD RES:800x480
3'b010 : lcd_id <= 16'h7016; //7' RGB LCD RES:1024x600
3'b100 : lcd_id <= 16'h4384; //4.3' RGB LCD RES:800x480
3'b101 : lcd_id <= 16'h1018; //10' RGB LCD RES:1280x800
default : lcd_id <=16'h0;
endcase
end
end
end
? ? ? ? 当像素值水平坐标pixel_xpos在水平分辨的第一个1/5内时显示一个颜色,第二个第三个第四个第五个1/5内显示另一个颜色。
//parameter define
parameter WHITE = 16'b11111_111111_11111; //白色
parameter BLACK = 16'b00000_000000_00000; //黑色
parameter RED = 16'b11111_000000_00000; //红色
parameter GREEN = 16'b00000_111111_00000; //绿色
parameter BLUE = 16'b00000_000000_11111; //蓝色
//根据当前像素点坐标指定当前像素点颜色数据,在屏幕上显示彩条
always @(posedge lcd_pclk or negedge rst_n) begin
if(!rst_n)
pixel_data <= BLACK;
else begin
if((pixel_xpos >= 11'd0) && (pixel_xpos < h_disp/5*1))
pixel_data <= WHITE;
else if((pixel_xpos >= h_disp/5*1) && (pixel_xpos < h_disp/5*2))
pixel_data <= BLACK;
else if((pixel_xpos >= h_disp/5*2) && (pixel_xpos < h_disp/5*3))
pixel_data <= RED;
else if((pixel_xpos >= h_disp/5*3) && (pixel_xpos < h_disp/5*4))
pixel_data <= GREEN;
else
pixel_data <= BLUE;
end
end
? ? ? ? 设水平扫描计数器为h_cnt ,垂直扫描计数器为v_cnt,则像素点坐标为:
//像素点坐标
assign pixel_xpos = data_req ? (h_cnt - (h_sync + h_back - 1'b1)) : 11'd0;
assign pixel_ypos = data_req ? (v_cnt - (v_sync + v_back - 1'b1)) : 11'd0;
//h_cnt为水平计数器,h_sync为行同步信号,h_back为行显示后沿
? ? ? ? 行场计数器的计数
//行计数器对像素时钟计数
always@ (posedge lcd_pclk or negedge rst_n) begin
if(!rst_n)
h_cnt <= 11'd0;
else begin
if(h_cnt == h_total - 1'b1)
h_cnt <= 11'd0;
else
h_cnt <= h_cnt + 1'b1;
end
end
//场计数器对行计数
always@ (posedge lcd_pclk or negedge rst_n) begin
if(!rst_n)
v_cnt <= 11'd0;
else begin
if(h_cnt == h_total - 1'b1) begin
if(v_cnt == v_total - 1'b1)
v_cnt <= 11'd0;
else
v_cnt <= v_cnt + 1'b1;
end
end
end
????????字模转换:字模转换指的是将字符的字模数据转换成实际的可显示的图像或矩阵,以便在屏幕上显示。
????????字符矩阵:是一种表示字符的方式,其中字符被划分为一个二维的矩阵,每个单元格代表一个像素或子元素。这个矩阵包含了字符在屏幕上的布局和外观信息。
? ? ? ? 对于RGB888这样的颜色显示,每个像素点都需要使用bits数据来表示颜色。通过程序扫描可以生成一个COE文件,他包含了每个像素点的rgb值。以下是一个简单的COE文件示例,表示一个3x3的图像,每个像素由RGB三个分量组成:
memory_initialization_radix=10;
memory_initialization_vector=
0 0 0,
255 0 0,
0 255 0,
0 0 255,
255 255 255,
128 128 128,
255 255 0,
0 255 255,
255 0 255;
memory_initialization_radix=10;
:表示使用十进制表示法。memory_initialization_vector=
:后面是具体的数据。在这个例子中,每个像素用逗号分隔,每个分量用空格分隔。????????时钟分频,读取ID,LCD驱动和彩条显示实验类似,主要是LCD显示模块有区别。
? ? ? ? 使用生成字模的软件PCtoLCD2002得到每个像素点的赋值(0或1),如下所示:
//给字符数组赋值,显示汉字“正点原子”,每个汉字大小为32*32
//128代表每一行有128个像素点(32×4),char位宽为32,代表有32行
always @(posedge lcd_pclk) begin
char[0 ] <= 128'h00000000000000000000000000000000;
char[1 ] <= 128'h00000000000000000000000000000000;
char[2 ] <= 128'h00000000000100000000002000000000;
char[3 ] <= 128'h000000100001800002000070000000C0;
char[4 ] <= 128'h000000380001800003FFFFF803FFFFE0;
char[5 ] <= 128'h07FFFFFC0001800003006000000001E0;
char[6 ] <= 128'h0000C000000180600300600000000300;
char[7 ] <= 128'h0000C0000001FFF00300C00000000600;
char[8 ] <= 128'h0000C000000180000310804000001800;
char[9 ] <= 128'h0000C00000018000031FFFE000003000;
char[10] <= 128'h0000C00000018000031800400001C000;
char[11] <= 128'h0000C00000018000031800400001C000;
char[12] <= 128'h00C0C000018181800318004000018000;
char[13] <= 128'h00C0C00001FFFFC0031FFFC000018010;
char[14] <= 128'h00C0C060018001800318004000018038;
char[15] <= 128'h00C0FFF001800180031800403FFFFFFC;
char[16] <= 128'h00C0C000018001800318004000018000;
char[17] <= 128'h00C0C000018001800218004000018000;
char[18] <= 128'h00C0C00001800180021FFFC000018000;
char[19] <= 128'h00C0C000018001800210304000018000;
char[20] <= 128'h00C0C00001FFFF800200300000018000;
char[21] <= 128'h00C0C000018001800606300000018000;
char[22] <= 128'h00C0C000018001000607370000018000;
char[23] <= 128'h00C0C00000000000060E31C000018000;
char[24] <= 128'h00C0C000001000400418307000018000;
char[25] <= 128'h00C0C000020830600430303800018000;
char[26] <= 128'h00C0C010020C18300860301800018000;
char[27] <= 128'h00C0C038060E18180883700800018000;
char[28] <= 128'h3FFFFFFC0C0618181100F008003F8000;
char[29] <= 128'h000000001C0408182000600000070000;
char[30] <= 128'h00000000000000000000000000020000;
char[31] <= 128'h00000000000000000000000000000000;
end
????????128代表每行有128个像素点,数组char位宽为32代表一共有32行,每8个像素点构成一个字节,使用两位16进制数来表示。
显示字符图片:
//为LCD不同显示区域绘制图片、字符和背景色
always @(posedge lcd_pclk or negedge rst_n) begin
if (!rst_n)
pixel_data <= BACK_COLOR;
else if( (pixel_xpos >= PIC_X_START) && (pixel_xpos < PIC_X_START + PIC_WIDTH)
&& (pixel_ypos >= PIC_Y_START) && (pixel_ypos < PIC_Y_START + PIC_HEIGHT) )
pixel_data <= rom_rd_data ; //显示图片
else if((pixel_xpos >= CHAR_X_START) && (pixel_xpos < CHAR_X_START + CHAR_WIDTH)
&& (pixel_ypos >= CHAR_Y_START) && (pixel_ypos < CHAR_Y_START + CHAR_HEIGHT)) begin
if(char[y_cnt][CHAR_WIDTH -1'b1 - x_cnt])
pixel_data <= CHAR_COLOR; //显示字符
else
pixel_data <= BACK_COLOR; //显示字符区域的背景色
end
else
pixel_data <= BACK_COLOR; //屏幕背景色
end
###本文参考正点原子视频,仅用于自己学习复习,如有侵权,请联系删除。