集成电路技术分享

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
查看: 2303|回复: 4

LCD1602的时钟显示

[复制链接]
FPGA_one 发表于 2017-7-22 10:11:07 | 显示全部楼层 |阅读模式
//***********************************************************
//**********************小墨笔记*****************************

//简易动态可调电子钟设计
//实现时钟在1602上动态显示且可调

module lcd1602(clk,rst_n,rs,wr,lcden,data,sw1,sw2,sw3,sw4);

input clk ;  //输入时钟50Mhz
input rst_n;  //复位信号
input sw1,sw2,sw3,sw4; //输入四个独立按键
output rs;    //1602数据命令选择端
output wr;    //读写控制端
output lcden;  //使能信号控制端
output [7:0]data;   //8位数据总线


reg rs,lcden;
reg [7:0]data;
assign wr = 0;
//---------------------------分频模块---------------------------

reg clkr;
reg [17:0] cnt;
always @ (posedge clk or negedge rst_n) begin  //产生1602时钟
    if(!rst_n)  begin
            cnt <= 18'd50000;
                 clkr <= 0;
                 end
         else if(cnt == 18'd50000) begin
              clkr <= ~clkr;
                        cnt <= 18'd0;
         end
         else cnt<= cnt + 1'b1;

end

//------------------------状态机控制液晶初始化模块--------------------------
parameter
         s0  = 5'd0,
                        s1  = 5'd1,
                        s2  = 5'd2,
                        s3  = 5'd3,
                   s4  = 5'd4,
                   s5  = 5'd5,
                   s6  = 5'd6,
                   s7  = 5'd7,
                   s8  = 5'd8,       
                        s9  = 5'd9,
                        s10 = 5'd10,
                        s11 = 5'd11,
                        s12 = 5'd12,
                        s13 = 5'd13,
                        s14 = 5'd14,
                        s15 = 5'd15,
                        s16 = 5'd16,
                        s17 = 5'd17,
                        s18 = 5'd18,       
                        s19 = 5'd19,
                        s20 = 5'd20,
                        s21 = 5'd21,
                        s22 = 5'd22,
                        s23 = 5'd23,
                        s24 = 5'd24,
                        s25 = 5'd25,
                        s26 = 5'd26;
                       
                       
reg [4:0] state;
reg init_over;   //液晶初始化完成标志位

always @ (posedge clkr or negedge rst_n)  begin
   if(!rst_n) begin           //上电复位初始化
           rs <= 1'b1;
                lcden <= 1'b0;
                data <= 8'd0;
                state <=4'd0;
                       
        end
       
        else case (state)
             s0 : begin            
                        rs <= 0;
                                  lcden <= 0;
                                  data <= 8'h38;  //送数据,设置16 x 2显示,5 X 7点阵,8位数据接口
                                  state <= s1;
                  end                                    
                  s1:  begin           //数据有效
                        lcden <= 1;
                                  state <= s2;
                  end                                    
                  s2 : begin
                       lcden <= 0;
                                 data <= 8'h0c;  // 开显示,显示光标,光标闪烁
                                 state <= s3;
                  end
                  s3 : begin
                       lcden <= 1;
                                 state <= s4;
                  end
                  s4 : begin
                         lcden <=0;
                                        data <= 8'h06;  // 写一个字符后地址指针加1
                                        state <= s5;
                  end
                  s5 : begin
                         lcden <= 1;
                                        state <= s6;
                  end
                  s6 : begin
                         lcden <= 0;
                                        data <= 8'h01;   // 显示清0,数据指针清0
                                        state <= s7;
                  end
                  s7 : begin
                        lcden <= 1;       
                        state <= s8;       
                             init_over <=1;                //初始化结束标志位          
                  end
//---------------------------------1602初始化结束-----------------------------               
                  s8 : begin
                        lcden <= 0;
                                  data <= 8'h84;   
                                  state <= s9;
                  end
                  s9 : begin
                        lcden <= 1;
              state <= s10;       
                   
                  end
          
                  
                  s10 : begin
                        rs <= 1;          //改为写数据状态
                        lcden <= 0;
                                  data <= shi_s+8'h30;    //写小时的十位
                                  state <= s11;
                  end
                  s11 : begin
                         lcden <= 1;
                                        state <= s12;
                  end
                  s12 : begin                                  
                        lcden <=0;
                                  data <= shi_g+8'h30;    //写小时的个位
                                  state <= s13;
                  end
                  s13 : begin
                        lcden <= 1;
                                  state <= s14;
                  end
                  s14 : begin                         
                        lcden <= 0;
                                  data <= ":";      //写冒号
                                  state <= s15;
                                  
                  end
                  s15 : begin
                        lcden <= 1;
                                  state <= s16;
                  end

                  s16 : begin
                        lcden <= 0;
                                  data <= fen_s+8'h30;  //写分钟的十位
                                  state <= s17;
                  end
                  s17 : begin
                        lcden <= 1;
                                  state <= s18;
                  end
                  s18 : begin
                        lcden <= 0;
                                  data <= fen_g+ 8'h30;  //写分钟的个位
                                  state <= s19;
                  end
                  s19 : begin
                        lcden <= 1;
                                  state <= s20;
                  end
                  s20 : begin
                        lcden <= 0;
                                  data <= ":";    //写冒号
                                  state <= s21;
                  end
                  s21 : begin
                        lcden <= 1;
                                  state <= s22;
                  end
                  s22 : begin
                        lcden <= 0;
                                  data <= miao_s+ 8'h30;   //写秒钟的十位
                                  state <= s23;
                  end
                  s23 : begin
                        lcden <= 1;
                                  state <= s24;
                  end
                  s24 : begin
                        lcden <= 0;
                                  data<= miao_g + 8'h30;    //写秒钟的个位
                                  state <= s25;
                  end
                  s25 : begin
                        lcden <= 1;
                                  state <= s26;
                                  
                  end
                  s26 : begin
                        lcden <= 0;
                                  state <= s8;          //回到写起始地址的状态,来回刷新
                                  rs <= 0;
                  end
                  default : begin
                            rs <= 1'b1;                                       
                                                lcden <= 1'b0;
                                                data <= 8'd0;
                                                state <= 0;
                  end

        endcase
end

//-------------------------------时分秒产生模块---------------------------------

reg [5:0] shi;
reg [5:0] fen;
reg [5:0] miao;
reg [25:0] cntr;  // 产生1秒钟的时钟,要计数到50_000_000;
always @ (posedge clk or negedge rst_n)begin
    if(!rst_n) begin
            shi <= 6'd18;               //设置初始时间
                                fen<= 6'd22;
                                miao <= 6'd36;
                                cntr <= 26'd0;
         end
         else  if(init_over ==1'b1 && flag ==1'b1)begin
                          if(cntr == 26'd50000000) begin
                                         cntr <= 26'd0;
                                         miao <= miao + 1'b1;
                                                 if(miao == 6'd59) begin
                                                          miao <= 6'd0;
                                                          fen <= fen +1'b1;
                                                                  if(fen == 6'd59)begin
                                                                          fen <= 6'd0;
                                                                          shi <= shi +1'b1;
                                                                          if(shi == 6'd23)
                                                                                  shi <= 6'd0;
                                                                  end
                                                 end
                                 
                         end
                    else cntr <= cntr+1'b1;
         end
         
         else if(key_state == 4'b1000)  begin
              miao <= miao + 1'b1;  //如果键1按下,那么调整秒针
                        if(miao == 6'd59) miao <= 6'd0;
                        end
         else if(key_state == 4'b0100)  begin
               fen <= fen +1'b1;         //如果键2按下,那么调整分针
                         if(fen == 6'd59) fen <= 6'd0;
                         end
         else if(key_state == 4'b0010)   begin
               shi <= shi +1'b1;   //如果键3按下,那么调整时针
                         if(shi == 6'd23) shi <= 6'd0;
                         end


end

//--------------------------------时分秒处理模块----------------------------

wire [3:0]miao_s;   
wire [3:0]miao_g;

wire [3:0]fen_s;
wire [3:0]fen_g;

wire [3:0] shi_s;
wire [3:0] shi_g;

//对时分秒进行求模求余运算
assign miao_s = miao /10;   
assign miao_g = miao %10;
assign fen_s = fen /10;
assign fen_g = fen %10;
assign shi_s = shi /10;
assign shi_g = shi %10;

//-----------------------------按键消抖部分----------------------------------
reg [3:0]key_rst;

always @ (posedge clk or negedge rst_n)  begin
    if(!rst_n) key_rst <= 4'b1111;
         else key_rst <= {sw4,sw3,sw2,sw1};                     //将按键状态送给第一级锁存器锁存                   
end

reg [3:0] key_rst_r;   //定义二级锁存器

always @(posedge clk or negedge rst_n) begin
    if(!rst_n) 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 rst_n) begin
   if(!rst_n) 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 rst_n) begin
   if(!rst_n) 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 rst_n) begin
   if(!rst_n) key_r <= 4'b1111;
        else key_r <= key;   //送到二级锁存器
end

wire [3:0] key_state = key_r& (~key); //边沿检测算法

//--------------------------时钟暂停----------------------------
reg  flag;

always @ (posedge clk or negedge rst_n) begin
   if(!rst_n) flag <= 1'b1;
        else if(key_state == 3'b0001)   //  如果键4按下,那么时钟暂停
           flag <= ~flag;
       
end

endmodule
fpga_wuhan 发表于 2017-7-22 11:53:43 | 显示全部楼层
LCD1602的时钟显示
小舍YZ 发表于 2017-7-22 16:37:55 | 显示全部楼层
赞,,,,,,,,,,,,,,,,,,谢谢分享。。。。。。。。。。。。。。。。。。。。
奋斗的小孩 发表于 2017-7-23 10:05:44 | 显示全部楼层
挺不错的呀
fpga_feixiang 发表于 2024-11-8 14:32:10 | 显示全部楼层
6                             
您需要登录后才可以回帖 登录 | 我要注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

QQ|小黑屋|手机版|Archiver|fpga论坛|fpga设计论坛 ( 京ICP备20003123号-1 )

GMT+8, 2024-11-23 07:43 , Processed in 0.059681 second(s), 20 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表