完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
本帖最后由 april1314 于 2015-9-5 16:14 编辑
/******************************************************************* / / 模块功能:LCD1602显示测试 / /序号 指令 RS R/W D7 D6 D5 D4 D3 D2 D1 D0 / 1 清显示 0 0 0 0 0 0 0 0 0 1/ 2 光标返回 0 0 0 0 0 0 0 0 1 * / 3 置输入模式 0 0 0 0 0 0 0 1 I/D S / 4 显示开/关控制 0 0 0 0 0 0 1 D C B / 5 光标或字符移位 0 0 0 0 0 1 S/C R/L * * / 6 置功能 0 0 0 0 1 DL N F * * / 7 置字符发生存贮器地址 0 0 0 1 字符发生存贮器地址 / 8 置数据存贮器地址 0 0 1 显示数据存贮器地址 / 9 读忙标志或地址 0 1 BF 计数器地址 / 10 写数到CGRAM或DDRAM)1 0 要写的数据内容 / 11 从CGRAM或DDRAM读数 1 1 读出的数据内容 / / 第一行初始地址 1000_0000 / 第二行初始地址 1100_0000 / /******************************************************************/ module LCD_1602 ( input CLK, input RSTn, input SW1, input SW2, input SW3, input SW4, output LCD_EN, //使能信号 output LCD_RW, //读、写选择信号 output LCD_RS, //数据、命令选择信号 output LCD_BLON, //背光灯亮灭 output LCD_ON, //电源开关 output [7:0]Data //总线 ); // RS R/W D7 D6 D5 D4 D3 D2 D1 D0 parameter IDLE = 10'b00_0000_0000; //空闲 parameter CLEAR = 10'b00_0000_0001; //清屏 parameter RETURNCURSOR = 10'b00_0000_0010; //光标返回 归home位 parameter SETMODE = 10'b00_0000_0110; //输入方式设置 读写数据后ram地址增/减1,画面动/不动 //光标移动方向 I/D: 1右移 0左移 S: 屏幕上文字移动 1有效 0无效 parameter SWITCHMODE = 10'b00_0000_1111; //显示状态设置 1DCB D:控制整体显示的开与关 1开 0关 C:控制光标的开与关 1开 0关 //B:控制光标是否闪烁 1闪 0不闪 parameter SHIFT = 10'b00_0001_1000; //光标画面滚动 第四位S/C 第三位R/L S/C:画面/光标平移一位;R/L:左右/平移一位 parameter SETFUNCtiON = 10'b00_0011_1000; //设置功能 第五位DL:高电平时为4位总线,低电平时为8位总线 第四位N:低电平时为单行显示,//高电平时双行显示 第三位F:低电平时显示5x7的点阵字符,高电平时显示5x10的点阵字符 parameter SETCGRAM = 10'b00_0100_0000; //设置CGRAM 字符发生存贮器 parameter SETDDRAM1 = 10'b00_1000_0000; //设置DDRAM 数据存贮器 ===//第一行首地址 parameter SETDDRAM2 = 10'b00_1100_0000; //设置DDRAM 数据存贮器 ===//第二行首地址 parameter READFLAG = 10'b01_0000_0000; //设置度状态 正数第三位BF 高电平表示忙,此时模块不能接收命令或者数据,如果为低电平表示不忙 parameter WRITERAM1 = 10'b10_0000_0001; //设置写RAM parameter WRITERAM2 = 10'b10_0000_0010; //设置写RAM parameter READRAM = 10'b11_0000_0000; //读RAM assign LCD_ON = 1'b1; assign LCD_BLON = 1'b1; //======================产生1602时钟====================== parameter T0P2US = 19'd050000; reg [22:0]Cnt; reg CLK_500Hz; always@(posedge CLK or negedge RSTn) begin if(!RSTn) begin Cnt <= 19'd0; CLK_500Hz <= 1'b0; end else if(Cnt == T0P2US) begin Cnt <= 19'd0; CLK_500Hz <= ~CLK_500Hz; end else Cnt <= Cnt+1'b1; end assign LCD_EN = CLK_500Hz; //上升沿之后为高电平 使能有效 数据已稳定 //============================按键控制========================= reg[3:0]key_rst; always@(posedge CLK or negedge RSTn) begin if(!RSTn) key_rst <= 4'b1111; else key_rst <= {SW4,SW3,SW2,SW1}; end reg[3:0]key_rst_r; always@(posedge CLK or negedge RSTn) begin if(!RSTn) key_rst_r <= 4'b1111; else key_rst_r <= key_rst; end wire key_an; //抖动标志位 assign key_an = key_rst_r&(~key_rst); //边沿检测 reg [17:0] cnt_k; always @ (posedge CLK or negedge RSTn) begin if(!RSTn) cnt_k <= 18'd0; else if(key_an) cnt_k <= 18'd0; //一旦有抖动,计数器马上清零 else cnt_k <= cnt_k +1'b1; end reg [3:0] key; always @ (posedge CLK or negedge RSTn) begin if(!RSTn) key <= 4'b1111; else if(cnt_k == 18'd250000) //等待5ms,再记录按键状态 key <= {SW4,SW3,SW2,SW1}; end reg [3:0]key_r; always @ (posedge CLK or negedge RSTn) begin if(!RSTn) key_r <= 4'b1111; else key_r <= key; //送到二级锁存器 end wire [3:0] key_state = key_r& (~key); //边沿检测算法 //--------------------------时钟暂停---------------------------- reg flag; always @ (posedge CLK or negedge RSTn) begin if(!RSTn) flag <= 1'b1; else if(key_state == 3'b0001) // 如果键4按下,那么时钟暂停 flag <= ~flag; end //======================产生时分秒数值===================== parameter T1S = 26'd50000000; reg[25:0]Time_Cnt; reg[5:0]Second; reg[5:0]Minute; reg[4:0]Hour; reg[3:0]Second_H; reg[3:0]Minute_H; reg[3:0]Hour_H; reg[3:0]Second_L; reg[3:0]Minute_L; reg[3:0]Hour_L; always@(posedge CLK or negedge RSTn) begin if(!RSTn) begin Time_Cnt <= 26'd0; Second <= 6'd0; Minute <= 6'd0; Hour <=5'd0; end else if(flag == 1'b1) //================没有调整按键按下时================ begin if(Time_Cnt == 26'd50000000) begin Time_Cnt <= 26'd0; if(Second == 6'd59) begin Second <= 6'd0; if(Minute == 6'd59) begin Minute <= 6'd0; if(Hour == 5'd23) Hour <= 5'd0; else Hour <= Hour + 1'b1; end else Minute <= Minute + 1'b1; end else Second <= Second + 1'b1; end else Time_Cnt <= Time_Cnt + 1'b1; end else //================有调整按键按下时================ begin if(key_state == 4'b0010) begin if(Second == 6'd59) Second <= 6'd0; else Second <= Second + 1'b1; end if(key_state == 4'b0100) begin if(Minute == 6'd59) Minute <= 6'd0; else Minute <= Minute + 1'b1; end if(key_state == 4'b1000) begin if(Hour == 5'd23) Hour <= 5'd0; else Hour <= Hour + 1'b1; end end end //============================================================ always@(posedge CLK_500Hz or negedge RSTn) begin if(!RSTn) begin Second_H <= 4'd0; Second_L <= 4'd0; Minute_H <= 4'd0; Minute_L <= 4'd0; Hour_H <= 4'd0; Hour_L <= 4'd0; end else begin Second_H <= Second/10; Second_L <= Second%10; Minute_H <= Minute/10; Minute_L <= Minute%10; Hour_H <= Hour/10; Hour_L <= Hour%10; end end //========================LCD初始化以及数据显示控制========================= reg [9:0]STATE; reg LCD_RW_Reg; reg LCD_RS_Reg; reg [7:0]Data_Reg; reg [3:0]Cnt_T; always@(posedge CLK_500Hz or negedge RSTn) begin if(!RSTn) begin STATE <= IDLE; Data_Reg <= 8'd0; LCD_RS_Reg<= 1'b0; LCD_RW_Reg<= 1'b0; Cnt_T <= 4'd0; end else begin case(STATE) IDLE: begin STATE <= CLEAR; Data_Reg <= 8'bzzzz_zzzz; end CLEAR: begin STATE <= SETFUNCTION; LCD_RS_Reg <= 1'b0; LCD_RW_Reg <= 1'b0; Data_Reg <= 8'h01; end SETFUNCTION: begin STATE <= SWITCHMODE; LCD_RS_Reg <= 1'b0; LCD_RW_Reg <= 1'b0; Data_Reg <= 8'h38; end SWITCHMODE: begin STATE <= SETMODE; LCD_RS_Reg <= 1'b0; LCD_RW_Reg <= 1'b0; Data_Reg <= 8'h0c; end SETMODE: begin STATE <= SETDDRAM1; LCD_RS_Reg <= 1'b0; LCD_RW_Reg <= 1'b0; Data_Reg <= 8'h06; end SETDDRAM1: begin STATE <= WRITERAM1; LCD_RS_Reg <= 1'b0; LCD_RW_Reg <= 1'b0; Data_Reg <= 8'b1000_0000; end WRITERAM1: begin case(Cnt_T) 4'd0: //=========小时高========= begin LCD_RS_Reg <= 1'b1; LCD_RW_Reg <= 1'b0; Data_Reg <= Hour_H + 8'b0011_0000; STATE <= WRITERAM1; Cnt_T <= Cnt_T + 1'b1; end 4'd1: //=========小时低======== begin LCD_RS_Reg <= 1'b1; LCD_RW_Reg <= 1'b0; Data_Reg <= Hour_L + 8'b0011_0000; STATE <= WRITERAM1; Cnt_T <= Cnt_T + 1'b1; end 4'd2: //========冒号======== begin LCD_RS_Reg <= 1'b1; LCD_RW_Reg <= 1'b0; Data_Reg <= 8'b0011_1010; STATE <= WRITERAM1; Cnt_T <= Cnt_T + 1'b1; end 4'd3: //=========分钟高======== begin LCD_RS_Reg <= 1'b1; LCD_RW_Reg <= 1'b0; Data_Reg <= Minute_H + 8'b0011_0000; STATE <= WRITERAM1; Cnt_T <= Cnt_T + 1'b1; end 4'd4: //=======分钟低======== begin LCD_RS_Reg <= 1'b1; LCD_RW_Reg <= 1'b0; Data_Reg <= Minute_L + 8'b0011_0000; STATE <= WRITERAM1; Cnt_T <= Cnt_T + 1'b1; end 4'd5: //=========冒号======= begin LCD_RS_Reg <= 1'b1; LCD_RW_Reg <= 1'b0; Data_Reg <= 8'b0011_1010; STATE <= WRITERAM1; Cnt_T <= Cnt_T + 1'b1; end 4'd6: //=========秒高======== begin LCD_RS_Reg <= 1'b1; LCD_RW_Reg <= 1'b0; Data_Reg <= Second_H + 8'b0011_0000; STATE <= WRITERAM1; Cnt_T <= Cnt_T + 1'b1; end 4'd7: //===========秒低======== begin LCD_RS_Reg <= 1'b1; LCD_RW_Reg <= 1'b0; Data_Reg <= Second_L + 8'b0011_0000; STATE <= SETDDRAM1; Cnt_T <= 4'd0; end endcase end endcase end end assign LCD_RW = LCD_RW_Reg; assign LCD_RS = LCD_RS_Reg; assign Data = Data_Reg; endmodule |
|
相关推荐
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
1945 浏览 1 评论
助力AIoT应用:在米尔FPGA开发板上实现Tiny YOLO V4
1134 浏览 0 评论
3047 浏览 1 评论
2713 浏览 0 评论
矩阵4x4个按键,如何把识别结果按编号01-16(十进制)显示在两个七段数码管上?
3006 浏览 0 评论
2205 浏览 58 评论
6101 浏览 113 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-11 15:36 , Processed in 0.500848 second(s), Total 68, Slave 52 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号