根据LCD1602的简单秒表的设计与实现.docx
《根据LCD1602的简单秒表的设计与实现.docx》由会员分享,可在线阅读,更多相关《根据LCD1602的简单秒表的设计与实现.docx(58页珍藏版)》请在冰豆网上搜索。
![根据LCD1602的简单秒表的设计与实现.docx](https://file1.bdocx.com/fileroot1/2023-7/3/69bc2b53-f1a9-46ec-95c9-b5d5d978f74b/69bc2b53-f1a9-46ec-95c9-b5d5d978f74b1.gif)
根据LCD1602的简单秒表的设计与实现
数字电路与逻辑设计
实验报告
学院:
电子工程学院
班级:
2014211212
姓名:
学号:
班内序号:
亠、设计课题的任务要求
简易秒表的设计与实现
设计制作一个计时精度为百分之一秒的计时秒表
基本要求:
1.用LCD1602液晶屏显示计时;
2.秒表计时长度为23小时59分59.99秒;
3.用BTNOf乍为启动/停止开关;
4.用BTN1作为复位开关,在任何情况下,只要按下复位开关,秒表都要无条件执行清零操作。
提高要求:
1.增加定时器功能,可根据用户设定的时间进行倒计时,时间到0后蜂鸣器报警提示;
2.自拟其他功能。
】、系统设计(设计思路、总体框图、分块设计)
1.设计思路:
分别设计6进制计数器、10进制计数器和24进制计数器用于秒表计时部分。
具体来说:
将两个10进制计数器级联分别作为秒表的十分秒位(最小单位为0.1秒)和百分秒位(最小单位为0.01秒);将一个10进制计数器和6进制计数器级联,分别作为秒表秒钟部分的个位(最小单位为1秒)和十位(最小单位为10秒);再将一个10进制计数器和6进制计数器级联,分别作为秒表分钟部分的个位(最小单位为1分钟)和十位(最小单位为10分钟);将24进制计数器作为秒表小时部分,其中低位输出作为秒表小时部分的个位(最小单位为1小时),高位输出作为秒表小时部分的十位(最小单位为10小时)。
最后把秒表百分秒、十分秒部分、秒钟部分、分钟部分、小时部分这四部分级联起来便构成了简易数字秒表的计时部分。
将各个计数器部分的输出信号通过译码模块,变成LCD1602液晶屏能够读
取并从而显示相关字符的8位二进制数据。
再定义一个存储器ram,存储各个计数器部分的输出信号经过译码部分之后得到的数据,然后将这个存储器ram代表的数据在LCD1602液晶屏上显示。
考虑到秒表的最小计时长度为0.01秒(频率为100HZ),如果系统时钟设置为50MHZ则需要500000分频;实验时发现LCD1602液晶屏的时钟在1KHZ寸,显示效果较好,故需要在系统时钟为50MHZ勺基础上进行50000分频。
考虑到基本要求中需要用BTN0作为启动/停止开关,用BTN1作为复位开
关,所以需要设计相应的按键防抖电路,这里我采用的是计数型防抖。
2.总体框图:
豎亠厂息
图1系统结构框图
3.分块设计:
系统共通过9个模块实现,分别是:
500000分频模块fpq
50000分频模块fpql
6进制计数器模块cnt6
10进制计数器模块cnt10
24进制计数器模块cnt24
译码模块yima
LCD1602显示模块LCD1602
BTN0启动/停止开关消抖模块xiaodou
BTN1复位开关消抖模块fuweixiaodou
具体设计如下:
500000分频模块fpq
输入端口:
clk:
instd_logic;输出端口:
clkout:
outstd_logic;
生成符号:
一
设计思路:
利用计数法实现分频主要代码:
(完整代码请见源程序)
signalclktmp:
std_logic;
signaltmp:
integerrange0to249999;
begin
process(clk)
begin
ifclk'eventandclk='1'then
iftmp=249999then--500000分频
tmpv=O;clktmpv=notclktmp;else
tmpv=tmp+1;
endif;
endif;
endprocess;
clkout<=clktmp;
50000分频模块fpql:
设计思路:
正常的计数状态是0->1->2->3->4->5->0->1……;
当计数到5时,进位信号变为‘1'否则状态自增,进位信号保持在’0'
主要代码:
(完整代码请见源程序)
SIGNALqs:
STD_LOGIC_VECTOR(3DOWNTO0);
SIGNALca:
STD_LOGIC;
BEGIN
PROCESS(clk)
begin
IF(reset='1')THENqs<="0000";
ELSIF(clk'EVENTANDclk='1')THEN
IF(en='0')THEN
qs<="0000";ca<='1';
ELSEqs<=qs+1;ca<='0';
ENDIF;
ENDIF;
ENDIF;
ENDPROCESS;
PROCESS(ca,en)
BEGIN
q<=qs;
carry<=ca;
ENDPROCESS;
10进制计数器模块cnt10:
输入端口:
reset,en,clk:
INSTD_LOGIC;
输出端口:
carry:
OUTSTD_LOGIC;
q:
OUTSTD_LOGIC_VECTOR(3DOWNTO0);
Mirry
en
e<30]
£:
纟!
m£i
7_______7
纟両而“i一•-iI纟:
Ii7I>>>!
■■■!
■|j.inii.i.icgiin.II|II>|..I并
'和"斗討繆FJ■和和和和曲
=■令•
-)k|-
设计思路:
正常的计数状态是;
0->1->2->3->4->5->6->7->8->9->0->1
当计数到9时,进位信号变为‘1'否则状态自增,进位信号保持在’0'
主要代码:
(完整代码请见源程序)
SIGNALqs:
STD_LOGIC_VECTOR(3DOWNTO0);
SIGNALca:
STD_LOGIC;
BEGIN
PROCESS(clk)
begin
IF(reset='1')THENqs<="0000";
ELSIF(clk'EVENTANDclk='1')THEN
IF(en='0')THEN
IF(qs="1001")THEN--计数到9
qs<="0000";
ca<='1';
ELSE
qs<=qs+1;
ca<='0';
ENDIF;
ENDIF;
ENDIF;
ENDPROCESS;
PROCESS(ca)
BEGIN
q<=qs;
carry<=ca;
ENDPROCESS;
24进制计数器模块cnt24:
输入端口en,Reset,clk:
inSTD_LOGIC;
输出端口carry:
outSTD_LOGIC;
qa:
outSTD_LOGIC_VECTOR(3DOWNTO0);
qb:
outSTD_LOGIC_VECTOR(3DOWNTO0);
设计思路:
正常的计数状态是;
低位qa状态变化:
0->1->2->3->4->5->6->7->8->9->0->1
高位qb状态变化:
0->1->2->0->1
当低位qa计数到9时,qb自增,进位信号保持在‘0'当低位qa为3且高位qb为2时,进位信号变为‘1',同时qa变为0、qb变为0
主要代码:
(完整代码请见源程序)
SIGNALca:
STD_LOGIC;
BEGIN
process(clk,Reset,en)
variabletma:
STD_LOGIC_VECTOR(3DOWNTO0);variabletmb:
STD_LOGIC_VECTOR(3DOWNTO0);begin
IfReset='1'thentma:
="0000";tmb:
="0000";else
ifclk'eventandclk='1'then
IF(en='0')THEN
--当BTN0键没有第一次按下时,正常计数
iftma="1001"thentma:
="0000";tmb:
=tmb+1;
elsiftmb="0010"andtma="0011"then
--计数到23
tma:
="0000";tmb:
="0000";
ca<='1';
elsetma:
=tma+1;
endif;
endif;
endif;
endif;
qa<=tma;qb<=tmb;
carry<=ca;
endprocess;
译码模块yima:
输入端口:
carry:
inSTD_LOGIC;
data:
instd」ogic_vector(3downto0);
输出端口:
dataout:
outstd」ogic_vector(7downto0));
生成符号:
打殆甘拝起耕拜蒲f和暑f*釋聲押聲幷和理f抨,..yy_
carry
■daCa[^L.4]
l\
设计思路:
根据输入信号的不同,使用case语句进行不同的译码操作即可。
具体来说:
'0'
(四位二
二进制)
译为"30"
(八位二
二进制)
'1'
(四位二
二进制)
译为"31"
(八位二
二进制)
2
(四位二
二进制)
译为"32"
(八位二
二进制)
3
(四位二
二进制)
译为"33"
(八位二
二进制)
'4'
(四位二
二进制)
译为"34"(八位二
二进制)
'5'
(四位二
二进制)
译为"35"(八位二
二进制)
'6'
(四位二
二进制)
译为"36"(八位二
二进制)
'7'
(四位二
二进制)
译为"37"(八位二
二进制)
'8'
(四位二
二进制)
译为"38"(八位二
二进制)
'9'
(四位二
二进制)
译为"39"(八位二
二进制)
其他译为"20"(八位二进制)
主要代码:
(完整代码请见源程序)
signaldis:
std」ogic_vector(7downto0);begin
process(data)
begin
if(carry='1')then
dis<="11111111";
else
casedatais
when"0000"=>dis<="00110000";-
-'0'
译为"30"
when"0001"=>dis<="00110001";-
-'1'
译为"31"
when"0010"=>dis<="00110010";-
-'2'
译为"32"
when"0011"=>dis<="00110011";-
-'3'
译为"33"
when"0100"=>dis<="00110100";-
-'4'
译为"34"
when"0101"=>dis<="00110101";-
-'5'
译为"35"
when"0110"=>dis<="00110110";-
-'6'
译为"36"
when"0111"=>dis<="00110111";-
-'7'
译为"37"
when"1000"=>dis<="00111000";-
-'8'
译为"38"
when"1001"=>dis<="00111001";-
-9
译为"39"
whenothers=>dis<="00100000";-
其他译为"20
endcase;
endif;
endprocess;
dataout<=dis;
译码数据信号1译码数据信号2译码数据信号3译码数据信号4译码数据信号5译码数据信号6译码数据信号7译码数据信号8
LCD1602显示模块LCD1602输入端口:
YIMA_DATA1:
instd_logic_vector(7downto0);--YIMA_DATA2:
instd_logic_vector(7downto0);--YIMA_DATA3:
instd_logic_vector(7downto0);--YIMA_DATA4:
instd_logic_vector(7downto0);--YIMA_DATA5:
instd_logic_vector(7downto0);--YIMA_DATA6:
instd_logic_vector(7downto0);--YIMA_DATA7:
instd_logic_vector(7downto0);--YIMA_DATA8:
instd_logic_vector(7downto0);--
LCD_Clk:
instd」ogic
--状态机时钟信号,同时也是液晶时钟信号,其周期应该满足液晶数据的建立时间
carry:
inSTD_LOGIC;
输出端口:
LCD_RS:
LCD_RW:
LCD_EN:
LCDData:
outstd」ogic;--寄存器选择信号
outstd」ogic;--液晶读写信号
outstd」ogic;--液晶时钟信号
outstd」ogic_vector(7downto0);
----液晶数据信号
生成符号:
I夕:
纟“UAyryQ]:
乡1¥IMA_MT«p.□]:
YlMA_[MTA+n0]纟¥IUA_gTA6(701纟:
!
^VIUA_[>A™8[7.0]纟4¥IHA_OA7A7P.0]:
纟Y1UA_D*7AS(7.耳
设计思路:
将各个计数器部分的输出信号通过译码模块,变成LCD1602液晶屏能够读取并从而显示相关字符的8位
二进制数据。
再定义一个存储器ram,存储各个计数器部分的输出信号经过译码部分之后得到的数据,然后将这个存储器ram代表的数据在LCD1602液晶屏上显示。
主要代码:
(完整代码请见源程序)
ram1(8)v=x"2e";ram1(9)v=YIMA_DATA2;--ram1(10)v=YIMA_DATA1;--
--显示小数点.
译码数据信号2,秒表十分秒位
译码数据信号1,秒表百分秒位
process(LCD_Clk)variableent:
integerrange0to37;
begin
ifLCD_Clk'eventandLCD_Clk='1'thenifent=37thenent:
=0;
elseent:
=ent+1;
endif;
endif;
easeentis
InitLCD1602初始化部分
when0=>LCD_RS<='0';lcd_data<="00111000";--0x38when1=>LCD_RS<='0';led_data<="00001100";--0x0C
when2=>LCD_RS<='0';led_data<="00000001";--0x01
when3=>LCD_RS<='0';lcd_data<="00000110";--0x06
when4=>LCD_RS<='0';lcd_data<="10000000";--0x80--display,0x00+0x80
datadisplay
when5=>LCD_RSv='1';lcd_data<="10100000";--空格
when6=>LCD_RS<='1';led_data<="10100000";--空格
when7=>LCD_RS<='1';led_data<="10100000";--空格
when8=>LCD_RS<='1';led_data<=ram1(0);--秒表小时部分十位when9=>LCD_RS<='1';led_data<=ram1
(1);--秒表小时部分个位
when10=>LCD_RS<='1';lcd_datav=ram1
(2);--冒号:
when1仁>LCD_RS<='1';lcd_data<=ram1(3);--秒表分钟部分十位
when12=>LCD_RS<='1';led_data<=ram1(4);--秒表分钟部分个位
when13=>LCD_RS<='1';led_data<=ram1(5);--冒号:
when14=>LCD_RS<='1';led_data<=ram1(6);--秒表秒钟部分十位when15=>LCD_RS<='1';lcd_datav=ram1(7);--秒表秒钟部分个位
when16=>LCD_RS<='1';led_data<=ram1(8);--小数点.
when17=>LCD_RS<='1';led_data<=ram1(9);--秒表十分秒位
when18=>LCD_RS<='1';led_data<=ram1(10);--秒表百分秒位
when19=>LCD_RS<='1';led_data<="10100000";-空格
when20=>LCD_RS<='1';led_data<="10100000";-空格
when2仁>LCD_RS<='0';lcd_data<="11000000";
--设定显示的位置在40H+80H
when22=>LCD_RS<='1';led_data<="10100000";--空格
when23=>LCD_RS<='1';lcd_data<="10100000";--空格when24=>LCD_RS<='1';lcd_data<="10100000";--空格when25=>LCD_RS<='1';lcd_data<="10100000";--空格when26=>LCD_RS<='1';lcd_data<="10100000";--空格when27=>LCD_RS<='1';lcd_data<="10100000";--空格when28=>LCD_RS<='1';lcd_data<="10100000";--空格when29=>LCD_RS<='1';lcd_data<="10100000";--空格when30=>LCD_RS<='1';lcd_data<="10100000";--空格when3仁>LCD_RS<='1';lcd_data<="10100000";--空格when32=>LCD_RS<='1';lcd_data<="10100000";--空格when33=>LCD_RS<='1';lcd_data<="10100000";--空格when34=>LCD_RS<='1';lcd_data<="10100000";--空格when35=>LCD_RS<='1';lcd_data<="10100000";--空格when36=>LCD_RS<='1';lcd_data<="10100000";--空格when37=>LCD_RS<='1';lcd_data<="10100000";--空格
endcase;
endprocess;
BTN0启动/停止开关消抖模块xiaodou:
输入端口:
clk:
instd_logic;
key_en:
instd_logic;
输出端口:
en_out:
outstd」ogic生成符号:
一一
--UB-LR-n-kr-o-
设计思路:
采用计数型防抖
当key_en第一次为'1'时,en_out延迟一段时间后变为'1',并且en_out就此保持在高电平'1';
直到key_en第二次为'1'时,en_out延迟一段时间后变为'0'。
主要代码:
(完整代码请见源程序)
signalcnt:
integerrange0to3;--采用计数型防抖
signalen,en_tmp:
std」ogic;
begin
p0:
process(clk)begin
ifclk'eventandclk='1'then
ifkey_en='1'then
ifent=3thenen<='1';
elsecnt<=cnt+1;en<='0';
endif;
elsecnt<=0;en<='0';
endif;
endif;
endprocessp0;
p1:
process(en)
begin
ifen'eventanden='1'then
en_tmp<=noten_tmp;
endif;
en_out<=en_tmp;
endprocessp1;
BTN1复位开关消抖模块fuweixiaodou:
输入端口:
clk:
instd」ogic;
fuwei:
instd_logic;
输出端口:
fuwei_out:
outstd」ogic生成符号:
一一
■BfaB>il■!
£.■-rB■-BhRbF
设计思路:
采用计数型防抖
当fuwei为'1'时,fuwei_out延迟一段时间后变为'1',然后fuwei_out又重新回到低电平'0'。
主要代码:
(完整代码请见源程序)
signalcnt:
integerrange0to3;--采用计数型防抖
signalen:
std_logic;
begin
process(clk)
begin
ifclk'eventandclk='1'then
iffuwei='1'then
ifent=3thenen<='1';elseent<=ent+1;en<='0';endif;
elseent<=0;en<='0';
endif;
endif;
endprocess;
fuwei_out<=en;
、仿真波形及波形分析
500000分频模块fpq
输入端口:
clk:
instd_logic;输出端口:
clkout:
outstd_logic;
仿真波形:
一
输入时钟信号为clk,频率为50MHZ(周期为20ns)输出时钟信号为clkout,频率为100HZ(周期为10m$)达到了500000分频的目的。
MiMieiTineQdc■*[*|PoriBn12rid心-1^.1ns占lartEnd
>-u.ciiLTfinQm.ao:
m.e也卩□p»i<:
in:
abp32a.p
Bt
n
_nL_r-L_rn—r~i—TT_TT_r~i_n_r~L_nL_nL_rT_r^_r~L_nL_nL
0L
输入端口输出端口仿真波形
clk:
instd_logic;clkout:
outstd_logi