新起点开发板的颜色格式是RGB565格式,具体颜色效果可参考PC端的RGB888格式,可以打开word文档颜色,如下:
当前黄色是R是8‘d210,G是8d'210,B是8d'24;换成2进制各为:2’b11010010,2‘b11010010,2’b00011000;转化成RGB565,取R高5位,取G高6位,取B高5位,即R为2‘b11010,G为110100,B为00011;
知道上述知识,我们可以在RGB—LCD上刷出许多颜色。
如何驱动正点原子开发板的4.3 LCD屏网上给许多案例,主要有分频、lcd-id识别、lcd驱动、以及lcd显示四大模块组成。
LCD如何显示,看了正点原子的LCD硬件文档,他是先一行显示完再跳转到下一列的第一行,如显示频的分辨率是1920*1080,则要刷1920*1080个像素点。
LCD显示所需要的时间,个人感觉只要时钟跟数据量相近即可,或者是高于LCD硬件说明书的最低时钟速率。
如何确定数据量,看技术文档即可
这个两个技术文档图说明,LCD一行要多少像素点,一场要多少像素点,但我确实不知道行同步时钟要128个像素点时钟,开发文档说只要一个就可以。
结合上面的图,可以就算一帧要多少个像素时钟,比如采用的480*272,则为T=(41+2+480+2)*(10+2+272+2)*(刷新率),如果是固定显示一个画面,这个刷新率可随意,可默认为1,计算得到T=150150;这个次要范围要大于150150Hz,最终还是看技术文档规定的最小时钟。
下面管脚
LCD-RGB Top模块代码
module rgb(
input sys_clk, //系统时钟
input sys_rst_n, //系统复位
//RGB LCD接口
output lcd_de, //LCD 数据使能信号
output lcd_hs, //LCD 行同步信号
output lcd_vs, //LCD 场同步信号
output lcd_clk, //LCD 像素时钟
inout [15:0] lcd_rgb, //LCD RGB565颜色数据
output lcd_rst,
output lcd_bl
);
wire [15:0] lcd_id ; //LCD屏ID
wire lcd_pclk ; //LCD像素时钟
wire [10:0] pixel_xpos; //当前像素点横坐标
wire [10:0] pixel_ypos; //当前像素点纵坐标
wire [10:0] h_disp ; //LCD屏水平分辨率
wire [10:0] v_disp ; //LCD屏垂直分辨率
wire [15:0] pixel_data; //像素数据
wire [15:0] lcd_rgb_o ; //输出的像素数据
wire [15:0] lcd_rgb_i ; //输入的像素数据
//*****************************************************
//** main code
//*****************************************************
//像素数据方向切换
assign lcd_rgb = lcd_de ? lcd_rgb_o : 16'bz;
assign lcd_rgb_i = lcd_rgb;
//读LCD ID模块
rd_id u_rd_id(
.clk (sys_clk ),
.rst_n (sys_rst_n),
.lcd_rgb (lcd_rgb_i),
.lcd_id (lcd_id )
);
//时钟分频模块
clk_div u_clk_div(
.clk (sys_clk ),
.rst_n (sys_rst_n),
.lcd_id (lcd_id ),
.lcd_pclk (lcd_pclk )
);
//LCD显示模块
lcd_display u_lcd_display(
.lcd_pclk (lcd_pclk ),
.rst_n (sys_rst_n ),
.lcd_en (lcd_de ),
.pixel_xpos (pixel_xpos),
.pixel_ypos (pixel_ypos),
.h_disp (h_disp ),
.v_disp (v_disp ),
.pixel_data (pixel_data)
);
//LCD驱动模块
lcd_driver u_lcd_driver(
.lcd_pclk (lcd_pclk ),
.rst_n (sys_rst_n ),
.lcd_id (lcd_id ),
.pixel_data (pixel_data),
.pixel_xpos (pixel_xpos),
.pixel_ypos (pixel_ypos),
.h_disp (h_disp ),
.v_disp (v_disp ),
.lcd_de (lcd_de ),
.lcd_hs (lcd_hs ),
.lcd_vs (lcd_vs ),
.lcd_clk (lcd_clk ),
.lcd_rgb (lcd_rgb_o ),
.lcd_rst (lcd_rst ),
.lcd_bl (lcd_bl)
);
endmodule
本次采用Ip-core pll—clk 分频,可以分任意想要的时钟频率
module clk_div(
input clk, //50Mhz
input rst_n,
input [15:0] lcd_id,
output reg lcd_pclk
);
wire locked;
pll_clk u_pll_clk (
.areset (sys_rst_n),
.inclk0 (clk),
.c0 (clk25m),
.c1 (clk13m),
.c2 (clk34m),
.locked (locked)
);
always @(*) begin
case(lcd_id)
16'h4342 : lcd_pclk = clk13m;
16'h7084 : lcd_pclk = clk25m;
16'h7016 : lcd_pclk = clk;
16'h4384 : lcd_pclk = clk34m;
16'h1018 : lcd_pclk = clk;
default : lcd_pclk = 0;
endcase
end
endmodule
显示驱动部分
module lcd_driver(
input lcd_pclk, //时钟
input rst_n, //复位,低电平有效
input [15:0] lcd_id, //LCD屏ID
input [15:0] pixel_data, //像素数据
output [10:0] pixel_xpos, //当前像素点横坐标
output [10:0] pixel_ypos, //当前像素点纵坐标
output reg [10:0] h_disp, //LCD屏水平分辨率
output reg [10:0] v_disp, //LCD屏垂直分辨率
//RGB LCD接口
output lcd_de, //LCD 数据使能信号
output lcd_hs, //LCD 行同步信号
output lcd_vs, //LCD 场同步信号
output lcd_bl, //LCD 背光控制信号 高电平有效
output lcd_clk, //LCD 像素时钟
output [15:0] lcd_rgb, //LCD RGB565颜色数据
output lcd_rst //LCD 复位,低电平有效
);
//parameter define
// 4.3' 480*272
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 define
reg [10:0] h_sync ;
reg [10:0] h_back ;
reg [10:0] h_total;
reg [10:0] v_sync ;
reg [10:0] v_back ;
reg [10:0] v_total;
reg [10:0] h_cnt ;
reg [10:0] v_cnt ;
//wire define
wire lcd_en;
wire data_req;
//*****************************************************
//** main code
//*****************************************************
//RGB LCD 采用DE模式时,行场同步信号需要拉高
assign lcd_hs = 1'b1; //LCD行同步信号
assign lcd_vs = 1'b1; //LCD场同步信号
assign lcd_clk = lcd_pclk; //LCD像素时钟
assign lcd_de = lcd_en; //LCD数据有效信号
//使能RGB565数据输出
assign lcd_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))
? 1'b1 : 1'b0;
//请求像素点颜色数据输入
assign data_req = ((h_cnt >= h_sync + h_back - 1'b1) && (h_cnt < h_sync + h_back + h_disp - 1'b1)
&& (v_cnt >= v_sync + v_back) && (v_cnt < v_sync + v_back + v_disp))
? 1'b1 : 1'b0;
//背光复位
assign lcd_rst = (rst_n == 1'b0) ? 1'b0 : 1'b1;
assign lcd_bl = (rst_n == 1'b0) ? 1'b0 : 1'b1;
//像素点坐标
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;
//RGB565数据输出
assign lcd_rgb = lcd_en ? pixel_data : 16'd0;
//行场时序参数
always @(posedge lcd_pclk) 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 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
endmodule
LCD-id识别
lcd——id识别 (个人感受,你买的Lcd屏有型号,直接赋值就行了,嫌代码多的可直接不要)
module rd_id(
input clk , //时钟
input rst_n , //复位,低电平有效
input [15:0] lcd_rgb, //RGB LCD像素数据,用于读取ID
output reg [15:0] lcd_id //LCD屏ID
);
//reg define
reg rd_flag; //读ID标志
//*****************************************************
//** main code
//*****************************************************
//获取LCD ID M2:B4 M1:G5 M0:R4
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
endmodule
LCD 显示
module lcd_display(
input lcd_pclk, //时钟
input rst_n, //复位,低电平有效
input [10:0] pixel_xpos, //当前像素点横坐标
input [10:0] pixel_ypos, //当前像素点纵坐标
input [10:0] h_disp, //LCD屏水平分辨率
input [10:0] v_disp, //LCD屏垂直分辨率
input lcd_en,
output reg [15:0] pixel_data //像素数据
);
//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; //蓝色
parameter YELLOW = 16'b11110_111100_00110; //黄色
//
reg[15:0] state_now;
reg[15:0] state_next;
reg[11:0] h_cnt;
reg[15:0] v_cnt;
wire en;
//
//assign en = (v_cnt == 12'd524) ? 1'b1 : 1'b0;
//刷屏
always@(posedge lcd_pclk or negedge rst_n)
begin
if(!rst_n)
h_cnt<=12'd0;
else if(h_cnt<12'd1055)
h_cnt<=h_cnt + 1'b1;
else if(v_cnt==12'd1055)
h_cnt<=12'd0;
else
h_cnt<=12'd0;
end
always@ (posedge lcd_pclk or negedge rst_n)
begin
if(!rst_n)
v_cnt <= 11'd0;
else begin
if(h_cnt == 12'd1055) begin
if(v_cnt == 16'd32228)
begin
v_cnt <= 16'd0;
state_now <= state_next;
end
else
v_cnt <= v_cnt + 1'b1;
end
end
end
always@(*)
begin
case (state_now)
WHITE :
state_next <= BLACK;
BLACK :
state_next <= RED;
RED :
state_next <= GREEN;
GREEN :
state_next <= BLUE;
BLUE :
state_next <= YELLOW ;
default: state_next <= RED;
endcase
end
always@(*)
begin
if(lcd_en)
pixel_data <= state_now;
else
pixel_data <= pixel_data;
end
//根据当前像素点坐标指定当前像素点颜色数据,在屏幕上显示彩条
//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 <= YELLOW;
// 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
endmodule
结果演示
RGB-LCD