FPGA-12864

介绍顺序:时序、设计思路、代码实现;

  1. 时序:

写入时序,12864与1602相同,不再重复,请看1602篇。

  1. 设计思路:

按照上述时序图,可以实现指令或数据的写入,具体写入指令或数据的顺序如下:

12864基本指令集与1602大致相同,除了这些12864还有7个扩展指令集,平时用不到,不介绍。11种基本指令的操作方法大致同1602:

下面只说平常用到的指令,按照执行顺序说明:

  1. 功能设置:0x30,延时72us
  2. 显示开关控制:0x0c,延时72us;
  3. 输入方式设置:0x06,延时72us;
  4. 清屏:0x01,延时4.6ms
  5. DDRAM地址设置:0x80/0x90/0x88/0x98;
  6. 写数据:待显示数据;

有几点需要注意:

  1. 功能设置指令最少执行两次,否则可能导致第二行不能显示;
  2. 延时时间一定要保证,特别是清屏指令,否则不显示;
  1. 代码实现:

写入以及显示各用一个状态机实现:

  1. 初始化:
input clk;//系统时钟
input rst;//系统复位

output reg rs;//液晶--rs
output reg rw;//液晶--rw
output reg e;//液晶--e
output reg [7:0] db;//液晶--db

reg write_en;//写入--启动,1启动,0停止
reg write_rs;//写入--指令or数据,1数据,0指令
reg [3:0] write_state;//写入--状态机
reg [5:0] write_cnt;//写入--延时控制

reg [5:0] lcd_state;//lcd状态机
reg [7:0] lcd_db_r;//lcd待显示数据
reg [19:0] lcd_delay;//lcd操作间延时
reg [3:0] lcd_init_cnt;//lcd初始化次数

parameter tas = 10;//140ns-->200ns
parameter pweh = 25;//450ns-->500ns
parameter th = 1;//10ns-->20ns
parameter tcycle = 50;//1000ns-->1000ns
parameter delay_4600 = 250000;//4.6ms-->5ms
parameter delay_72 = 5000;//72us-->100us
  1. 写入:
always @ (posedge clk or negedge rst) begin//指令、数据写入
	if(!rst) begin
		write_state <= 4'd0;
		write_cnt <= 8'd0;
		rs <= 1'b0; 
		rw <= 1'b0; 
		e <= 1'b0;
		db <= 8'd0;	
	end
	else begin
		case(write_state)
			4'd0 : if(write_en == 1'b1) write_state <= 4'd1;//等待
			4'd1 : begin//rs,rw置位,延时tas
					rs <= write_rs;
					rw <= 1'b0;
					if(write_cnt == (tas - 1)) begin
						write_state <= 4'd2;
						write_cnt <= 8'd0;
					end
					else write_cnt <= write_cnt + 1;
				end
			4'd2 : begin//e,data置位,延时pweh
					e <= 1'b1;
					db <= lcd_db_r;
					if(write_cnt == (pweh - 1)) begin
						write_state <= 4'd3;
						write_cnt <= 8'd0;
					end
					else write_cnt <= write_cnt + 1'b1;
				end
			4'd3 : begin//e复位,延时th
					e <= 1'b0;
					if(write_cnt == (th - 1)) begin
						write_state <= 4'd4;
						write_cnt <= 8'd0;
					end
					else write_cnt <= write_cnt + 1'b1;
				end
			4'd4 : begin//rs,rw复位,延时tcycle,写入完毕
					rs <= 1'b0;
					rw <= 1'b0;
					if(write_cnt == (tcycle - 1)) begin
						write_state <= 4'd0;
						write_cnt <= 8'd0;
					end
					else write_cnt <= write_cnt + 1'b1;
				end
			default : ;
		endcase
	end
end
  1. 显示:
always @ (posedge clk or negedge rst) begin//显示
	if(!rst) begin
		lcd_state <= 6'd0;
		lcd_db_r <= 8'd0;
		lcd_delay <= 20'd0;
		lcd_init_cnt <= 4'd0;
		write_en <= 1'b0;
		write_rs <= 1'b0;		
	end
	else begin
		case(lcd_state)
			6'd0 : begin//功能设置(6)
					lcd_db_r <= 8'h30;//基本指令集动作
					write_rs <= 1'b0;//指令
					write_en <= 1'b1;
					if(write_cnt == (tcycle - 1)) begin
						lcd_state <= lcd_state + 1; 
						write_en <= 1'b0;
					end
				end
			6'd1 : begin//功能设置--延时(72us)
					if(lcd_delay == delay_72) begin 
						if(lcd_init_cnt == 4'd1) begin
							lcd_state <= lcd_state + 1; 
							lcd_init_cnt <= 4'd0;
						end
						else begin
							lcd_state <= 6'd0; 
							lcd_init_cnt <= lcd_init_cnt + 1;
						end
						lcd_delay <= 20'd0;
					end
					else lcd_delay <= lcd_delay + 1;
				end
			6'd2 : begin//显示开关控制(4)
					lcd_db_r <= 8'h0c;//开显示,关光标,关闪烁
					write_rs <= 1'b0;//指令
					write_en <= 1'b1;
					if(write_cnt == (tcycle - 1)) begin
						lcd_state <= lcd_state + 1; 
						write_en <= 1'b0;
					end
				end
			6'd3 : begin//显示开关控制--延时(72us)
					if(lcd_delay == delay_72) begin
						lcd_state <= lcd_state + 1; 
						lcd_delay <= 20'd0;
					end
					else lcd_delay <= lcd_delay + 1;
				end
			6'd4 : begin//输入方式设置(3)
					lcd_db_r <= 8'h06;//AC++,画面不动
					write_rs <= 1'b0;//指令
					write_en <= 1'b1;
					if(write_cnt == (tcycle - 1)) begin
						lcd_state <= lcd_state + 1; 
						write_en <= 1'b0;
					end
				end
			6'd5 : begin//输入方式设置--延时(72us)
					if(lcd_delay == delay_72) begin
						lcd_state <= lcd_state + 1; 
						lcd_delay <= 20'd0;
					end
					else lcd_delay <= lcd_delay + 1;
				end
			6'd6 : begin//清屏(1)
					lcd_db_r <= 8'h01;//固定,注意延时4.6ms
					write_rs <= 1'b0;//指令
					write_en <= 1'b1;
					if(write_cnt == (tcycle - 1)) begin
						lcd_state <= lcd_state + 1; 
						write_en <= 1'b0;
					end
				end
			6'd7 : begin//清屏--延时(4.6ms)
					if(lcd_delay == delay_4600) begin
						lcd_state <= lcd_state + 1; 
						lcd_delay <= 20'd0;
					end
					else lcd_delay <= lcd_delay + 1;
				end
				
			6'd8 : begin//DDRAM地址设置(8)
					lcd_db_r <= 8'h80;//地址:第一行第一个
					write_rs <= 1'b0;//指令
					write_en <= 1'b1;
					if(write_cnt == (tcycle - 1)) begin
						lcd_state <= lcd_state + 1; 
						write_en <= 1'b0;
					end
				end
			6'd9 : begin//DDRAM地址设置--延时(72us)
					if(lcd_delay == delay_72) begin
						lcd_state <= lcd_state + 1; 
						lcd_delay <= 20'd0;
					end
					else lcd_delay <= lcd_delay + 1;
				end
			
			6'd10 : begin//写数据(10)
					lcd_db_r <= "A";//待显示数据
					write_rs <= 1'b1;//数据
					write_en <= 1'b1;
					if(write_cnt == (tcycle - 1)) begin
						lcd_state <= lcd_state + 1; 
						write_en <= 1'b0;
					end
				end
			6'd11 : begin//写数据--延时(72us)
					if(lcd_delay == delay_72) begin
						lcd_state <= lcd_state + 1; 
						lcd_delay <= 20'd0;
					end
					else lcd_delay <= lcd_delay + 1;
				end
			6'd12 : begin//写数据(10)
					lcd_db_r <= "D";//待显示数据
					write_rs <= 1'b1;//数据
					write_en <= 1'b1;
					if(write_cnt == (tcycle - 1)) begin
						lcd_state <= lcd_state + 1; 
						write_en <= 1'b0;
					end
				end
			6'd13 : begin//写数据--延时(72us)
					if(lcd_delay == delay_72) begin
						lcd_state <= lcd_state + 1; 
						lcd_delay <= 20'd0;
					end
					else lcd_delay <= lcd_delay + 1;
				end
			6'd14 : begin//写数据(10)
					lcd_db_r <= "8";//待显示数据
					write_rs <= 1'b1;//数据
					write_en <= 1'b1;
					if(write_cnt == (tcycle - 1)) begin
						lcd_state <= lcd_state + 1; 
						write_en <= 1'b0;
					end
				end
			6'd15 : begin//写数据--延时(72us)
					if(lcd_delay == delay_72) begin
						lcd_state <= lcd_state + 1; 
						lcd_delay <= 20'd0;
					end
					else lcd_delay <= lcd_delay + 1;
				end
			6'd16 : begin//写数据(10)
					lcd_db_r <= "3";//待显示数据
					write_rs <= 1'b1;//数据
					write_en <= 1'b1;
					if(write_cnt == (tcycle - 1)) begin
						lcd_state <= lcd_state + 1; 
						write_en <= 1'b0;
					end
				end
			6'd17 : begin//写数据--延时(72us)
					if(lcd_delay == delay_72) begin
						lcd_state <= lcd_state + 1; 
						lcd_delay <= 20'd0;
					end
					else lcd_delay <= lcd_delay + 1;
				end
			6'd18 : begin//写数据(10)
					lcd_db_r <= "9";//待显示数据
					write_rs <= 1'b1;//数据
					write_en <= 1'b1;
					if(write_cnt == (tcycle - 1)) begin
						lcd_state <= lcd_state + 1; 
						write_en <= 1'b0;
					end
				end
			6'd19 : begin//写数据--延时(72us)
					if(lcd_delay == delay_72) begin
						lcd_state <= lcd_state + 1; 
						lcd_delay <= 20'd0;
					end
					else lcd_delay <= lcd_delay + 1;
				end	
			6'd20 : begin//写数据(10)
					lcd_db_r <= "7";//待显示数据
					write_rs <= 1'b1;//数据
					write_en <= 1'b1;
					if(write_cnt == (tcycle - 1)) begin
						lcd_state <= lcd_state + 1; 
						write_en <= 1'b0;
					end
				end
			6'd21 : begin//写数据--延时(72us)
					if(lcd_delay == delay_72) begin
						lcd_state <= lcd_state + 1; 
						lcd_delay <= 20'd0;
					end
					else lcd_delay <= lcd_delay + 1;
				end
				
			6'd22 : begin//DDRAM地址设置(8)
					lcd_db_r <= 8'h90;//地址:第二行第一个
					write_rs <= 1'b0;//指令
					write_en <= 1'b1;
					if(write_cnt == (tcycle - 1)) begin
						lcd_state <= lcd_state + 1; 
						write_en <= 1'b0;
					end
				end
			6'd23 : begin//DDRAM地址设置--延时(72us)
					if(lcd_delay == delay_72) begin
						lcd_state <= lcd_state + 1; 
						lcd_delay <= 20'd0;
					end
					else lcd_delay <= lcd_delay + 1;
				end	
			
			6'd24 : begin//写数据(10)
					lcd_db_r <= "A";//待显示数据
					write_rs <= 1'b1;//数据
					write_en <= 1'b1;
					if(write_cnt == (tcycle - 1)) begin
						lcd_state <= lcd_state + 1; 
						write_en <= 1'b0;
					end
				end
			6'd25 : begin//写数据--延时(72us)
					if(lcd_delay == delay_72) begin
						lcd_state <= lcd_state + 1; 
						lcd_delay <= 20'd0;
					end
					else lcd_delay <= lcd_delay + 1;
				end
			6'd26 : begin//写数据(10)
					lcd_db_r <= "D";//待显示数据
					write_rs <= 1'b1;//数据
					write_en <= 1'b1;
					if(write_cnt == (tcycle - 1)) begin
						lcd_state <= lcd_state + 1; 
						write_en <= 1'b0;
					end
				end
			6'd27 : begin//写数据--延时(72us)
					if(lcd_delay == delay_72) begin
						lcd_state <= lcd_state + 1; 
						lcd_delay <= 20'd0;
					end
					else lcd_delay <= lcd_delay + 1;
				end
			6'd28 : begin//写数据(10)
					lcd_db_r <= "6";//待显示数据
					write_rs <= 1'b1;//数据
					write_en <= 1'b1;
					if(write_cnt == (tcycle - 1)) begin
						lcd_state <= lcd_state + 1; 
						write_en <= 1'b0;
					end
				end
			6'd29 : begin//写数据--延时(72us)
					if(lcd_delay == delay_72) begin
						lcd_state <= lcd_state + 1; 
						lcd_delay <= 20'd0;
					end
					else lcd_delay <= lcd_delay + 1;
				end
			6'd30 : begin//写数据(10)
					lcd_db_r <= "2";//待显示数据
					write_rs <= 1'b1;//数据
					write_en <= 1'b1;
					if(write_cnt == (tcycle - 1)) begin
						lcd_state <= lcd_state + 1; 
						write_en <= 1'b0;
					end
				end
			6'd31 : begin//写数据--延时(72us)
					if(lcd_delay == delay_72) begin
						lcd_state <= lcd_state + 1; 
						lcd_delay <= 20'd0;
					end
					else lcd_delay <= lcd_delay + 1;
				end
			6'd32 : begin//写数据(10)
					lcd_db_r <= "3";//待显示数据
					write_rs <= 1'b1;//数据
					write_en <= 1'b1;
					if(write_cnt == (tcycle - 1)) begin
						lcd_state <= lcd_state + 1; 
						write_en <= 1'b0;
					end
				end
			6'd33 : begin//写数据--延时(72us)
					if(lcd_delay == delay_72) begin
						lcd_state <= lcd_state + 1; 
						lcd_delay <= 20'd0;
					end
					else lcd_delay <= lcd_delay + 1;
				end		
			
			6'd34 : begin//DDRAM地址设置(8)
					lcd_db_r <= 8'h88;//地址:第三行第一个
					write_rs <= 1'b0;//指令
					write_en <= 1'b1;
					if(write_cnt == (tcycle - 1)) begin
						lcd_state <= lcd_state + 1; 
						write_en <= 1'b0;
					end
				end
			6'd35 : begin//DDRAM地址设置--延时(72us)
					if(lcd_delay == delay_72) begin
						lcd_state <= lcd_state + 1; 
						lcd_delay <= 20'd0;
					end
					else lcd_delay <= lcd_delay + 1;
				end
			
			6'd36 : begin//写数据(10)
					lcd_db_r <= "A";//待显示数据
					write_rs <= 1'b1;//数据
					write_en <= 1'b1;
					if(write_cnt == (tcycle - 1)) begin
						lcd_state <= lcd_state + 1; 
						write_en <= 1'b0;
					end
				end
			6'd37 : begin//写数据--延时(40us)
					if(lcd_delay == delay_72) begin
						lcd_state <= lcd_state + 1; 
						lcd_delay <= 20'd0;
					end
					else lcd_delay <= lcd_delay + 1;
				end
			6'd38 : begin//写数据(10)
					lcd_db_r <= "M";//待显示数据
					write_rs <= 1'b1;//数据
					write_en <= 1'b1;
					if(write_cnt == (tcycle - 1)) begin
						lcd_state <= lcd_state + 1; 
						write_en <= 1'b0;
					end
				end
			6'd39 : begin//写数据--延时(40us)
					if(lcd_delay == delay_72) begin
						lcd_state <= lcd_state + 1; 
						lcd_delay <= 20'd0;
					end
					else lcd_delay <= lcd_delay + 1;
				end
			6'd40 : begin//写数据(10)
					lcd_db_r <= "C";//待显示数据
					write_rs <= 1'b1;//数据
					write_en <= 1'b1;
					if(write_cnt == (tcycle - 1)) begin
						lcd_state <= lcd_state + 1; 
						write_en <= 1'b0;
					end
				end
			6'd41 : begin//写数据--延时(40us)
					if(lcd_delay == delay_72) begin
						lcd_state <= lcd_state + 1; 
						lcd_delay <= 20'd0;
					end
					else lcd_delay <= lcd_delay + 1;
				end			
			6'd42 : begin//写数据(10)
					lcd_db_r <= "1";//待显示数据
					write_rs <= 1'b1;//数据
					write_en <= 1'b1;
					if(write_cnt == (tcycle - 1)) begin
						lcd_state <= lcd_state + 1; 
						write_en <= 1'b0;
					end
				end
			6'd43 : begin//写数据--延时(40us)
					if(lcd_delay == delay_72) begin
						lcd_state <= lcd_state + 1; 
						lcd_delay <= 20'd0;
					end
					else lcd_delay <= lcd_delay + 1;
				end	
			6'd44 : begin//写数据(10)
					lcd_db_r <= "2";//待显示数据
					write_rs <= 1'b1;//数据
					write_en <= 1'b1;
					if(write_cnt == (tcycle - 1)) begin
						lcd_state <= lcd_state + 1; 
						write_en <= 1'b0;
					end
				end
			6'd45 : begin//写数据--延时(40us)
					if(lcd_delay == delay_72) begin
						lcd_state <= lcd_state + 1; 
						lcd_delay <= 20'd0;
					end
					else lcd_delay <= lcd_delay + 1;
				end
			6'd46 : begin//写数据(10)
					lcd_db_r <= "0";//待显示数据
					write_rs <= 1'b1;//数据
					write_en <= 1'b1;
					if(write_cnt == (tcycle - 1)) begin
						lcd_state <= lcd_state + 1; 
						write_en <= 1'b0;
					end
				end
			6'd47 : begin//写数据--延时(40us)
					if(lcd_delay == delay_72) begin
						lcd_state <= lcd_state + 1; 
						lcd_delay <= 20'd0;
					end
					else lcd_delay <= lcd_delay + 1;
				end	
			6'd48 : begin//写数据(10)
					lcd_db_r <= "0";//待显示数据
					write_rs <= 1'b1;//数据
					write_en <= 1'b1;
					if(write_cnt == (tcycle - 1)) begin
						lcd_state <= lcd_state + 1; 
						write_en <= 1'b0;
					end
				end
			6'd49 : begin//写数据--延时(40us)
					if(lcd_delay == delay_72) begin
						lcd_state <= lcd_state + 1; 
						lcd_delay <= 20'd0;
					end
					else lcd_delay <= lcd_delay + 1;
				end	
				
			6'd50 : begin//DDRAM地址设置(8)
					lcd_db_r <= 8'h98;//地址:第三行第一个
					write_rs <= 1'b0;//指令
					write_en <= 1'b1;
					if(write_cnt == (tcycle - 1)) begin
						lcd_state <= lcd_state + 1; 
						write_en <= 1'b0;
					end
				end
			6'd51 : begin//DDRAM地址设置--延时(72us)
					if(lcd_delay == delay_72) begin
						lcd_state <= lcd_state + 1; 
						lcd_delay <= 20'd0;
					end
					else lcd_delay <= lcd_delay + 1;
				end
			
			6'd52 : begin//写数据(10)
					lcd_db_r <= "O";//待显示数据
					write_rs <= 1'b1;//数据
					write_en <= 1'b1;
					if(write_cnt == (tcycle - 1)) begin
						lcd_state <= lcd_state + 1; 
						write_en <= 1'b0;
					end
				end
			6'd53 : begin//写数据--延时(40us)
					if(lcd_delay == delay_72) begin
						lcd_state <= lcd_state + 1; 
						lcd_delay <= 20'd0;
					end
					else lcd_delay <= lcd_delay + 1;
				end
			6'd54 : begin//写数据(10)
					lcd_db_r <= "P";//待显示数据
					write_rs <= 1'b1;//数据
					write_en <= 1'b1;
					if(write_cnt == (tcycle - 1)) begin
						lcd_state <= lcd_state + 1; 
						write_en <= 1'b0;
					end
				end
			6'd55 : begin//写数据--延时(40us)
					if(lcd_delay == delay_72) begin
						lcd_state <= lcd_state + 1; 
						lcd_delay <= 20'd0;
					end
					else lcd_delay <= lcd_delay + 1;
				end
			6'd56 : begin//写数据(10)
					lcd_db_r <= "0";//待显示数据
					write_rs <= 1'b1;//数据
					write_en <= 1'b1;
					if(write_cnt == (tcycle - 1)) begin
						lcd_state <= lcd_state + 1; 
						write_en <= 1'b0;
					end
				end
			6'd57 : begin//写数据--延时(40us)
					if(lcd_delay == delay_72) begin
						lcd_state <= lcd_state + 1; 
						lcd_delay <= 20'd0;
					end
					else lcd_delay <= lcd_delay + 1;
				end
			6'd58 : begin//写数据(10)
					lcd_db_r <= "7";//待显示数据
					write_rs <= 1'b1;//数据
					write_en <= 1'b1;
					if(write_cnt == (tcycle - 1)) begin
						lcd_state <= lcd_state + 1; 
						write_en <= 1'b0;
					end
				end
			6'd59 : begin//写数据--延时(40us)
					if(lcd_delay == delay_72) begin
						lcd_state <= lcd_state + 1; 
						lcd_delay <= 20'd0;
					end
					else lcd_delay <= lcd_delay + 1;
				end
		endcase
	end
end

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值