1、 电子信息工程专业 专业综合课程设计 基于FPGA的液晶显示控制器设计 学 院(系): 信息与通信工程 专 业: 电子信息工程 专业综合课程设计题目 目 录 1设计指标及要求 1 1.1任务及要求 1 1.2设计原理 1 2系统硬件电路设计 2 2.1FPGA核心板 2 2.2液晶显示部分 3 2.3按键控制部分 5 3系统软件设计 5 4系统调试 6 4.1硬件调试 6 4
2、2软件调试 7 5结论 7 6参考文献 7 附录一 系统硬件电路图(原理图,PCB) 8 附录二 实物照片 9 附录三 系统完整程序代码 9 - 20 - 1设计指标及要求 1.1任务及要求 采用FPGA技术实现液晶的显示功能,要求学生选好液晶芯片,画出电路板,做好硬件电路后调试程序,基本功能要求显示字符,扩展功能是显示动画。 1.2设计原理 显示控制模块是通过对FPGA芯片的编程,在此同时通过调用显示ROM文件中的字库,找到相应的二进制显示代码,再一条一条地送到显示驱动电路中,最后经过放大,送到点阵中的液晶去显示。 系统的整体框图如下图所示:
3、 2系统硬件电路设计 2.1FPGA核心板 2.2液晶显示部分 12864各引脚的功能如下: 引脚号 引脚名称 引脚功能描述 1 VSS 电源地 2 VDD 电源电压 3 V0 LCD驱动负电压,调节LCD对比度 4 RS H:DB0-DB7为显示数据 L: DB0-DB7为指令
4、数据 5 R/W R/W=H,E=H数据被读到DB0-DB7 R/W=L,E=H DB0-DB7数据写到IR或DR 6 E 使能信号:R/W=L,E信号下降沿锁存到DB0-DB7; R/W=H,E=H,DDRAM数据读到DB0-DB7 7 DB0~DB7 8位三态并行数据总线 8 PSB PS
5、B=H时为并行输入方式,PSB=L时为串行输入方式 9 RST 复位端,低电平有效 12864的信号功能表如下图所示: 12864的工作时序如下图所示: 2.3按键控制部分 按键连接电路如下图所示: 按键分别连接着FPGA芯片的I/O口,通过拨动按键使液晶显示不同的字符。 3系统软件设计 程序流程图如下图所示: 4系统调试
6、 调试分为硬件调试和软件调试。 4.1硬件调试 1、上电之前,用万用表测试电源与地未短路。 2、上电接通电路,指示灯正常点亮。 3、但12864液晶屏背光灯点亮,却未出现正常阴影,将12864反插接入电路,液晶屏点亮,出现正常阴影,检查PCB及原理图发现12864引脚并未接错,于是参考已有12864的多种电路接法,更改板子上的12864电路,问题却仍得不到解决,最终发现是所用12864液晶屏自带电路已默认选择串行数据通信,而我们所采用的电路都是并行数据通信电路,将12864液晶屏自带电路改焊,液晶屏正常点亮。原先设计12864电路所加的用于调节液晶屏对比度的滑动变阻器,实际使用时,发
7、现并未起作用,故将其去掉。 4、向板子内烧录简单的显示程序,12864液晶屏正常显示出编写的内容。至此,硬件调试完成。 4.2软件调试 1、先根据整体思路确定了软件采用状态机的方式编写。然后查阅了12864液晶屏的使用手册以及EP4CE6E22芯片使用手册,确定了基本的操作要求,并根据要求进行了12864读数据写数据的程序编写,建成工程,完成编译,烧录进芯片,上电后,正确显示成功,完成了初步调试。 2、画出了程序框图,然后将各部细节补充出来。 3、正确的延时对于12864液晶屏的正确显示至关重要。要想延时正确就得先解决时序的问题,我们通过借鉴以往的学习EDA时所做的实验,直接套用了一
8、个典型分频程序,解决了该问题。 4、在程序里延时的正确使用是一大难点,因为VHDL语言仿真性极强,其独有的延时语句,多数只支持仿真状态,综合设计时并不能通过编译,无法实现,我们尝试了诸如for、loop、wait until、wait on等语句都未能正常编译通过,最后采用if语句,计数延时才得以正确延时。 5、最终,我们经过多次删改,基本完成了预期要实现的设计目标。 5结论 本设计硬件电路的使用比较简单,所用元器件较少,电路中使用了FPGA芯片和LCD12864液晶显示器等主要芯片,实现了预计的功能。在对芯片的管脚功能和用法有了充分的了解后,根据原先的选择好的设计要求设计硬件电路
9、包括FPGA控制电路、按键接口电路、显示电路。然后通过软件编程,实现了用按键进行控制,用液晶模块进行显示,基本完成了预期要实现的目标。 6参考文献 [1] 潘松, 黄继业. EDA技术实用教程——VHDL版[M]. 第四版. 北京:科学出版社, 2010. [2] 赵俊超等. 集成电路设计VHDL教程[M]. 北京 :北京希望电子出版社, 2009. [3] 李维是, 郭强. 液晶显示应用技术[M]. 北京:电子工业出版社, 2011. 附录一 系统硬件电路图(原理图,PCB) 附录二 实物照片 附录三 系统完整程序代码 -------------1286
10、4液晶的显示----------- ----时钟:50MHZ library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; entity lcd12864 is generic( divide_500k:integer:=100;--100分频后:500KHZ:2us cnt1_value:integer:=50 ); port( clk,reset:in std_logi
11、c; key:in std_logic_vector(1 downto 0); rs,rw,en:out std_logic; data:out std_logic_vector(7 downto 0) ); end entity; architecture behavior of lcd12864 is type word is array(0 to 15) of std_logic_vector(7 downto 0); --数组中的左起第1个数为数组中的最低位对应的数,所以设置为array(0 to 3),而不是array(3 do
12、wnto 0)。 type state is( set_dlnf,set_cursor,set_dcb,set_shift, set_ddram1,set_ddram2,set_ddram3,set_ddram4, write_xuexiao,write_zhuanye,write_mc,write_fh, over ); constant name1:word:=("10100001","11101111","10110100","11110011","11000001","10101100","110
13、00011","11110001","11010111","11100101","11010001","10100111","11010100","10111010","10100001","11101111");--大连民族大学 constant name2:word:=("10100001","11101111","10110101","11100111","11010111","11010011","11010000","11000101","11001111","10100010","10111001","10100100","10110011","11001100","1010
14、0001","11101111");--电子信息工程 constant name3:word:=("11001101","11110101","10111010","10110001","10100001","11101111","10100001","11101111","10100001","11101111","11001101","11110100","11010101","11010111","10111001","11111010");--李瑞 constant name4:word:=("11010111","10100011","11000000","11001111"
15、"11001010","10100110","10111101","11011010","11001000","11010101","10111111","11101100","11000000","11010110","10100011","10100001");--祝老师节日快乐 constant name5:word:=("11010111","10100011","11000000","11001111","11001010","10100110","11001001","11101101","11001100","11100101","10111101","10100001","
16、10111111","10110101","10100011","10100001");--祝老师身体健康 constant name6:word:=("11010111","10100011","11000000","11001111","11001010","10100110","11001101","11110010","11001010","11000010","11001000","11100111","11010010","11100010","10100011","10100001");--祝老师万事如意 constant name7:word:=("11010111","1
17、0100011","11000000","11001111","11001010","10100110","10111010","11001111","10111100","11010010","11010000","11010010","10111000","10100011","10100011","10100001");--祝老师阖家幸福 signal pr_state:state; signal newclk:std_logic; begin process(clk) is variable num:integer range 0 to divide_500k
18、
begin
if(clk'event and clk='1')then
num:=num+1;
if(num=divide_500k) then
num:=0;
end if;
if(num 19、e cnt1:integer range 0 to 100*cnt1_value:=0;
variable cnt2:integer range 0 to 100:=0;
begin
if reset='0' then
pr_state<=set_dlnf;--把状态set_dlnf赋于pr_state
cnt1:=0;
cnt2:=0;
en<='0';
rs<='0';
rw<='0';
data<="00000001";--清屏
en<='1';
elsif(newclk'event and n 20、ewclk='1') then
case pr_state is
when set_dlnf=>
cnt1:=cnt1+1;
if(cnt1 21、1<20*cnt1_value) then
en<='1';
elsif(cnt1=20*cnt1_value) then
en<='0';
cnt1:=0;
pr_state<=set_cursor;
end if;
when set_cursor=>
cnt1:=cnt1+1;
if(cnt1 22、hen
data<="00001100"; --整体显示设置:光标OFF 反光0FF:0x0c
elsif(cnt1<20*cnt1_value) then
en<='1';
elsif(cnt1=20*cnt1_value) then
en<='0';
cnt1:=0;
pr_state<=set_dcb;
end if;
when set_dcb=>
cnt1:=cnt1+1;
if(cn 23、t1 24、
end if;
when set_shift=>
cnt1:=cnt1+1;
if(cnt1 25、ue) then
en<='0';
cnt1:=0;
pr_state<=set_ddram1;
end if;
when set_ddram1=>
cnt1:=cnt1+1;
if(cnt1 26、nt1<20*cnt1_value) then
en<='1';
elsif(cnt1=20*cnt1_value) then
en<='0';
cnt1:=0;
pr_state<=write_xuexiao;
end if;
when write_xuexiao=>
cnt1:=cnt1+1;
if cnt1<1*cnt1_value then
en<='0';
rs<='1'; 27、 ------------选择数据
rw<='0';
elsif cnt1<2*cnt1_value then
if key="00" then data<=name1(cnt2) ; ------------送数据
elsif key="01" then data<=name1(cnt2);
elsif key="10" then data<=name3(cnt2);
elsif key="11" then data<=name4(cnt2);
end if;
elsif cnt1<20*c 28、nt1_value then
en<='1'; -----在上升沿时,数据才能写入液晶,所以要先送数据,再让使能端变高
elsif cnt1=20*cnt1_value then
en<='0'; -----通过液晶的时序图知:使能端先低,送数据,使能端升高,再变低。
cnt1:=0;
cnt2:=cnt2+1;
if
cnt2=16
then
pr_state<=set 29、ddram2;
cnt1:=0;
cnt2:=0;
end if;
end if;
when set_ddram2=>
cnt1:=cnt1+1;
en<='0';
rw<='0';
rs<='0';
if(cnt1 30、0x80
elsif(cnt1<20*cnt1_value) then
en<='1';
elsif(cnt1=20*cnt1_value) then
en<='0';
cnt1:=0;
pr_state<=write_zhuanye;
end if;
when write_zhuanye=>
cnt1:=cnt1+1;
if cnt1<1*cnt1_value then
en<='0';
31、 rs<='1'; ------------选择数据
rw<='0';
elsif cnt1<2*cnt1_value then
if key="00" then data<=name2(cnt2); ------------送数据
elsif key="01" then data<=name1(cnt2);
elsif key="10" then data<=name3(cnt2);
elsif key="11" then data<=name5(cnt2);
end if; 32、
elsif cnt1<20*cnt1_value then
en<='1'; -----在上升沿时,数据才能写入液晶,所以要先送数据,再让使能端变高
elsif cnt1=20*cnt1_value then
en<='0'; -----通过液晶的时序图知:使能端先低,送数据,使能端升高,再变低。
cnt1:=0;
cnt2:=cnt2+1;
if
cnt2=16
then 33、
pr_state<=set_ddram3;
cnt1:=0;
cnt2:=0;
end if;
end if;
when set_ddram3=>
cnt1:=cnt1+1;
en<='0';
rw<='0';
rs<='0';
if(cnt1 34、01000"; --从第三行的第一个字开始显示:0x80
elsif(cnt1<20*cnt1_value) then
en<='1';
elsif(cnt1=20*cnt1_value) then
en<='0';
cnt1:=0;
pr_state<=write_mc;
end if;
when write_mc=>
cnt1:=cnt1+1;
if cnt1<1*cnt1_value then
35、 en<='0';
rs<='1'; ------------选择数据
rw<='0';
elsif cnt1<2*cnt1_value then
if key="00" then data<=name3(cnt2); ------------送数据
elsif key="01" then data<=name1(cnt2);
elsif key="10" then data<=name3(cnt2);
elsif key="11" then data< 36、name6(cnt2);
end if;
elsif cnt1<20*cnt1_value then
en<='1'; -----在上升沿时,数据才能写入液晶,所以要先送数据,再让使能端变高
elsif cnt1=20*cnt1_value then
en<='0'; -----通过液晶的时序图知:使能端先低,送数据,使能端升高,再变低。
cnt1:=0;
cnt2:=cnt2+1;
if
cnt2=16 37、
then
pr_state<=set_ddram4;
cnt1:=0;
cnt2:=0;
end if;
end if;
when set_ddram4=>
cnt1:=cnt1+1;
en<='0';
rw<='0';
rs<='0';
if(cnt1 38、ta<="10011000"; --从第四行的第一个字开始显示:0x80
elsif(cnt1<20*cnt1_value) then
en<='1';
elsif(cnt1=20*cnt1_value) then
en<='0';
cnt1:=0;
pr_state<=write_fh;
end if;
when write_fh=>
cnt1:=cnt1+1;
if cnt1<1*cnt1_value then
39、 en<='0';
rs<='1'; ------------选择数据
rw<='0';
elsif cnt1<2*cnt1_value then
if key="00" then data<=name4(cnt2); ------------送数据
elsif key="01" then data<=name1(cnt2);
elsif key="10" then data<=name3(cnt2);
elsif key="11" then d 40、ata<=name7(cnt2);
end if;
elsif cnt1<20*cnt1_value then
en<='1'; -----在上升沿时,数据才能写入液晶,所以要先送数据,再让使能端变高
elsif cnt1=20*cnt1_value then
en<='0'; -----通过液晶的时序图知:使能端先低,送数据,使能端升高,再变低。
cnt1:=0;
cnt2:=cnt2+1;
if
c 41、nt2=16
then
pr_state<=over;
cnt1:=0;
cnt2:=0;
end if;
end if;
when over=>
null;
when others=>
en<='Z';
rs<='Z';
rw<='Z';
data<=(others=>'Z');
cnt1:=0;
cnt2:=0;
end case;
end if;
end process;
end architecture;






