【国产FPGA高云GW1N-4系列开发板测评】——11、点个LCD1602屏
本帖最后由 gs001588 于 2022-1-20 20:55 编辑<p><span style="font-size:16px;"><span style="font-family:宋体;"> 【国产FPGA高云GW1N-4系列开发板测评】——11、点个LCD1602屏</span></span></p>
<p><span style="font-size:16px;"><span style="font-family:宋体;"> </span></span></p>
<p><span style="font-size:16px;"><span style="font-family:宋体;"> 之前用在FPGA上写过12864带字库屏的显示应用,间隔时间比较长了,之前备份的资料暂时没有找到。手头正好有LCD1602的LCD屏,不妨先拿LCD1602来做个显示实验。LCD1602作为一款经典的LCD屏,在各种学习平台上的应用自然是少不了的,在FPGA上也不例外。</span></span></p>
<p><span style="font-size:16px;"><span style="font-family:宋体;"> 本着拿来主义的想法,参考网友资料,做了适当修改。原本打算做成显存方式模块,对外接口为异步RAM方式,模块内部完成LCD初始化,有新显存数据后自动显示刷新操作。这样就需要写顶层文件,需要提供变化的数据源,把问题复杂化,因此可作为之后的改进实验。本贴先显示一下LCD1602。</span></span></p>
<p><span style="font-size:16px;"><span style="font-family:宋体;"> 参考网址(<a href="https://blog.csdn.net/qq_33231534/article/details/108484995" target="_blank">基于FPGA的LCD1602显示屏驱动 https://blog.csdn.net/qq_33231534/article/details/108484995</a>)</span></span></p>
<p> </p>
<p><span style="font-size:16px;"><span style="font-family:宋体;"> 本实验使用到的FPGA管脚资源配置如下:<br />
</span></span></p>
<p> </p>
<p><span style="font-size:16px;"><span style="font-family:宋体;"> GWIN-4B与LCD1602屏之间对应关系接线表:</span></span></p>
<table align="center" border="1" cellpadding="1" cellspacing="1">
<tbody>
<tr>
<td><span style="font-size:16px;"><span style="font-family:宋体;">LCD1602</span></span></td>
<td><span style="font-size:16px;"><span style="font-family:宋体;">功能说明</span></span></td>
<td><span style="font-size:16px;"><span style="font-family:宋体;">GWIN-4B</span></span></td>
</tr>
<tr>
<td><span style="font-size:16px;"><span style="font-family:宋体;">1、VCC</span></span></td>
<td><span style="font-size:16px;"><span style="font-family:宋体;">电源地</span></span></td>
<td><span style="font-size:16px;"><span style="font-family:宋体;">JP7.2-5V</span></span></td>
</tr>
<tr>
<td><span style="font-size:16px;"><span style="font-family:宋体;">2、GND</span></span></td>
<td><span style="font-size:16px;"><span style="font-family:宋体;">电源正极</span></span></td>
<td><span style="font-size:16px;"><span style="font-family:宋体;">J19.1-GND</span></span></td>
</tr>
<tr>
<td rowspan="1">
<p><span style="font-size:16px;"><span style="font-family:宋体;">3、V0(接5.1K到GND)</span></span></p>
</td>
<td rowspan="1"><span style="font-size:16px;"><span style="font-family:宋体;">液晶显示偏压</span></span></td>
<td rowspan="1"> </td>
</tr>
<tr>
<td><span style="font-size:16px;"><span style="font-family:宋体;">4、RS</span></span></td>
<td><span style="font-size:16px;"><span style="font-family:宋体;">命令/数据选择</span></span></td>
<td><span style="font-size:16px;"><span style="font-family:宋体;">J4.1-32</span></span></td>
</tr>
<tr>
<td><span style="font-size:16px;"><span style="font-family:宋体;">5、RW</span></span></td>
<td><span style="font-size:16px;"><span style="font-family:宋体;">读/写选择</span></span></td>
<td><span style="font-size:16px;"><span style="font-family:宋体;">J4.2-34</span></span></td>
</tr>
<tr>
<td><span style="font-size:16px;"><span style="font-family:宋体;">6、EN</span></span></td>
<td><span style="font-size:16px;"><span style="font-family:宋体;">使能信号</span></span></td>
<td><span style="font-size:16px;"><span style="font-family:宋体;">J4.3-38</span></span></td>
</tr>
<tr>
<td><span style="font-size:16px;"><span style="font-family:宋体;">7、DATA0</span></span></td>
<td><span style="font-size:16px;"><span style="font-family:宋体;">数据0</span></span></td>
<td><span style="font-size:16px;"><span style="font-family:宋体;">J4.4-39</span></span></td>
</tr>
<tr>
<td>
<p><span style="font-size:16px;"><span style="font-family:宋体;">8、DATA1</span></span></p>
</td>
<td><span style="font-size:16px;"><span style="font-family:宋体;">数据1</span></span></td>
<td><span style="font-size:16px;"><span style="font-family:宋体;">J4.5-40</span></span></td>
</tr>
<tr>
<td><span style="font-size:16px;"><span style="font-family:宋体;">9、DATA2</span></span></td>
<td><span style="font-size:16px;"><span style="font-family:宋体;">数据2</span></span></td>
<td><span style="font-size:16px;"><span style="font-family:宋体;">J4.6-41</span></span></td>
</tr>
<tr>
<td><span style="font-size:16px;"><span style="font-family:宋体;">10、DATA3</span></span></td>
<td><span style="font-size:16px;"><span style="font-family:宋体;">数据3</span></span></td>
<td><span style="font-size:16px;"><span style="font-family:宋体;">J4.7-42</span></span></td>
</tr>
<tr>
<td><span style="font-size:16px;"><span style="font-family:宋体;">11、DATA4</span></span></td>
<td><span style="font-size:16px;"><span style="font-family:宋体;">数据4</span></span></td>
<td><span style="font-size:16px;"><span style="font-family:宋体;">J4.8-43</span></span></td>
</tr>
<tr>
<td><span style="font-size:16px;"><span style="font-family:宋体;">12、DATA5</span></span></td>
<td><span style="font-size:16px;"><span style="font-family:宋体;">数据5</span></span></td>
<td><span style="font-size:16px;"><span style="font-family:宋体;">J4.9-44</span></span></td>
</tr>
<tr>
<td>
<p><span style="font-size:16px;"><span style="font-family:宋体;">13、DATA6</span></span></p>
</td>
<td><span style="font-size:16px;"><span style="font-family:宋体;">数据6</span></span></td>
<td><span style="font-size:16px;"><span style="font-family:宋体;">J4.10-45</span></span></td>
</tr>
<tr>
<td><span style="font-size:16px;"><span style="font-family:宋体;">14、DATA7</span></span></td>
<td><span style="font-size:16px;"><span style="font-family:宋体;">数据7</span></span></td>
<td><span style="font-size:16px;"><span style="font-family:宋体;">J4.11-46</span></span></td>
</tr>
<tr>
<td><span style="font-size:16px;"><span style="font-family:宋体;">15、A(5V)</span></span></td>
<td><span style="font-size:16px;"><span style="font-family:宋体;">背光正极</span></span></td>
<td><span style="font-size:16px;"><span style="font-family:宋体;">JP7.1-5V</span></span></td>
</tr>
<tr>
<td><span style="font-size:16px;"><span style="font-family:宋体;">16、K(GND)</span></span></td>
<td><span style="font-size:16px;"><span style="font-family:宋体;">背光负极</span></span></td>
<td><span style="font-size:16px;"><span style="font-family:宋体;">J19.16-GND</span></span></td>
</tr>
</tbody>
</table>
<p> </p>
<p><span style="font-size:16px;"><span style="font-family:宋体;"> LCD1602的1、3脚之间并个5.1K直插电阻,为3脚的液晶显示偏置电压V0提供参考。一般开发板上使用的话会在1、3脚之间接个10K的电位器来调节电压,为啥是5.1K?之前修过一块开发板,在板上3脚接到GND了,导致普通LCD1602不能显示。查询LCD1602数据手册,此管脚V0为液晶显示偏压,接地时对比度最高,对比度过高时会产生“鬼影”,显示发黑不易区分正常显示与底色;接正电源电压时对比度最弱,显示发白几乎看不见。接个5K左右的电阻即可正常显示,电阻不需要精确4到6K都可以。</span></span></p>
<p><span style="font-size:16px;"><span style="font-family:宋体;"></span></span></p>
<p> </p>
<p><span style="font-size:16px;"><span style="font-family:宋体;"> 正好JP7有两针5V引出,其中一个给LCD逻辑供电,另一个给背光正极供电;GND比较多,随意选了两个,一个作为电源地,另一个作为背光负极。</span></span></p>
<p><span style="font-size:16px;"><span style="font-family:宋体;"></span></span></p>
<p> </p>
<p><span style="font-size:16px;"><span style="font-family:宋体;"> 剩余11条数据线分别一一对应接到JP14的1到11脚。</span></span></p>
<p><span style="font-size:16px;"><span style="font-family:宋体;"></span></span></p>
<p> </p>
<p><span style="font-size:16px;"><span style="font-family:宋体;"> 逻辑代码见下。具体功能及LCD1602相关寄存器功能等可以参考上面的“参考网址”中相关内容。</span></span></p>
<pre>
<code>module lcd(
input clk ,
input rst_n ,
output reg lcd_rs ,
output wire lcd_rw ,
output reg lcd_en ,
output reg lcd_data
);
reg cnt ;
reg state_c ;
reg state_n ;
reg char_cnt ;
reg data_display ;
localparam
IDLE = 4'd0 ,
INIT = 4'd1 ,
S0 = 4'd2 ,
S1 = 4'd3 ,
S2 = 4'd4 ,
S3 = 4'd5 ,
ROW1_ADDR = 4'd6 ,
WRITE = 4'd7 ,
ROW2_ADDR = 4'd8 ,
stop = 4'd9 ;
reg disp_memory ;
reg disp_cnt;
assign lcd_rw = 1'b0;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt <= 17'd0;
end
else begin
if (cnt==17'd100_000 - 1) begin
cnt <= 17'd0;
end
else begin
cnt <= cnt + 1'b1;
end
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
lcd_en <= 0;
end
else if (cnt==17'd50_000 - 1) begin
lcd_en <= 1;
end
else if (cnt==17'd100_000 - 1) begin
lcd_en <= 0;
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
char_cnt <= 0;
end
else if (state_c==WRITE && cnt==17'd50_000 - 1) begin
if (char_cnt==5'd31) begin
char_cnt <= 5'd0;
end
else begin
char_cnt <= char_cnt + 1'b1;
end
end
end
integer i;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
for(i=0;i<32;i=i+1)
begin
case(i)
5'd0: data_display = "W";
5'd1: data_display = "e";
5'd2: data_display = "l";
5'd3: data_display = "c";
5'd4: data_display = "o";
5'd5: data_display = "m";
5'd6: data_display = "e";
5'd7: data_display = " ";
5'd8: data_display = "t";
5'd9: data_display = "o";
5'd10: data_display= " ";
5'd11: data_display= "G";
5'd12: data_display= "O";
5'd13: data_display= "W";
5'd14: data_display= "I";
5'd15: data_display= "N";
5'd16: data_display= "M";
5'd17: data_display= "i";
5'd18: data_display= "n";
5'd19: data_display= "i";
5'd20: data_display= " ";
5'd21: data_display= "K";
5'd22: data_display= "i";
5'd23: data_display= "T";
5'd24: data_display= " ";
5'd25: data_display= "G";
5'd26: data_display= "W";
5'd27: data_display= "I";
5'd28: data_display= "N";
5'd29: data_display= "-";
5'd30: data_display= "4";
5'd31: data_display= "B";
default:data_display = "P";
endcase
disp_memory = data_display;
end
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
state_c <= IDLE;
end
else if(cnt==17'd50_000 - 1) begin
state_c <= state_n;
end
end
reg cnt_15ms;
reg flag ;
always@(posedge clk or negedge rst_n)begin
if (!rst_n) begin
cnt_15ms <= 0;
end
else if (state_c == IDLE) begin
cnt_15ms <= cnt_15ms + 1'b1;
end
end
always@(posedge clk or negedge rst_n)begin
if (!rst_n) begin
flag <= 0;
end
else if (state_c==IDLE && cnt_15ms==20'd750000) begin
flag <= 1;
end
end
always @(*) begin
case(state_c)
IDLE :
begin
if (flag) begin
state_n = INIT;
end
else begin
state_n = state_c;
end
end
INIT :
begin
state_n = S0;
end
S0 :
begin
state_n = S1;
end
S1 :
begin
state_n = S2;
end
S2 :
begin
state_n = S3;
end
S3 :
begin
state_n = ROW1_ADDR;
end
ROW1_ADDR:
begin
state_n = WRITE;
end
WRITE :
begin
if (char_cnt==5'd15) begin
state_n = ROW2_ADDR;
end
else if (char_cnt==5'd31) begin
state_n = stop;
end
else begin
state_n = state_c;
end
end
ROW2_ADDR:
begin
state_n = WRITE;
end
stop :
begin
state_n = stop;
end
default:state_n = IDLE;
endcase
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
lcd_data <= 8'd0;
end
else begin
case(state_c)
IDLE :begin lcd_data <= 8'h38; lcd_rs <= 0;end
INIT :begin lcd_data <= 8'h38; lcd_rs <= 0;end
S0 :begin lcd_data <= 8'h08; lcd_rs <= 0;end
S1 :begin lcd_data <= 8'h01; lcd_rs <= 0;end
S2 :begin lcd_data <= 8'h06; lcd_rs <= 0;end
S3 :begin lcd_data <= 8'h0c; lcd_rs <= 0;end
ROW1_ADDR :begin lcd_data <= 8'h80; lcd_rs <= 0;end
//WRITE :begin lcd_data <= data_display; lcd_rs <= 1;end
WRITE :begin lcd_data <= disp_memory; lcd_rs <= 1;end
ROW2_ADDR :begin lcd_data <= 8'hc0; lcd_rs <= 0;end
stop :begin lcd_data <= 8'h38; lcd_rs <= 0;end
default:;
endcase
end
end
endmodule
</code></pre>
<p> </p>
<p><span style="font-size:16px;"><span style="font-family:宋体;"> 本实验用到了复位功能,将双功能管脚选项中的RECONFIG_N作为普通IO选项打勾。</span></span></p>
<p><span style="font-size:16px;"><span style="font-family:宋体;"></span></span></p>
<p><span style="font-size:16px;"><span style="font-family:宋体;"> </span></span></p>
<p><span style="font-size:16px;"><span style="font-family:宋体;"> 逻辑代码编译通过,下载到开发板,LCD1602两行分别显示“Welcome to GOWIN”、“Mini KiT GWIN-4B”,效果见下图。</span></span></p>
<p><span style="font-size:16px;"><span style="font-family:宋体;"></span></span></p>
<p> </p>
<p><span style="font-size:16px;"><span style="font-family:宋体;"> 本实验完成将LCD1602屏点亮显示字符。</span></span></p>
<p><span style="font-size:16px;"><span style="font-family:宋体;"> 疫情原因无法正常上般,家里条件有限,手头缺少扩展模块来实验,更多扩展功能之后有时间补上。</span></span></p>
<p><span style="font-size:16px;"><span style="font-family:宋体;"> </span></span></p>
<p>熟悉的lcd1602,我以为它已经被淘汰了</p>
<p>希望是疫情最后一波,明年可以解放啦</p>
页:
[1]