基于LCD1602的简易秒表的设计与实现.docx
- 文档编号:5327256
- 上传时间:2022-12-15
- 格式:DOCX
- 页数:45
- 大小:341.23KB
基于LCD1602的简易秒表的设计与实现.docx
《基于LCD1602的简易秒表的设计与实现.docx》由会员分享,可在线阅读,更多相关《基于LCD1602的简易秒表的设计与实现.docx(45页珍藏版)》请在冰豆网上搜索。
基于LCD1602的简易秒表的设计与实现
数字电路与逻辑设计
实验报告
学院:
电子工程学院
班级:
2014211212
姓名:
学号:
班内序号:
一、设计课题的任务要求
简易秒表的设计与实现
设计制作一个计时精度为百分之一秒的计时秒表
基本要求:
1.用LCD1602液晶屏显示计时;
2.秒表计时长度为23小时59分59.99秒;
3.用BTN0作为启动/停止开关;
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分频模块fpq1
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分频
tmp<=0;clktmp<=notclktmp;
else
tmp<=tmp+1;
endif;
endif;
endprocess;
clkout<=clktmp;
50000分频模块fpq1:
输入端口:
clk:
instd_logic;
输出端口:
clkout:
outstd_logic;
生成符号:
设计思路:
利用计数法实现分频
主要代码:
(完整代码请见源程序)
signalclktmp:
std_logic;
signaltmp:
integerrange0to24999;
begin
process(clk)
begin
ifclk'eventandclk='1'then
iftmp=24999then--50000分频
tmp<=0;clktmp<=notclktmp;
else
tmp<=tmp+1;
endif;
endif;
endprocess;
clkout<=clktmp;
6进制计数器模块cnt6:
输入端口:
reset,en,clk:
INSTD_LOGIC;
输出端口:
carry:
OUTSTD_LOGIC;
q:
OUTSTD_LOGIC_VECTOR(3DOWNTO0);
生成符号:
设计思路:
正常的计数状态是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
IF(qs="0101")THEN--计数到5
qs<="0000";
ca<='1';
ELSE
qs<=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);
生成符号:
设计思路:
正常的计数状态是;
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_logic_vector(3downto0);
输出端口:
dataout:
outstd_logic_vector(7downto0));
生成符号:
设计思路:
根据输入信号的不同,使用case语句进行不同的译码操作即可。
具体来说:
'0'(四位二进制)译为"30"(八位二进制)
'1'(四位二进制)译为"31"(八位二进制)
'2'(四位二进制)译为"32"(八位二进制)
'3'(四位二进制)译为"33"(八位二进制)
'4'(四位二进制)译为"34"(八位二进制)
'5'(四位二进制)译为"35"(八位二进制)
'6'(四位二进制)译为"36"(八位二进制)
'7'(四位二进制)译为"37"(八位二进制)
'8'(四位二进制)译为"38"(八位二进制)
'9'(四位二进制)译为"39"(八位二进制)
其他译为"20"(八位二进制)
主要代码:
(完整代码请见源程序)
signaldis:
std_logic_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;
LCD1602显示模块LCD1602:
输入端口:
YIMA_DATA1:
instd_logic_vector(7downto0);--译码数据信号1
YIMA_DATA2:
instd_logic_vector(7downto0);--译码数据信号2
YIMA_DATA3:
instd_logic_vector(7downto0);--译码数据信号3
YIMA_DATA4:
instd_logic_vector(7downto0);--译码数据信号4
YIMA_DATA5:
instd_logic_vector(7downto0);--译码数据信号5
YIMA_DATA6:
instd_logic_vector(7downto0);--译码数据信号6
YIMA_DATA7:
instd_logic_vector(7downto0);--译码数据信号7
YIMA_DATA8:
instd_logic_vector(7downto0);--译码数据信号8
LCD_Clk:
instd_logic;
--状态机时钟信号,同时也是液晶时钟信号,其周期应该满足液晶数据的建立时间
carry:
inSTD_LOGIC;
输出端口:
LCD_RS:
outstd_logic;--寄存器选择信号
LCD_RW:
outstd_logic;--液晶读写信号
LCD_EN:
outstd_logic;--液晶时钟信号
LCD_Data:
outstd_logic_vector(7downto0);--液晶数据信号
生成符号:
设计思路:
将各个计数器部分的输出信号通过译码模块,变成LCD1602液晶屏能够读取并从而显示相关字符的8位二进制数据。
再定义一个存储器ram,存储各个计数器部分的输出信号经过译码部分之后得到的数据,然后将这个存储器ram代表的数据在LCD1602液晶屏上显示。
主要代码:
(完整代码请见源程序)
typeramisarray(0to10)ofstd_logic_vector(7downto0);
signalram1:
ram;
begin
LCD_EN<=LCD_Clk;--液晶时钟信号
LCD_RW<='0';--液晶读写信号
ram1(0)<=YIMA_DATA8;--译码数据信号8,秒表小时部分十位
ram1
(1)<=YIMA_DATA7;--译码数据信号7,秒表小时部分个位
ram1
(2)<=x"3a";--显示冒号:
ram1(3)<=YIMA_DATA6;--译码数据信号6,秒表分钟部分十位
ram1(4)<=YIMA_DATA5;--译码数据信号5,秒表分钟部分个位
ram1(5)<=x"3a";--显示冒号:
ram1(6)<=YIMA_DATA4;--译码数据信号4,秒表秒钟部分十位
ram1(7)<=YIMA_DATA3;--译码数据信号3,秒表秒钟部分个位
ram1(8)<=x"2e";--显示小数点.
ram1(9)<=YIMA_DATA2;--译码数据信号2,秒表十分秒位
ram1(10)<=YIMA_DATA1;--译码数据信号1,秒表百分秒位
process(LCD_Clk)
variablecnt:
integerrange0to37;
begin
ifLCD_Clk'eventandLCD_Clk='1'then
ifcnt=37thencnt:
=0;
elsecnt:
=cnt+1;
endif;
endif;
casecntis
-----------------InitLCD1602初始化部分-------------
when0=>LCD_RS<='0';lcd_data<="00111000";--0x38
when1=>LCD_RS<='0';lcd_data<="00001100";--0x0C
when2=>LCD_RS<='0';lcd_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_RS<='1';lcd_data<="10100000";--空格
when6=>LCD_RS<='1';lcd_data<="10100000";--空格
when7=>LCD_RS<='1';lcd_data<="10100000";--空格
when8=>LCD_RS<='1';lcd_data<=ram1(0);--秒表小时部分十位
when9=>LCD_RS<='1';lcd_data<=ram1
(1);--秒表小时部分个位
when10=>LCD_RS<='1';lcd_data<=ram1
(2);--冒号:
when11=>LCD_RS<='1';lcd_data<=ram1(3);--秒表分钟部分十位
when12=>LCD_RS<='1';lcd_data<=ram1(4);--秒表分钟部分个位
when13=>LCD_RS<='1';lcd_data<=ram1(5);--冒号:
when14=>LCD_RS<='1';lcd_data<=ram1(6);--秒表秒钟部分十位
when15=>LCD_RS<='1';lcd_data<=ram1(7);--秒表秒钟部分个位
when16=>LCD_RS<='1';lcd_data<=ram1(8);--小数点.
when17=>LCD_RS<='1';lcd_data<=ram1(9);--秒表十分秒位
when18=>LCD_RS<='1';lcd_data<=ram1(10);--秒表百分秒位
when19=>LCD_RS<='1';lcd_data<="10100000";-空格
when20=>LCD_RS<='1';lcd_data<="10100000";-空格
-----------------------------------------------------
when21=>LCD_RS<='0';lcd_data<="11000000";
--设定显示的位置在40H+80H,
-----------------------------------------------------
when22=>LCD_RS<='1';lcd_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";--空格
when31=>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_logic;
生成符号:
设计思路:
采用计数型防抖
当key_en第一次为'1'时,en_out延迟一段时间后变为'1',
并且en_out就此保持在高电平'1';
直到key_en第二次为'1'时,en_out延迟一段时间后变为'0'。
主要代码:
(完整代码请见源程序)
signalcnt:
integerrange0to3;--采用计数型防抖
signalen,en_tmp:
std_logic;
begin
p0:
process(clk)
begin
ifclk'eventandclk='1'then
ifkey_en='1'then
ifcnt=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_logic;
fuwei:
in
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 LCD1602 简易 秒表 设计 实现