TA的每日心情 | 开心 2019-11-19 11:07 |
---|
签到天数: 226 天 连续签到: 1 天 [LV.7]常住居民III
|
【MAXII_EPM240T100_CPLD】实验七 LCD1602显示屏驱动
有实验六的基础,已知道板载连接LCD1602或LCD128X64显示屏的插座,就可以开展LCD屏的驱显。经过几番实验,最好总算成功了。看来这个芯片的资源有限,想制作一个稍大点的东西,内部的cels就不够了,最后折中显示固定码为好。因为1602 自带ASCII码,不需要自己编点阵码,这样就简单了一点。
创建项目,名称为lcd162。过程免了,代码如下。
module lcd162(clk,rst,LCD_E,LCD_RW,LCD_RS,LCD_D);
input clk,rst;
output LCD_E,LCD_RW,LCD_RS;
output [7:0]LCD_D;
reg LCD_E,LCD_RW,LCD_RS;
reg [7:0]LCD_D;
reg [9:0]state;
reg [5:0]address;
parameter IDLE=10'b0000000000;
parameter CLEAR=10'b0000000001;//清屏
parameter RETURNCURSOR=10'b0000000010;//归home位
parameter SETMODE=10'b0000000111;//输入方式设置
parameter SWITCHMODE=10'b0000001111;//显示状态设置
parameter SHIFT=10'b0000011100;//光标画面滚动
parameter SETFUNCTION=10'b0000111100;//工作方式设置1:8/0:4位数据接口
parameter SETCGRAM=10'b0001000000;//设置CGRA
parameter SETDDRAM1=10'b0010000001;//设置DDRAM
parameter SETDDRAM2=10'b0010000010;//设置DDRAM
parameter READFLAG=10'b0100000000;//读状态
parameter WRITERAM1=10'b1000000001;//写RAM
parameter WRITERAM2=10'b1000000010;//写RAM
parameter READRAM=10'b1100000000;//读RAM
parameter cur_inc =1;
parameter cur_dec =0;
parameter cur_shift =1;
parameter cur_noshift =0;
parameter open_display =1;
parameter open_cur =0;
parameter blank_cur =0;
parameter shift_display=1;
parameter shift_cur =0;
parameter right_shift =1;
parameter left_shift =0;
parameter LCD_Dwidth8 =1;
parameter LCD_Dwidth4 =0;
parameter twoline =1;
parameter oneline =0;
parameter font5x10 =1;
parameter font5x7 =0;
//
function [7:0] ddram;//写入ASCII字符数据
input [5:0] n;
begin
case(n)
0:ddram=8'h57;//W
1:ddram=8'h65;//e
2:ddram=8'h6c;//l
3:ddram=8'h63;//c
4:ddram=8'h6f;//o
5:ddram=8'h6d;//m
6:ddram=8'h65;//e
7:ddram=8'hA0;//space
8:ddram=8'h74;//t
9:ddram=8'h6f;//o
10:ddram=8'hA0;//space
11:ddram=8'h6d;//m
12:ddram=8'h79;//y
13:ddram=8'h77;//w
14:ddram=8'h79;//y
15:ddram=8'h64;//d
16:ddram=8'hA0;//space
17:ddram=8'h77;//w
18:ddram=8'h77;//w
19:ddram=8'h77;//w
20:ddram=8'h2E;//.
21:ddram=8'h7A;//z
22:ddram=8'h68;//h
23:ddram=8'h6A;//j
24:ddram=8'h62;//b
25:ddram=8'h2E;//.
26:ddram=8'h6E;//n
27:ddram=8'h65;//e
28:ddram=8'h74;//t
29:ddram=8'h21;//!
30:ddram=8'hA0;//space
31:ddram=8'hA0;//space
default:ddram=8'hxx;
endcase
end
endfunction
//分频模块
reg [16:0] clkcnt;
reg clkdiv;
always @ (posedge clk)
if(!rst)
clkcnt<=17'b0_0000_0000_0000_0000;
else
begin
if(clkcnt<17'b0_1001_1100_0100_0000) //17'b0_1001_1100_0100_0000
begin
clkcnt<=clkcnt+1;
clkdiv<=0;
end
else if(clkcnt==17'b1_1000_0110_1010_0000)//17'b1_0011_1000_0111_1111
clkcnt<=17'b0_0000_0000_0000_0000;
else
begin
clkcnt<=clkcnt+1;
clkdiv<=1;
end
end
reg clk_int;
//原为clkdiv
always @ (posedge clkdiv or negedge rst)
if(!rst)
clk_int<=0;
else
clk_int<=~clk_int;
//显示允许
always @ (negedge clkdiv or negedge rst) // T 为clkdiv的2倍,100000个clk: 500Hz,2ms
if(!rst)
LCD_E<=0;
else
LCD_E<=~LCD_E;
//LCD初始化和显示,由状态机控制->state
always @ (posedge clk_int or negedge rst)
if(!rst)
begin
state<=IDLE;
address<=6'b000000;
LCD_D<=8'b00000000;
LCD_RS<=0;
LCD_RW<=0;
end
else
begin
case(state)
IDLE:
begin
LCD_D<=8'bzzzz_zzzz;
state<=CLEAR;
end
CLEAR:
begin
LCD_RS<=0;
LCD_RW<=0;
LCD_D<=8'b0000_0001;//清屏01
state<=SETFUNCTION;
end
SETFUNCTION:
begin
LCD_RS<=0;
LCD_RW<=0;
LCD_D[7:5]<=3'b001;//功能设置3C
LCD_D[4]<=LCD_Dwidth8;
LCD_D[3]<=twoline;
LCD_D[2]<=font5x10;
LCD_D[1:0]<=2'b00;
state<=SWITCHMODE;
end
SWITCHMODE:
begin
LCD_RS<=0;
LCD_RW<=0;
LCD_D[7:3]<=5'b00001;//显示状态开关设置0C
LCD_D[2]<=open_display;
LCD_D[1]<=open_cur;
LCD_D[0]<=blank_cur;
state<=SETMODE;end
SETMODE:
begin
LCD_RS<=0;
LCD_RW<=0;
LCD_D[7:2]<=6'b000001;//输入方式设置06
LCD_D[1]<=cur_inc;
LCD_D[0]<=cur_noshift;
state<=SHIFT;
end
SHIFT:
begin
LCD_RS<=0;
LCD_RW<=0;
LCD_D[7:4]<=4'b0001;//光标画面滚动
LCD_D[3]<=shift_cur;
LCD_D[2]<=left_shift;
LCD_D[1:0]<=2'b00;
state<=SETDDRAM1;
end
SETDDRAM1:
begin
LCD_RS<=0;
LCD_RW<=0;
LCD_D<=8'b10000000;//显示数据存储器地址80
state<=WRITERAM1;
end
SETDDRAM2:
begin
LCD_RS<=0;
LCD_RW<=0;
LCD_D<=8'b11000000;//显示数据存储器地址80+40
state<=WRITERAM2;
end
WRITERAM1:
begin//写第一行数据
if(address<=15)
begin
LCD_RS<=1;
LCD_RW<=0;
LCD_D<=ddram(address);
address<=address+1;
state<=WRITERAM1;
end
else
begin
LCD_RS<=0;
LCD_RW<=0;
state<=SETDDRAM2;
end
end
WRITERAM2:
begin//写第二行数据
if(address<=31)
begin
LCD_RS<=1;
LCD_RW<=0;
LCD_D<=ddram(address);
address<=address+1;
state<=WRITERAM2;
end
else
begin
LCD_RS<=0;
LCD_RW<=0;
state<=SHIFT;
address<=6'b000000;
end
end
endcase
end
endmodule
管脚绑定见图71,
管脚绑定,一共8Data+3控制+2系统时钟和复位
运行结果见照片72。
实际显示结果,还是不错的。
至此整个实验经历了从去年申请实验样板得到之后,前后翻阅资料、网上学习、看书直到节后初有眉目开始找到压箱底的DIY的板子,开始在Quartus II上倒腾了一番,尽管只是初级实验,但对CPLD-FPGA初入门的来说,是很不容易的一件事,因为与单片机、ARM芯片相比,两者完全不一样。实验暂告一段落,休整一下再继续。谢谢看过和关心过的所有网友。许多代码都是照搬的,因为她的语法现象只能说还是门外汉,但以后会从简单的开始逐步向较难的进军的。FPGA,我已经喜欢上了你! |
|