小弟最近学习开发板上的1602液晶,
写了代码,下载后液晶没显示,只有背光是亮的。
相信很多人都用过1602噻,程序也很普遍,
我贴出代码来大家帮我在你们的开发板上运行下
看看能实现不?
最好能找下问题所在,谢谢各位指点
-
- /*************************************************
- //Module: lcd1602
- //File Name: lcd1602.v
- //Version: 1.0
- //Date: 2011.12.5
- //Author: wang li
- //Code Type: RTL
- //Description: LCD1602液晶显示
- // clk——时钟输入(1位)
- // rst——复位信号输入(1位)
- // 输入看模块
- **************************************************/
- module lcd1602(clk,rst,LCD_E,LCD_RW,LCD_RS,LCD_DATA);
- input clk; //时钟信号,50Mhz
- input rst; //复位信号,低电平进行复位
- output LCD_E; //1602使能引脚,1时读取信息,1->0(下降沿)执行命令
- output LCD_RS; //1602数据——H/命令——L 选择端
- output LCD_RW; //1602写——L/读——H 选择端
- output [7:0] LCD_DATA; //1602数据传输端口
- wire LCD_E;
- reg [8:0] count;
- reg clk_div1; //500个clk的周期,20ns*500=10us
- reg clk_div2; //1000个,20us
- reg [8:0] count1; //500个clk_div2的周期,10us*200=2000u=5ms
- reg clk_buf;
- //******************
- //-----分频模块-----
- //******************
- always @(posedge clk or negedge rst)
- begin
- if(!rst) //rst=0
- count<=0;
- else
- begin
- if(count<250) //2500
- begin
- clk_div1<=0;
- count<=count+1'b1;
- end
- else if(count>=500-1) //5000
- count<=0;
- else
- begin
- clk_div1<=1;
- count<=count+1'b1;
- end
- end
- end
- always @(posedge clk_div1 or negedge rst)
- begin
- if(!rst)
- clk_div2<=0;
- else
- clk_div2<=~clk_div2;
- end
- always @(posedge clk_div2 or negedge rst)
- begin
- if(!rst) //rst=0
- count1<=0;
- else
- begin
- if(count1<250) //2500
- begin
- clk_buf<=0;
- count1<=count1+1'b1;
- end
- else if(count1>=500-1) //5000
- count1<=0;
- else
- begin
- clk_buf<=1;
- count1<=count1+1'b1;
- end
- end
- end
- assign LCD_E=clk_buf;
-
- //**********************
- //-----显示控制模块-----
- //**********************
- reg [3:0] state; //当前状态寄存器 ,10个状态
- reg [4:0] address; //地址的位置,0~31
- reg [7:0] LCD_DATA;
- reg LCD_RW,LCD_RS;
- parameter
- IDLE = 4'd0, //空闲
- SET_FUNCTION = 4'd2, //工作方式设置指令
- SWITCH_MODE = 4'd3, //开关控制指令
- SET_MODE = 4'd4, //输入方式设置
- CLEAR = 4'd5,
- SET_DDRAM1 = 4'd6, //设定第一行DDRAM地址指令
- WRITE_RAM1 = 4'd7, //向第一行写入的数码
- WRITE_RAM2 = 4'd8, //向第2行写入的数码
- SHIFT = 4'd9, //设定显示屏或光标移动方向指令
- SET_DDRAM2 = 4'd10, //设定第2行DDRAM地址指令
- STOP = 4'd11;
- reg [127:0] Data_First = "www.endchina.com"; //液晶显示的第一行的数据
- reg [127:0] Data_Second = " chick_kid "; //液晶显示的第二行的数据
- reg [127:0] Data_First_Buf,
- Data_Second_Buf; //液晶显示的数据缓存
- //-----状态控制-----
- always @(posedge clk_buf or negedge rst)
- begin
- if(!rst)
- begin
- state<=IDLE;
- address<=5'd0;
- LCD_DATA<=8'b0000_0000;
- LCD_RS<=0;
- LCD_RW<=0;
- end
- else
- begin
- case(state)
- IDLE: //空闲状态
- begin
- LCD_DATA<=8'b00000000; //8'bzzzz_zzzz
- state<=SET_FUNCTION;
- end
- SET_FUNCTION: //工作方式设置
- begin
- LCD_RS<=0;
- LCD_RW<=0;
- LCD_DATA<=8'b0011_1000; //38h
- //第4位DL:0=数据总线为4位;1=数据总线为8位★★★
- //第3位N:0=显示1行;1=显示2行★★★
- //第2位F:0=5×7点阵/每字符★★★;1=5×10点阵/每字符
- state<=SWITCH_MODE;
- end
- SWITCH_MODE: //显示开关控制指令
- begin
- LCD_RS<=0;
- LCD_RW<=0;
- LCD_DATA<=8'b0000_1111; //0Fh
- //第2位D:0=显示功能关;1=显示功能开★★★
- //第1位C:0=无光标;1=有光标★★★
- //第0位B:0=光标闪烁; 1=光标不闪烁★★★
- state<=SET_MODE;
- end
- SET_MODE: //设定显示屏或光标移动方向指令
- begin
- LCD_RS<=0;
- LCD_RW<=0;
- LCD_DATA<=8'b0000_0110; //06h
- //第1位N:0=读或者写一个字符后,地址指针-1,光标-1
- // 1=读或者写一个字符后,地址指针+1,光标+1★★★
- //第0位S:0=当写一个字符,整屏显示不移动★★★
- // 1=当写一个字符,整屏显示左移(N=1)或者右移(N=0),以得到光标不移动而屏幕移动的效果
- state<=CLEAR;
- end
- CLEAR: //清屏指令
- begin
- LCD_RS<=0;
- LCD_RW<=0;
- LCD_DATA<=8'b0000_0001; //指令
- state<=SHIFT;
- end
-
- SHIFT: //设定显示屏或光标移动方向指令
- begin
- LCD_RS<=0;
- LCD_RW<=0;
- LCD_DATA<=8'b0001_0100;
- //第3位S/C;第2位R/L
- // S/C R/L 设定情况
- // 0 0 光标左移1格,且AC值减1
- // 0 1 光标右移1格,且AC值加1 ★★★
- // 1 0 显示器上字符全部左移一格,但光标不动
- // 1 1 显示器上字符全部右移一格,但光标不动
- state<=SET_DDRAM1;
- end
- SET_DDRAM1: //设定第一行DDRAM地址指令
- begin
- LCD_RS<=0;
- LCD_RW<=0;
-
- //-----写入第一行显示起始地址:-----
- // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
- // 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 第一行
- LCD_DATA<=8'h80+8'd0; //第一行第1个位置
-
- state<=WRITE_RAM1;
- Data_First_Buf<=Data_First;
- end
- WRITE_RAM1: //向第一行写入的数码
- begin
- if(address<=15) //表示写第一行
- begin
- LCD_RS<=1;
- LCD_RW<=0;
- LCD_DATA<=Data_First_Buf[127:120];
- Data_First_Buf<=(Data_First_Buf<<8); //左移
- address<=address+1'b1;
- state<=WRITE_RAM1;
- end
- else
- begin
- LCD_RS<=0;
- LCD_RW<=0;
- state<=SET_DDRAM2;
- end
- end
- SET_DDRAM2: //设定第2行DDRAM地址指令
- begin
- LCD_RS<=0;
- LCD_RW<=0;
-
- //-----写入第2行显示起始地址:-----
- // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
- // 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 第二行
- LCD_DATA<=8'hC0+8'd0; //第2行第1个位置
-
- state<=WRITE_RAM2;
- Data_Second_Buf<=Data_Second;
- end
- WRITE_RAM2: //向第2行写入的数码
- begin
- if(address<=31) //表示写第一行
- begin
- LCD_RS<=1;
- LCD_RW<=0;
- LCD_DATA<=Data_First_Buf[127:120];
- Data_Second_Buf<=(Data_Second_Buf<<8);
- address<=address+1'b1;
- state<=WRITE_RAM2;
- end
- else
- begin
- LCD_RS<=0;
- LCD_RW<=0;
- address<=5'd0;
- state<=STOP;
- end
- end
- STOP: //设定第一行DDRAM地址指令
- begin
- state<=STOP;
- end
- default:
- state<=CLEAR;
- endcase
- end
- end
-
- endmodule
-
-
-
|