搜索
bottom↓
回复: 20

1602液晶的驱动(verilog)

[复制链接]

出0入0汤圆

发表于 2010-2-3 22:11:32 | 显示全部楼层 |阅读模式

(原文件名:elsonx.jpg)

module LCD1602 (clk_500Hz, rst_n, update, addr, data, lcd_rw, lcd_rs, lcd_en, lcd_data);

input clk_500Hz, rst_n, update;
input[4:0] addr;
input[7:0] data;

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

reg lcd_rs;
wire lcd_en;
reg[7:0] lcd_data;

reg[9:0] current_state, next_state;
reg[4:0] addr_cnt;
reg[7:0] disp_buf1[15:0];
reg[7:0] disp_buf2[15:0];

parameter         IDLE        = 10'b00_0000_0000,
        CLEAR          = 10'b00_0000_0010,
        DISPOFF         = 10'b00_0000_0100,
        SETLCDMODE  = 10'b00_0000_1000,
        SETCURSOR   = 10'b00_0001_0000,
        CURSORMODE         = 10'b00_0010_0000,
        WRITEADDR1  = 10'b00_0100_0000,
        WRITEADDR2          = 10'b00_1000_0000,
        WRITEDATA1   = 10'b01_0000_0000,
        WRITEDATA2          = 10'b10_0000_0000;

assign lcd_rw = 1'b0;
assign lcd_en = clk_500Hz;

task init_buf;
        disp_buf1[0] <= "T";
        disp_buf1[1] <= "o";
        disp_buf1[2] <= ":";
        disp_buf1[3] <= "w";
        disp_buf1[4] <= "w";
        disp_buf1[5] <= "w";
        disp_buf1[6] <= ".";
        disp_buf1[7] <= "o";
        disp_buf1[8] <= "u";
        disp_buf1[9] <= "r";
        disp_buf1[10] <= "d";
        disp_buf1[11] <= "e";
        disp_buf1[12] <= "v";
        disp_buf1[13] <= ".";
        disp_buf1[14] <= "c";
        disp_buf1[15] <= "n";
       
        disp_buf2[0] <= " ";
        disp_buf2[1] <= " ";
        disp_buf2[2] <= " ";
        disp_buf2[3] <= " ";
        disp_buf2[4] <= " ";
        disp_buf2[5] <= " ";
        disp_buf2[6] <= " ";
        disp_buf2[7] <= "b";
        disp_buf2[8] <= "y";
        disp_buf2[9] <= " ";
        disp_buf2[10] <= "E";
        disp_buf2[11] <= "l";
        disp_buf2[12] <= "s";
        disp_buf2[13] <= "o";
        disp_buf2[14] <= "n";
        disp_buf2[15] <= "x";
endtask

always @ (posedge clk_500Hz or negedge rst_n)
  begin
        if (!rst_n)
                current_state <= IDLE;
        else
                current_state <= next_state;
  end
  
always @ (current_state or addr_cnt)
  begin
        next_state = 4'hx;
        case (current_state)
                IDLE:                next_state = SETLCDMODE;
               
                SETLCDMODE:        next_state = DISPOFF;

                DISPOFF:                   next_state = CLEAR;
               
                CLEAR:                next_state = SETCURSOR;
               
                SETCURSOR:          next_state = CURSORMODE;
               
                CURSORMODE:        next_state = WRITEADDR1;
       
                WRITEADDR1:        next_state = WRITEDATA1;
       
                WRITEADDR2:        next_state = WRITEDATA2;
       
                WRITEDATA1:
                  begin
                        if(addr_cnt == 16)
                                next_state = WRITEADDR2;
                        else
                                next_state = WRITEDATA1;
                  end
                WRITEDATA2:
                  begin
                        if(addr_cnt == 16)
                                next_state = WRITEADDR1;
                        else
                                next_state = WRITEDATA2;
                  end
                default: next_state = IDLE;
       
        endcase
  end
  
always @ (posedge clk_500Hz or negedge rst_n)
  begin
        if (!rst_n)
                addr_cnt <= 0;
        else
        case (next_state)
                IDLE:
                  begin
                    lcd_rs = 0;
                        lcd_data = 8'hxx;
                  end
                SETLCDMODE:
                  begin
                        lcd_rs = 0;
                        lcd_data = 8'h38;
                  end
                DISPOFF:
                  begin
                        lcd_rs = 0;
                        lcd_data = 8'h08;
                  end
                CLEAR:
                  begin
                        lcd_rs = 0;
                        lcd_data = 8'h1;
                  end
                SETCURSOR:
                  begin
                        lcd_rs = 0;
                        lcd_data = 8'h06;
                  end
                CURSORMODE:
                  begin
                        lcd_rs = 0;
                        lcd_data = 8'h0C;
                  end
                WRITEADDR1:
                  begin
                        lcd_rs = 0;
                        lcd_data = 8'h80;
                  end
                WRITEADDR2:
                  begin
                        lcd_rs = 0;
                        lcd_data = 8'hc0;
                  end
                WRITEDATA1:
                  begin
                        lcd_rs = 1;
                        lcd_data = disp_buf1[addr_cnt];
                        addr_cnt <= addr_cnt + 1;
                  end
                WRITEDATA2:
                  begin
                        lcd_rs = 1;
                        lcd_data = disp_buf2[addr_cnt];
                        addr_cnt <= addr_cnt + 1;
                  end
        endcase
  end

always @ (posedge update or negedge rst_n)
  begin
        if (!rst_n)
                init_buf;
        else if (!addr[4])
                disp_buf1[addr[3:0]] <= data;
        else
                disp_buf2[addr[3:0]] <= data;
  end
  
endmodule

代码贴上来好像缩进有点乱了~~~

点击此处下载 LCD1602.rar(文件大小:960字节) (原文件名:LCD1602.rar)

阿莫论坛20周年了!感谢大家的支持与爱护!!

该献的血还是要献的。你不献他不献。难道让我去献? --- 出自坛友:lovejp1981

出0入0汤圆

发表于 2010-2-3 23:03:03 | 显示全部楼层
蛮好。

出0入0汤圆

 楼主| 发表于 2010-2-4 00:48:30 | 显示全部楼层
回复【1楼】tear086 .COM缺氧
-----------------------------------------------------------------------

谢谢~~~

出0入0汤圆

发表于 2010-3-15 18:01:09 | 显示全部楼层

出0入0汤圆

发表于 2010-3-15 20:25:31 | 显示全部楼层
1602显示频直接用50Mhz的频率可以驱动不?楼主用的500hz。我的开发板只有50mhz的和27M的。

出0入0汤圆

发表于 2010-3-15 20:30:30 | 显示全部楼层
回复【5楼】yvhksovo
1602显示频直接用50Mhz的频率可以驱动不?楼主用的500hz。我的开发板只有50mhz的和27M的。
-----------------------------------------------------------------------

分频即可。500Khz ~ 1MHz 皆可



贴个更好用的,新近写的,水平有限,欢迎拍砖。




// 0 ~ (8*16-1) = 128
// 16bits             -> 0123456789ABCDEF <-
wire [127:0] row1_val = "A Lcd Disp Test ";
wire [127:0] row2_val = "Amy-studio Pub  ";


// 例化LCD1602驱动
lcd1602_drive u0(
  .clk              (CLOCK_50),
  .rst_n            (Q_KEY),
  // LCD1602 Input Value
  .row1_val         (row1_val),
  .row2_val         (row2_val),
  // LCD1602 Interface
  .lcd_data         (LCD1602_DATA),
  .lcd_e            (LCD1602_E),
  .lcd_rs           (LCD1602_RS),
  .lcd_rw           (LCD1602_RW)
);


(原文件名:抓图-1.png)

点击此处下载 ourdev_538520.zip(文件大小:89K) (原文件名:lcd1602_test.zip)

出0入0汤圆

发表于 2010-3-15 20:36:02 | 显示全部楼层
回复【6楼】tear086 .COM缺氧
-----------------------------------------------------------------------

呃,还是有频率限制的哦。只有分频了。

出0入0汤圆

发表于 2010-3-15 20:41:26 | 显示全部楼层
回复【7楼】yvhksovo
-----------------------------------------------------------------------

分频的方法可以参考我的博客。
http://www.cnblogs.com/yuphone/archive/2010/02/08/1666130.html

出0入0汤圆

发表于 2010-3-15 20:43:18 | 显示全部楼层
回复【8楼】tear086 .COM缺氧
-----------------------------------------------------------------------

嗯,很详细。谢谢。

出0入0汤圆

发表于 2010-3-15 20:48:45 | 显示全部楼层
直接用PLL分频不是很方便吗:)

出0入0汤圆

发表于 2010-4-16 00:45:00 | 显示全部楼层
回复【6楼】tear086  .COM 缺氧
-----------------------------------------------------------------------

用到了~ 谢谢6楼的弟兄!

出0入0汤圆

发表于 2010-4-16 06:33:44 | 显示全部楼层
verilog mark

出0入0汤圆

发表于 2010-4-25 17:17:11 | 显示全部楼层
我想问一下,如果我要调用一个字库该怎么做呢?字库以什么形式包含到项目中,如何调用字库?

出0入0汤圆

发表于 2010-5-6 16:26:44 | 显示全部楼层
我连一个delay函数都不知道怎么弄,下来看看,谢谢上传的代码。

出0入0汤圆

发表于 2010-8-2 21:27:10 | 显示全部楼层
非常感谢   6楼的哥们

出0入0汤圆

发表于 2010-8-2 21:28:08 | 显示全部楼层
新手  需要帮助  关键原因是对  状态机掌握不是很深刻  但是6楼主写的很能接受

出0入0汤圆

发表于 2010-8-2 22:26:13 | 显示全部楼层
关注中

出0入0汤圆

发表于 2010-9-1 21:41:33 | 显示全部楼层
之前也写过,现在想写显示变量的,不知道要用什么方法弄好一点~

出0入0汤圆

发表于 2011-4-24 09:31:55 | 显示全部楼层
回复【6楼】tear086  .COM 缺氧
------------------------------------------------------------------
请问为什么用格雷码编码 有什么好处吗? 直接用二进制不是更好理解吗?
新手求教。。

出0入0汤圆

发表于 2011-4-24 10:26:58 | 显示全部楼层
仅限于 RZ类语法学习阶段,谨慎收藏。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-27 21:15

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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