这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » LCD1602 作业

共4条 1/1 1 跳转至

LCD1602 作业

助工
2014-06-30 22:32:26     打赏

交一下LCD1602的作业。

这次学到了不少,刚开始自己听完课之后,看着数据手册,写完了代码,慢慢编译过来,成功了一大部分,最后的两个状态转换搞错了,后来跟51FPGA 大神的源代码进行比较,根据他的正确代码一点点纠正状态机的源代码,结果,跟51FPGA 大大的几乎一样了。不过还是学到了很多。

以下是源代码:

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: Charles Wang 
// 
// Create Date:    06/23/2014 
// Design Name: 	lcd1602_clock
// Module Name:   lcd1602_clock
// Project Name: 	lcd1602_clock
// Target Devices: EP4CE6E22C8
// Tool versions: Quartus II 13.1 
// Description: 用LCD1602显示数字时钟
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//			
//////////////////////////////////////////////////////////////////////////////////
module lcd1602_clock(clk,rst_n,lcd_en,lcd_rs,lcd_rw,lcd_data);
input clk;
input rst_n;

output lcd_en;
output lcd_rs;
output lcd_rw;
output [7:0]lcd_data;

reg lcd_rs;
reg [7:0]lcd_data;
reg clk_div;
reg [4:0]char_cnt;
reg [9:0]state;
reg [17:0]delay_cnt;
reg [7:0]lcd_data_r;
parameter	idle 				=10'b00_0000_0001,
				clear				=10'b00_0000_0010,
				set_function	=10'b00_0000_0100,
				switch_mode		=10'b00_0000_1000,
				set_mode			=10'b00_0001_0000,
				shift				=10'b00_0010_0000,
				set_ddram1		=10'b00_0100_0000,
				set_ddram2		=10'b00_1000_0000,
				write_ddram1	=10'b01_0000_0000,
				write_ddram2	=10'b10_0000_0000;
assign lcd_en = clk_div;
assign lcd_rw = 1'b0;
///////////////////////////////////////////////////////////////////////////////
always@(posedge clk or negedge rst_n)
	begin
		if(!rst_n)
			begin
				delay_cnt <= 18'h0;
				clk_div	 <= 1'b0;
			end
		else if(delay_cnt == 18'd249999)
			begin
				delay_cnt <= 18'h0;
				clk_div	 <= ~ clk_div;
			end
		else
			begin
				delay_cnt <= delay_cnt + 1'b1;
				clk_div	 <= clk_div;
			end
	end
////////////////////////////////////////////////////////////////////////////////
always@(posedge clk_div or negedge rst_n)//状态机模块
	begin
		if(!rst_n)
			begin
				state <= idle;
				char_cnt<= 5'd0;
			end
		else 
			case(state)
				idle: 									//起始状态
					begin
						lcd_data	<=	8'bzzzz_zzzz;
						state		<=	clear;
					end
				clear:									//清屏
					begin	
						lcd_rs	<=	1'b0;
						lcd_data	<=	8'b0000_0001;
						state 	<=	set_function;
					end
				set_function:							//功能设置:8位数据接口/2行显示/5*8点阵字符
					begin
						lcd_rs	<=	1'b0;
						lcd_data	<=	8'b0011_1000;
						state		<=	switch_mode;
					end
				switch_mode:							//开关模式:开显示,关闭光标和闪烁
					begin
						lcd_rs	<=	1'b0;
						lcd_data	<=	8'b0000_1100;
						state		<=	set_mode;
					end
				set_mode:								//输入方式:数据读写操作后,地址自动加一/画面不动
					begin
						lcd_rs	<= 1'b0;
						state 	<= shift;
						lcd_data <= 8'b0000_0110;
					end
				shift:
					begin
						lcd_rs	<=	1'b0;
						lcd_data	<=	8'b0001_0000;
						state		<=	set_ddram1;
					end
				set_ddram1:
					begin
						lcd_rs	<=	1'b0;
						lcd_data	<=	8'b1000_0000;
						state		<=	write_ddram1;
					end
				set_ddram2:
					begin
						lcd_rs	<=	1'b0;
						lcd_data	<=	8'b1100_0000;
						state		<=	write_ddram2;
					end
				write_ddram1:
					begin
						if(char_cnt	<=	5'd15)
							begin
								lcd_rs	<=	1'b1;
								char_cnt	<=	char_cnt +	1'b1;
								lcd_data	<=	lcd_data_r;
								state		<=	write_ddram1;
							end
						else
							state	<=	set_ddram2;
					end
				write_ddram2:
					begin
						if(char_cnt	<=	5'd30)
							begin
								char_cnt	<=	char_cnt	+ 	1'b1;
								lcd_rs	<=	1'b1;			
								lcd_data	<=	lcd_data_r;
								state		<=	write_ddram2;
							end
						else
							begin
								char_cnt <= 5'd0;
								state	<=	shift;
							end
					end
				default:
					state	<=	idle;
			endcase
	end
always@(char_cnt)										//显示相关字符
	begin
		case(char_cnt)
			5'd0:			lcd_data_r	<=	"D";
			5'd1:			lcd_data_r	<=	"e";
			5'd2:			lcd_data_r	<=	"s";
			5'd3:			lcd_data_r	<=	"i";
			5'd4:			lcd_data_r	<=	"g";
			5'd5:			lcd_data_r	<=	"n";
			5'd6:			lcd_data_r	<=	" ";
			5'd7:			lcd_data_r	<=	"b";
			5'd8:			lcd_data_r	<=	"y";
			5'd9:			lcd_data_r	<=	" ";
			5'd10:		lcd_data_r	<=	"C";
			5'd11:		lcd_data_r	<=	"h";
			5'd12:		lcd_data_r	<=	"a";
			5'd13:		lcd_data_r	<=	"r";
			5'd14:		lcd_data_r	<=	"l";
			5'd15:		lcd_data_r	<=	"e";
			5'd16:		lcd_data_r	<=	" ";
			5'd17:		lcd_data_r	<=	"T";
			5'd18:		lcd_data_r	<=	"i";
			5'd19:		lcd_data_r	<=	"m";
			5'd20:		lcd_data_r	<=	"e";
			5'd21:		lcd_data_r	<=	":";
			5'd22:		lcd_data_r	<=	" ";
			5'd23:		lcd_data_r	<=	hour_reg_dec_char;
			5'd24:		lcd_data_r	<=	hour_reg_bit_char;
			5'd25:		lcd_data_r	<=	"-";
			5'd26:		lcd_data_r	<=	minu_reg_dec_char;
			5'd27:		lcd_data_r	<=	minu_reg_bit_char;
			5'd28:		lcd_data_r	<=	"-";
			5'd29:		lcd_data_r	<=	sec_reg_dec_char;
			5'd30:		lcd_data_r	<=	sec_reg_bit_char;
			default:		lcd_data_r	<= "";
		endcase
	end
////////////////////////////////////////////////////////////////////////////////
reg 	[2:0]sec_reg_dec;//秒的十位
reg	[3:0]sec_reg_bit;//秒的个位
reg 	[2:0]minu_reg_dec;//分的十位
reg	[3:0]minu_reg_bit;//分的个位
reg	[3:0]hour_reg_dec;//小时的十位
reg	[1:0]hour_reg_bit;//小时的个位
reg 	[27:0]delay_cnt_clock;//数字时钟计数器分频寄存器
always@(posedge clk or negedge rst_n)//数字时钟计数器分频模块,50MHz → 1Hz
	begin
		if(!rst_n)
			delay_cnt_clock <= 28'h0000000;
		else if(delay_cnt_clock == 28'd49999999)
			delay_cnt_clock <= 28'd0;
		else
			delay_cnt_clock <= delay_cnt_clock + 1'b1;
	end
always@(posedge clk or negedge rst_n)//数字时钟模块
	begin
		if(!rst_n)
			begin
				sec_reg_bit	<=	4'd0;
				sec_reg_dec	<=	3'd0;
				minu_reg_bit<=	4'd0;
				minu_reg_dec<=	3'd0;
				hour_reg_bit<=	4'd0;
				hour_reg_dec<=	2'd0;
			end
		else if(delay_cnt_clock == 28'd49999999)
			begin
				if(sec_reg_bit == 4'd9 && sec_reg_dec == 3'd5)
					begin
						if(hour_reg_bit == 4'd3 && hour_reg_dec == 2'd2 && minu_reg_bit == 4'd9
						&& minu_reg_dec == 3'd5)
							begin
								sec_reg_bit	<=	4'd0;
								sec_reg_dec	<=	3'd0;
								minu_reg_bit<=	4'd0;
								minu_reg_dec<=	3'd0;
								hour_reg_bit<=	4'd0;
								hour_reg_dec<=	2'd0;
							end
						else if(hour_reg_bit == 4'd9 && hour_reg_dec < 2'd2 && minu_reg_bit == 4'd9
						&& minu_reg_dec == 3'd5)
							begin
								sec_reg_bit	<=	4'd0;
								sec_reg_dec	<=	3'd0;
								minu_reg_bit<=	4'd0;
								minu_reg_dec<=	3'd0;
								hour_reg_bit<=	4'd0;
								hour_reg_dec <= hour_reg_dec + 1'b1;
							end
						else if(hour_reg_bit <4'd9 && minu_reg_bit == 4'd9 && minu_reg_dec == 3'd5)
							begin
								sec_reg_bit	<=	4'd0;
								sec_reg_dec	<=	3'd0;
								minu_reg_bit<=	4'd0;
								minu_reg_dec<=	3'd0;
								hour_reg_bit <= hour_reg_bit + 1'b1;
								hour_reg_dec <= hour_reg_dec;
							end
						else if(minu_reg_bit == 4'd9 && minu_reg_dec < 3'd5)
							begin
								sec_reg_bit	<=	4'd0;
								sec_reg_dec	<=	3'd0;
								minu_reg_bit<=	4'd0;
								minu_reg_dec<=	minu_reg_dec + 1'b1;
								hour_reg_bit<= hour_reg_bit;
								hour_reg_dec<= hour_reg_dec;
							end
						else if(minu_reg_bit < 4'd9)
							begin
								sec_reg_bit	<=	4'd0;
								sec_reg_dec	<=	3'd0;
								minu_reg_bit<=	minu_reg_bit + 1'b1;
								minu_reg_dec<=	minu_reg_dec;
								hour_reg_bit<= hour_reg_bit;
								hour_reg_dec<= hour_reg_dec;
							end
					end							
				else if(sec_reg_bit == 4'd9 && sec_reg_dec < 3'd5)
					begin
						sec_reg_bit	<=	4'd0;
						sec_reg_dec	<=	sec_reg_dec + 1'b1;
						minu_reg_bit<=	minu_reg_bit;
						minu_reg_dec<=	minu_reg_dec;
						hour_reg_bit<= hour_reg_bit;
						hour_reg_dec<= hour_reg_dec;
					end
				else
					begin
						sec_reg_bit	<=	sec_reg_bit + 1'b1;
						sec_reg_dec	<=	sec_reg_dec;
						minu_reg_bit<=	minu_reg_bit;
						minu_reg_dec<=	minu_reg_dec;
						hour_reg_bit<= hour_reg_bit;
						hour_reg_dec<= hour_reg_dec;
					end
			end
		else 
			begin
				sec_reg_bit	<=	sec_reg_bit;
				sec_reg_dec	<=	sec_reg_dec;
				minu_reg_bit<=	minu_reg_bit;
				minu_reg_dec<=	minu_reg_dec;
				hour_reg_bit<= hour_reg_bit;
				hour_reg_dec<= hour_reg_dec;
			end	
	end
////////////////////////////////////////////////////////////////////////////////
//将数字时钟的秒、分、时以字符的形式显示在LCD屏幕上
reg[7:0] sec_reg_bit_char;
reg[7:0] sec_reg_dec_char;
reg[7:0] minu_reg_bit_char;
reg[7:0] minu_reg_dec_char;
reg[7:0] hour_reg_bit_char;
reg[7:0] hour_reg_dec_char;
always@(sec_reg_bit)
	begin
		case(sec_reg_bit)
			4'd0: sec_reg_bit_char <= "0";
			4'd1: sec_reg_bit_char <= "1";
			4'd2: sec_reg_bit_char <= "2";
			4'd3: sec_reg_bit_char <= "3";
			4'd4: sec_reg_bit_char <= "4";
			4'd5: sec_reg_bit_char <= "5";
			4'd6: sec_reg_bit_char <= "6";
			4'd7: sec_reg_bit_char <= "7";
			4'd8: sec_reg_bit_char <= "8";
			4'd9: sec_reg_bit_char <= "9";
			default:sec_reg_bit_char <= sec_reg_bit_char;
		endcase
	end
always@(sec_reg_dec)
	begin
		case(sec_reg_dec)
			3'd0: sec_reg_dec_char <= "0";
			3'd1: sec_reg_dec_char <= "1";
			3'd2: sec_reg_dec_char <= "2";
			3'd3: sec_reg_dec_char <= "3";
			3'd4: sec_reg_dec_char <= "4";
			3'd5: sec_reg_dec_char <= "5";
			default:sec_reg_dec_char <= "0";
		endcase
	end
always@(minu_reg_bit)
	begin
		case(minu_reg_bit)
			4'd0:	minu_reg_bit_char <= "0";
			4'd1:	minu_reg_bit_char <= "1";
			4'd2:	minu_reg_bit_char <= "2";
			4'd3:	minu_reg_bit_char <= "3";
			4'd4:	minu_reg_bit_char <= "4";
			4'd5:	minu_reg_bit_char <= "5";
			4'd6:	minu_reg_bit_char <= "6";
			4'd7:	minu_reg_bit_char <= "7";
			4'd8:	minu_reg_bit_char <= "8";
			4'd9:	minu_reg_bit_char <= "9";
			default:	minu_reg_bit_char <= "0";
		endcase
	end
always@(minu_reg_dec)
	begin
		case(minu_reg_dec)
			3'd0: minu_reg_dec_char <= "0";
			3'd1: minu_reg_dec_char <= "1";
			3'd2: minu_reg_dec_char <= "2";
			3'd3: minu_reg_dec_char <= "3";
			3'd4: minu_reg_dec_char <= "4";
			3'd5: minu_reg_dec_char <= "5";
			default:minu_reg_dec_char <= "0";
		endcase
	end
always@(hour_reg_bit)
	begin
		case(hour_reg_bit)
			4'd0:	hour_reg_bit_char <= "0";
			4'd1:	hour_reg_bit_char <= "1";
			4'd2:	hour_reg_bit_char <= "2";
			4'd3:	hour_reg_bit_char <= "3";
			4'd4:	hour_reg_bit_char <= "4";
			4'd5:	hour_reg_bit_char <= "5";
			4'd6:	hour_reg_bit_char <= "6";
			4'd7:	hour_reg_bit_char <= "7";
			4'd8:	hour_reg_bit_char <= "8";
			4'd9:	hour_reg_bit_char <= "9";
			default:	hour_reg_bit_char <= "0";
		endcase
	end
always@(hour_reg_dec)
	begin
		case(hour_reg_dec)
			2'd0:	hour_reg_dec_char	<= "0";
			2'd1:	hour_reg_dec_char	<=	"1";
			2'd2:	hour_reg_dec_char	<= "2";
			default:hour_reg_dec_char	<= "0";
		endcase	
	end
endmodule						






关键词: LCD1602     作业    

助工
2014-06-30 22:40:41     打赏
2楼
19205960

助工
2014-06-30 22:46:03     打赏
3楼

不过,还是遇到一个问题,就是,如各位所看到的实验现象里面,数字时钟的秒的个位右边的那个字符老是跟着个位一直显示,而且跟它显示的一模一样。不觉名利。其他的均显示正常。

希望个位大神看出原因了,指出来我的错误,谢谢了


从中午十二点到现在,敲了一下午代码,眼睛酸痛,目前来看,自己是看不出来了,明天再看看哪里出错了。


助工
2014-12-24 16:47:37     打赏
4楼
赞一个!!

共4条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]