睿酷研发-助学板上实现的液晶刷屏程序
睿酷研发-助学板上实现的液晶刷屏程序
时间:2020年8月21~23日
开发板型号:睿智FPGA开发板ALTERA IV EP4CE四代
液晶屏型号:3.5' 320X480 LCD MODULE
液晶屏驱动:ILI9481
液晶屏接口:8080
源码如下:
/******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
- File Name : ILI9481_320X480.v
- Author : 驱动开发小组
- Version : V1.0.0
- Date : 8/23/2018
- Description : 3.5寸液晶屏模块FPGA驱动.
- 屏幕尺寸 :3.5英寸
- 分辨率 :320 X 480
- 颜色深度 :262k
- 驱动型号 :ILI9481,IC分辨率320*480
- 接口类型 :8080接口
*******************************************************************************/
module ILI9481_320X480(RSTn,clk,LCD_DB,LCD_CS,LCD_WR,LCD_RS,test,state_lcd_write,LCD_RESET,LCD_DATA_TEMP_17);
input clk;
input RSTn;
output [15:0] LCD_DB;
output LCD_CS; //液晶屏选择
output LCD_WR; //写命令
output LCD_RS; //1:数据/0:命令
output test; //测试引脚
output LCD_RESET; //复位引脚
output [3:0] state_lcd_write;//写的状态
output LCD_DATA_TEMP_17; //也是用于测试位,将此信号接到FPGA引脚上
reg [15:0] LCD_DB;
reg LCD_CS;
reg LCD_WR;
reg LCD_RS;
reg LCD_RESET;
reg test;
//内部寄存器
reg [3:0] state_lcd_write;//写的状态
reg [16:0] LCD_DATA_TEMP; //数据缓存
reg [7:0] addr_command; //地址命令
reg [31:0] count_dot; //显示的点数
reg [15:0] count_delay; //延时时钟周期
assign LCD_DATA_TEMP_17=LCD_DATA_TEMP[16];
//将时钟信号分频之后
always @(posedge clk)
LCD_RESET<=1'b1;
//测试代码
always @(posedge clk)
test<=~test;
always @(posedge clk)
if(!RSTn) //复位,各个状态初始化
begin
state_lcd_write <= 4'd0;//0状态
LCD_CS <= 1'b1; //未选中液晶屏
LCD_WR <= 1'b1; //写入不使能
LCD_RS <= 1'b0; //0表示命令读写
LCD_DB <= 16'd0; //总线上数据清零
addr_command <= 8'd0; //初始化命令为零
LCD_DATA_TEMP <= 17'd0; //数据缓存清零
count_dot <= 16'd0; //写屏点数清零
count_delay <= 16'd0; //延时是时钟数初始化
end
else
begin
case(state_lcd_write)//LCD的各个状态
4'd0: //初始化状态
if(count_delay == 16'd2499) //init delay,初始化延时50ms
begin
state_lcd_write <= 4'd1;
count_delay <= 16'd0; //到下一个状态延时清零
end
else
begin
state_lcd_write <= 4'd0; //在50ms内每次回到原状态
count_delay <= count_delay + 1'b1;
end
4'd1: //开始执行Function中的命令
begin
state_lcd_write <= 4'd2;//更改状态
LCD_CS <= 1'b1;
LCD_WR <= 1'b1;
LCD_DATA_TEMP<=display_command(addr_command);
count_delay <= 16'd0; //延时清零
count_delay <= count_delay + 1'b1;
end
4'd2:
if(LCD_DATA_TEMP[16])//data写数据
begin
state_lcd_write <= state_lcd_write + 1'b1;//状态变换
LCD_CS <= 1'b0;
LCD_RS <= 1'b1; //写数据
LCD_WR <= 1'b0;
LCD_DB <= LCD_DATA_TEMP[15:0];
end
else //command写命令
begin
state_lcd_write <= state_lcd_write + 1'b1;//状态变换
LCD_CS <= 1'b0;
LCD_RS <= 1'b0; //写命令
LCD_WR <= 1'b0;
LCD_DB<= LCD_DATA_TEMP[15:0];
end
4'd3:
begin
state_lcd_write <= state_lcd_write + 1'b1;//状态变换,相当于等待一个周期,20ns
end
4'd4:
begin
state_lcd_write <= state_lcd_write + 1'b1;//状态变换
LCD_CS <= 1'b1; //液晶屏不选中
end
4'd5:
begin
state_lcd_write <= state_lcd_write + 1'b1;//状态变换
LCD_WR <= 1'b1; //WR置高
end
4'd6:
if(addr_command == 8'd49)//如果当前命令为第48条命令,显示颜色为红色这条
begin
count_dot <= count_dot + 1'b1;//显示的点加1
state_lcd_write <= 4'd1; //置下一状态为1状态
if(count_dot == 32'd76800) //显示液晶屏的一半,就更换颜色显示
begin
addr_command <= 8'd50; //换颜色
count_dot <= 32'd1; //显示颜色变换,将显示的颜色点数重新计数
end
else
state_lcd_write <= 4'd1; //取数的状态
end
else if(addr_command == 8'd50) //white
begin
count_dot <= count_dot + 1'b1;
state_lcd_write <= 4'd1;
if(count_dot == 32'd76800) //显示液晶屏的一半,就更换颜色显示
begin
addr_command <= 8'd49; //换颜色
count_dot <= 32'd0; //显示颜色变换,将显示的颜色点数重新计数
end
else
state_lcd_write <= 4'd1;
end
else
begin
addr_command <= addr_command + 1'b1;
state_lcd_write <= 4'd0;
end
4'd7:
state_lcd_write <= 4'd7;
endcase
end
//返回一个值
function [16:0] display_command;
input [7:0] addr;//端口说明语句
begin
case (addr)
8'd0:display_command = {1'b0,16'h0011};
//需要延时120ms
8'd1:display_command = {1'b0,16'h00D0};//写寄存器
8'd2:display_command = {1'b1,16'h0007};//写命令
8'd3:display_command = {1'b1,16'h0042};
8'd4:display_command = {1'b1,16'h0018};
8'd5:display_command = {1'b0,16'h00D1};
8'd6:display_command = {1'b1,16'h0000};
8'd7:display_command = {1'b1,16'h0007};
8'd8:display_command = {1'b1,16'h0010};
8'd9:display_command = {1'b0,16'h00D2};
8'd10:display_command = {1'b1,16'h0001};
8'd11:display_command = {1'b1,16'h0002};
8'd12:display_command = {1'b0,16'h00C0};
8'd13:display_command = {1'b1,16'h0010};
8'd14:display_command = {1'b1,16'h003B};
8'd15:display_command = {1'b1,16'h0000};
8'd16:display_command = {1'b1,16'h0002};
8'd17:display_command = {1'b1,16'h0011};
8'd18:display_command = {1'b0,16'h00C5};
8'd19:display_command = {1'b1,16'h0003};//set display control mode
8'd20:display_command = {1'b0,16'h00C8};
8'd21:display_command = {1'b1,16'h0000};
8'd22:display_command = {1'b1,16'h0032};
8'd23:display_command = {1'b1,16'h0036};
8'd24:display_command = {1'b1,16'h0045};
8'd25:display_command = {1'b1,16'h0006};
8'd26:display_command = {1'b1,16'h0016};
8'd27:display_command = {1'b1,16'h0037};
8'd28:display_command = {1'b1,16'h0075};
8'd29:display_command = {1'b1,16'h0077};
8'd30:display_command = {1'b1,16'h0054};
8'd31:display_command = {1'b1,16'h000C};
8'd32:display_command = {1'b1,16'h0000};
8'd33:display_command = {1'b0,16'h0036};
8'd34:display_command = {1'b1,16'h000A};
8'd35:display_command = {1'b0,16'h003A};
8'd36:display_command = {1'b1,16'h0055};
8'd37:display_command = {1'b0,16'h002A};
8'd38:display_command = {1'b1,16'h0000};
8'd39:display_command = {1'b1,16'h0000};
8'd40:display_command = {1'b1,16'h0001};
8'd41:display_command = {1'b1,16'h003F};
8'd42:display_command = {1'b0,16'h002B};
8'd43:display_command = {1'b1,16'h0000};
8'd44:display_command = {1'b1,16'h0000};
8'd45:display_command = {1'b1,16'h0001};
8'd46:display_command = {1'b1,16'h00E0};
//需要延时 120ms
8'd47:display_command = {1'b0,16'h0029};//horizontal ram address
8'd48:display_command = {1'b0,16'h002c};
8'd49:display_command = {1'b1,16'hF800};//显示为红色的数据
8'd50:display_command = {1'b1,16'hFFFF};//显示为白色的数据
default:display_command = {1'b0,16'h0000};
endcase
end
endfunction
endmodule
状态机如下图所示
代码参考: