该可编程器件实验板是以 Altera 公司的 MAX II 系列可编程器件
EPM1270T144C5 为核心芯片,是一款具有多种外部接口和显示器件的通用数字电路实验平台。选用1kHz。

一、 设计课题的任务要求

1、 智能药盒有三个药格,分别对应老年人每天早中晚的三次服药,每个药格有对应的提醒灯。按下BTN0 键进入开机初始状态,三个药格的提醒灯在 8×8 点阵中显示红、绿、黄图案。
2、 三个药格可通过 BTN7 键切换设定服药时间,切换到哪个药格,相应药格的提醒图案以 2Hz 的频率进行闪烁显示。服药时间的设定采用 BTN6 和 BTN5 键,BTN6 每按 1 下,时间加 1 秒,BTN5 每按 1 下,时间减 1 秒,每个药格可设定一个时间,设定时间范围在 0~59 秒之间,在设定过程中采用数码管 DISP1 和 DISP0 显示所设定的服药时间。
3、 服药时间设定结束后,按下智能药盒工作键 BTN2 后,药格提醒图案停止闪烁,药 盒开始工作,并从 0 开始进行 60 秒计时,数码管 DISP1 和 DISP0 显示计时时间。当计时计到各个药格所设定的服药时间时,点阵上相应药格的提醒图案以 4Hz 的频率进行闪烁提醒,同时蜂鸣器报警,按 BTN1 键后报警和闪烁停止。
4、 智能药盒计到 60 秒后重复开始服药计时和提醒,直到按下 BTN0 键后智能药盒关闭,点阵全灭,计时停止。
提高要求:
1、 用 4*4 小键盘设定服药时间;
2、 采用液晶 LCD1602 显示设定的服药时间;
3、 增加高级模式,每个药格可设定 1~2个服药时间进行提醒; 4、 自拟其他功能。

二、 系统设计

  1. 设计思路
    该智能药盒类似于一个闹钟,也就是计时器。核心内容就是设定几个时间,然后计时到所设定的时间时报警。8×8 点阵用于显示药格,数码管显示时间,蜂鸣器报警。

  2. 总体框图

  3. 分块设计
    1). 计时与计数:这是实验的核心内容。由于计时和计数都涉及到对时间的操作,因此这两个功能必须集合到同一个模块并且是同一个always块里。刚开机后,药盒应处于计数状态,用来设定时间;按下BTN2后进入计时状态,开始60秒循环计时。所以使用一个work信号来控制计时与计数的切换。work初始为0,对应计数状态,按BTN2使work翻转,状态切换。计数时按BTN4获取当前时间值并输出,在这个模块的外部会有其他模块负责将这个获取的时间存起来。这里需要注意获取时间和存储时间的先后问题,否则会存入无效时间。因此,选择在时钟上升沿获取时间,然后在按键信号下降沿存储,二者相差一个时钟周期。
    2). 8*8点阵显示:点阵用红、绿、黄分别表示3个药格。在设定时间以及报警时都要求对应的点阵要闪烁,因此,它可以分为4种状态:都不闪,红色闪,绿色闪,黄色闪。这样我们就可以用一个2位的二进制数来表示它们:00,01,10,11.同时选用BTN7驱动模4计数器,按一下,二进制数加一,状态切换,这样就实现了药格切换。药格的显示是采用行扫描的形式,由于只扫描2行,所以将行扫描信号和时钟信号绑定,当时钟为高电平时,扫第3行,时钟为低电平时扫第4行,这样之后就不用重复对行信号进行处理了。
    3). 数码管显示:由于只用两个数码管,所以将数码管的阴极信号与时钟绑定,当时钟为高电平时,亮十位的数码管,同时阳极信号赋值为时间的十位,时钟为低电平时亮个位的数码管,同时阳极信号赋值为时间的个位,这样就完成了数码管的显示。

三、 功能说明及资源利用情况
1.功能说明
该药盒实现了课题要求的基本功能,包括按BTN0开机关机,按BTN7切换设定服药时间,切换时,对应的药格会以2Hz闪烁。按BTN6和BTN5可分别实现加计数和减计数,按下BTN4即可保存时间。之后,按下BTN2便可进入计时工作状态。药盒能够循环进行60秒计时,当到达设定的时间后,对应药格4Hz闪烁,同时蜂鸣器报警。报警和闪烁可按下BTN1手动关闭,或者计时到60秒后自动关闭。按下BTN2又可切换到设定时间状态,设定新的时间。再按下BTN0后,药盒关机,数据清空。此外,还实现了提高功能之一,即每个药盒可以设定一到两个时间。
2.资源利用情况
总共使用了200个逻辑门和50个管脚。

四、 故障及问题分析
1.在代码编写过程中,运行代码调试时,经常报错说重复赋值。比如计数与计时重复对时间负值;关机将数据清零时,又对这些数据重复进行了赋值。所以,需要将这些对变量的赋值都综合到对应的同一个模块里,以此避免冲突。
2.在测试功能的时候,发现保存的时间总是会出现错位。分析发现是获取时间与存储时间同时进行导致的。在获取时间的同时存时间,存储的并不是获取的时间,而是初始化的0时间,然后在下一次存时间时,才会存储这次获取的时间,也就是发生了错位。因此,选择在时钟上升沿获取时间,然后在按键信号下降沿存储,二者相差一个时钟周期。这样错开后,功能正常实现。
3.在测试功能时,发现在刚开始计时时就报警。分析发现,原本能设置两个时间的药格,如果只设置一个时间,剩下的那个时间就会保持初始化的0时间,这样刚开始计时就会报警。因此,增加一个判断条件,来取消对初始0时间的报警。

module imbox(        //上层模块  input   clk,      //时钟信号,需选用1kHz  input   btn0,       //开机关机键  input   btn1,       //关闭报警键  input   btn2,       //开始或停止计时  input   btn4,       //保存时间  input   btn5,       //减计数键  input   btn6,       //加计数键  input   btn7,   //切换药格键  output  [7:0]col_r,     //8*8点阵的列信号,红色  output  [7:0]col_g,     //8*8点阵的列信号,绿色  output  beep,              //蜂鸣器  output  [7:0] seg,      //数码管阳极信号  output reg [7:0] row,   //8*8点阵的行信号,用于进行行扫描  output reg [7:0] cat,   //数码管阴极信号   output  led         //led灯,在BTN4按下时响应  );wire [1:0] change;    //药格切换信号  reg  [1:0] remind;      //报警状态下的药格信号  wire clk_2, clk_4,clk_500;      //不同频率的时钟  wire key0, key1, key2, key4, key5, key6, key7;  //消抖后的按键信号  reg  clk_2_r,clk_500_r, work,start,rmd; //生成时钟的中间量;工作、开始、提醒信号  wire [5:0] total;           //计数与计时  wire [5:0] time_e;      //获取设定时间  reg  [11:0] timee [2:0];    //存储设定时间  reg  [3:0] data;            //数码管显示的数据  wire [3:0] data1, data2;        //时间的十位和个位  always@(posedge key0)   //开机于关机  begin  start<=~start;  end  divide d0(clk,clk_4);      //时钟分频  always@(posedge clk_4)  clk_2_r<=~clk_2_r;  assign clk_2=clk_2_r;     always@(posedge clk)  clk_500_r<=~clk_500_r;  assign clk_500=clk_500_r;  always@(clk)      if(~start)  //关机状态  begin  row<=8'b11111111;  cat<=8'b11111111;  end  else if(clk)        //将row,cat,data与时钟绑定,随时钟变化而自动扫描  begin  row<=8'b11101111;  cat<=8'b11111101;  data<=data1;  end  else  begin  row<=8'b11110111;  cat<=8'b11111110;  data<=data2;  end  always@(negedge clk)    if(~start)  work<=0;  else if(key2)   //非工作工作(计数与计时切换)  work<=~work;  else  work<=work;  always@(negedge key4 or posedge key0)     if(key0)  begin  timee[0][11:0]<=0;  timee[1][11:0]<=0;  timee[2][11:0]<=0;  end  else if(change>0)  timee[change-1][11:0]<={timee[change-1][5:0],time_e};  //移位寄存设定的时间  //按键消抖  debounce d1(clk,{btn0,btn1,btn2,btn4,btn5,btn6,btn7},{key0,key1,key2,key4,key5,key6,key7});//切换药格  counter4 c1(start,key7,change);  //8*8点阵显示  show s0(col_r,col_g,clk,clk_500,((work&rmd)?clk_4:clk_2),((work&rmd)?remind:change));//计数与计时  timer t0(start,work,clk,key6,key5,key4,key2,led,total,time_e);  //计算十位和个位  div_rill d2(total,data1,data2);   //数码管显示  segment s1(clk,data,seg);  //控制报警  always@(posedge clk )  if(key1|key0|(~start)|(~work))  rmd<=0;  else  case(total)   timee[0][11:6]:begin remind<=2'b01;rmd<=timee[0][11:6];end//  timee[0][5:0] :begin remind<=2'b01;rmd<=1;end  timee[1][11:6]:begin remind<=2'b10;rmd<=timee[1][11:6];end//  timee[1][5:0] :begin remind<=2'b10;rmd<=1;end  timee[2][11:6]:begin remind<=2'b11;rmd<=timee[2][11:6];end//  timee[2][5:0] :begin remind<=2'b11;rmd<=1;end   default:begin remind<=remind;rmd<=rmd;end  endcase           assign beep=rmd&clk;        //蜂鸣器报警  endmodule  //计数与计时  module timer (  input start,        //开始信号(开机或关机)  input work,         //工作信号(计数或计时)  input clk1,         //时钟  input key6,         //加计数  input key5,         //减计数  input key4,         //保存时间  input key2,         //切换计数与计时  output reg led, //用于响应key4  output reg [5:0]total,  //时间  output reg [5:0]time_e  //获取设定的时间用以保存  );  reg           [9:0] cnt;  always @(posedge clk1)  if((~start)|key2)  total<=6'b000000;  else if(~work)         begin  if (key6&(total<59))    total <= total+1'b1;     //计数  else if (key5&(total>0))  total <= total-1'b1;  else if(key4&(total>0))  begin   time_e<=total;       //获取设定的时间用以保存  led<=key4;  end  else  begin  total <= total;  led<=0;  end  end   else if (cnt==999)        begin  cnt<=0;  if(total==60)  total<=1'b0;  else  total<=total+1'b1;   //计时  end  else   cnt<=cnt+1;                            endmodule  //数码管显示  module segment(  input clk,      //时钟  input [3:0]data,    //数码管阳极  output reg [7:0]seg //数码管  );  always @(clk)             case (data)     //将阳极的数据译码显示为数字  4'b0000: begin seg<=8'h3f;end              4'b0001: begin seg<=8'h06;end              4'b0010: begin seg<=8'h5b;end              4'b0011: begin seg<=8'h4f;end          4'b0100: begin seg<=8'h66;end              4'b0101: begin seg<=8'h6d;end  4'b0110: begin seg<=8'h7d;end  4'b0111: begin seg<=8'h07;end  4'b1000: begin seg<=8'h7f;end  4'b1001: begin seg<=8'h6f;end  endcase  endmodule  //除法和取余(二进制转十进制)  module div_rill    (    input      [5:0] a,   //需要处理的二进制数  output reg [3:0] yshang,  //十位(除以十后的商)  output reg [3:0] yyushu  //个位(除以十后的余数)  );   reg[5:0] tempa;      reg[8:0] temp_a;      integer i;          always @(a )      tempa <= a;       always @(tempa)    begin    temp_a = {3'b000,tempa};      for(i = 0;i < 3;i = i + 1)    begin    temp_a = {temp_a[7:0],1'b0};    if(temp_a[8:3] >= 4'b1010)    temp_a = temp_a - 7'b1010000 + 1'b1;    else    temp_a = temp_a;                       end         yshang <= {1'b0,temp_a[2:0]};    yyushu <= temp_a[6:3];    end    endmodule  //8*8点阵显示  module show(  output reg[7:0]col_r,   //8*8点阵的列信号,红色  output reg[7:0]col_g,   //8*8点阵的列信号,绿色  input clk,      //1kHz时钟  input clk500,   //500Hz,让橙色和绿色交替,从而调出黄色  input clkout,   //闪烁时钟,调用时的参数可在2Hz和4Hz间切换  input [1:0]cnt //药格信号,切换药格  );  always @ (clk)  if(clkout)  case (clk500)     0: begin col_r<=8'b00000011;col_g<=8'b11011000; end //绿|绿|红  1: begin col_r<=8'b11000011;col_g<=8'b11011000; end //橙|绿|红(上面的绿色与下面的橙色叠加出黄色)  endcase  else  case(cnt)  2'b00:begin  case (clk500)          //初始状态         0: begin col_r<=8'b00000011;col_g<=8'b11011000; end  1: begin col_r<=8'b11000011;col_g<=8'b11011000; end  endcase  end  2'b01:begin  case (clk500)          //红灯闪烁  0: begin col_r<=8'b00000000;col_g<=8'b11011000; end  1: begin col_r<=8'b11000000;col_g<=8'b11011000; end     endcase  end  2'b10:begin       case (clk500)           //绿灯闪烁  0: begin col_r<=8'b00000011;col_g<=8'b11000000; end  1: begin col_r<=8'b11000011;col_g<=8'b11000000; end     endcase  end  2'b11:begin  case (clk500)         //黄灯闪烁  0: begin col_r<=8'b00000011;col_g<=8'b00011000; end  1: begin col_r<=8'b00000011;col_g<=8'b00011000; end         endcase  end  endcase   endmodule  //模4计数(分别对应3个药格和初始状态,用来控制切换药格)  module counter4 (  input start,    //开机信号  input btn,      //按键计数  output reg [1:0]count   //模4计数  ) ;  always @ (posedge btn or negedge start)  if(~start)   count<=2'b00;      else if(count==2'b11)  count<=2'b00;  else   count<=count+1'b1;  endmodule  //时钟分频  module divide (clk,clkout);  input      clk;              //输入时钟  output     clkout;           //输出时钟  reg           [6:0] cnt_p;      //cnt_p为上升沿触发的计数器  reg         clk_p;            //clk_p为上升沿触发的分频时钟  always @ (posedge clk )                                                                 begin  if (cnt_p==124)         //250分频,1kHz转4Hz  begin  cnt_p<=0;  clk_p<=~clk_p;  end  else   cnt_p<=cnt_p+1;               end  assign clkout = clk_p;        endmodule   //按键消抖  module debounce (                     input           clk,        //时钟  input   [6:0]   key,    //需要消抖的按键                              output  [6:0]   key_pulse   //消抖后的按键信号  );    reg     [6:0]   key_rst_pre;  //按键前一状态               reg     [6:0]   key_rst;      //按键当前状态            wire    [6:0]   key_edge;     //按键上升沿检测                        reg     [6:0]   key_sec_pre;  //按键前一电平状态               reg     [6:0]   key_sec;        //按键后一电平状态  reg   [3:0]  cnt;               //计数  always @(posedge clk )  begin      key_rst <= key;                       key_rst_pre <= key_rst;                          end  assign  key_edge = (~key_rst_pre) & key_rst; //检测上升沿  always @(posedge clk )  begin  if(key_edge)                     cnt <= 4'b0000;  else  cnt <= cnt + 1'b1;  end    always @(posedge clk)          if (cnt==4'b1010)    //延时10ms后检测电平  key_sec <= key;  else  key_sec<=key_sec;  always @(posedge clk)   key_sec_pre <= key_sec;                  assign  key_pulse = (~key_sec_pre) & key_sec;     endmodule

【Verilog智能药盒的设计与实现】相关推荐

  1. 特别提醒蓝牙语音智能药盒的设计思路(二)TTS技术应用篇,附手机小程序界面

    全文3000字,阅读时间约8分钟,建议收藏后慢慢看 目录 引言 蓝牙TTS智能药盒方案系统图 智能药盒是什么 智能药盒为什么需要语音提醒 语音提醒功能为什么要用TTS技术 TTS语音提醒的应用场景 1 ...

  2. 嵌入式单片机智能药盒设计(含代码)

    目录 前言 设计的内容 (1)显示 (2)定时时间与用药量的设定 (3)实时时间调节 (4)报警功能 时钟模块 蓝牙模块 系统软件设计 系统主程序 按键函数 中断服务函数 作品展示 测试药定时提醒功能 ...

  3. 基于stm32的智能药盒

    提示:记录毕设 文章目录 前言 一.任务书 1.1设计(研究)目标: 1.2设计(研究)内容: 二.框架思路 三.硬件及代码 四.相关功能介绍 五.交流联系 六.喜欢请点赞哦! 前言 基于STM32的 ...

  4. 智能手环功能模块设计_智能手环的设计的方案.doc

    智能手环的设计的方案 智能手环的设计的方案 摘 要 本手环设计本身添加了市面上智能手环的相关功能,能够实现显示时间.测量步数.热量.闹钟等功能.因此本设计也适用于普通的使用者,在能够拥有智能手环的便捷 ...

  5. 天津大学计算机课程设计挂,《天津大学_智能装置课程设计报告》.doc

    智能装置课程设计报告 一.设计题目 空调控制系统 二.设计目的 1. 深入了解PIC16F877单片机的工作原理,熟练掌握汇编语言程序设计方法,熟练使用MPLAB-ICD仿真器及MPLAB-IDE仿真 ...

  6. 《智能家居产品 从设计到运营》——第2章 技术搭台——与智能家居相关的技术...

    本节书摘来异步社区<智能家居产品 从设计到运营>一书中的第2章,作者:邢袖迪,更多章节内容可以访问云栖社区"异步社区"公众号查看 第2章 技术搭台--与智能家居相关的技 ...

  7. python做商品推荐系统_一种商品智能推荐系统的设计的制作方法

    一种商品智能推荐系统的设计,其技术领域涉及web技术.Java语言的开发和数据库的建立. 背景技术: 近年来,互联网信息的增长十分迅速,基于电子商务模式的商品销售已经变得十分普及,如何为如此庞大的商品 ...

  8. Android 腾讯入门教程( 智能手表UI设计 和 MVC模式 )

    *****注意到mvc 在android 中是如何进行分层分域执行各自的功能.**** 官方推荐的按钮尺寸是48像素 前端之Android入门(1):环境配置 前端之Android入门(2):程序目录 ...

  9. 基于verilog贪吃蛇游戏设计

    概述 基于verilog贪吃蛇游戏设计.使用verilog语言 小游戏主要分为以下几个模块:顶层模块.VGA显示模块.蛇身控制模块.苹果控制模块. 系统主要分为顶层模块.VGA显示模块.蛇身控制模块. ...

最新文章

  1. 掌握 Ajax,第 7 部分: 在请求和响应中使用 XML
  2. 数据库并发控制,选择乐观锁还是悲观锁?
  3. linux 硬软链接区别
  4. ElasticSearch5.x实践_day05_03_Mapping_Meta-Fields
  5. How to trouble shoot if there is no entityset available when creating a tile
  6. .bash_profile vs .bashrc
  7. CSS那些不大不小的事
  8. 过滤器实栗 登录检测
  9. 解析IP代理软件市场上的发展现状
  10. 前端实现自定义表情【微信表情】
  11. python二元一次方程组用鸡兔同笼的思路来写编程_应用二元一次方程组——鸡兔同笼教学设计...
  12. Filter vs Listener
  13. 计算机设置休眠密码,win10系统如何设置电脑待机密码?windows10设置待机密码图文教程...
  14. 解决Mac book pro (M1芯片)电脑打开idea卡顿,cpu飙升的问题。
  15. python gevent async_谈谈Python协程技术的演进
  16. 搭建react项目教程(二)
  17. 动态循环数组(ArrayList优化)
  18. css3 新属性的兼容性之--transform
  19. 生态流量监测管理系统
  20. 高中数学知识点-高考回归课本的100个问题(实用干货)

热门文章

  1. acm——男人的承诺
  2. S5PV210-裸机中断
  3. vue脚手架实现留言板功能
  4. php怎么建留言本,php实现留言板功能的详细代码
  5. 多官能度可聚会型光引发剂(图文说明)
  6. Java中生产者和消费者总结
  7. python mse函数_Python 线性回归处理糖尿病数据 计算MSE等
  8. 权限管理中的RBAC与ABAC
  9. python猫狗大战游戏下载_猫狗大战RPG最新下载-猫狗大战RPG游戏安卓版-Minecraft中文分享站...
  10. [BZOJ2539][CTSC2000][KM]丘比特的烦恼