原创 fpga学习日记16,驱动LCD1602显示

2013-8-30 16:25 3453 28 29 分类: FPGA/CPLD 文集: 数电,FPGA学习

注:如果本文有代码 则均搜索于网络或本人编写仅供学习交流之用

FPGA驱动LCD1602

驱动1602其实比实现IIC协议要简单

要注意读写模式  命令/数据线以及数据的发送和时序问题即可

难点还是在于时钟的生成

00.jpg

开发板自带的LCD1602是具有8位数据线 1个使能信号线

1个读写控制信号 1个数据/命令模式选择信号

01.jpg

 

使用流程如下

  1. 发命令配置LCD
  2. 设置数据地址
  3. 发送数据

 

因为要延时5ms  系统晶振50Mhz

50M = 20ns , 20ns * 131072 *2 ~= 5ms, 5 ms is LCD Cycle

在系统时钟的边沿开始计数,计数到一定值时归零并产生一个时钟信号,下次计数满时将时钟信号翻转即可产生新时钟。

 

verilog语言: 1602操作时钟生成
// 50M = 20ns , 20ns * 131072 *2 ~= 5ms, 5 ms is LCD Cycle
always @(posedge sys_clk_50m or negedge sys_rst_n) begin
       if (sys_rst_n ==1'b0)  
           div_cnt <= #`U_DLY 17'b0;
       else
           div_cnt <= #`U_DLY div_cnt + 17'b1;
end

always @(posedge sys_clk_50m or negedge sys_rst_n) begin
       if (sys_rst_n ==1'b0)  
           clk_lcd <= #`U_DLY 1'b0;
       else if ( div_cnt == {17{1'b1}} )
           clk_lcd <= #`U_DLY ~clk_lcd;
       else ;
end

接下来就是控制读写信号线  和  数据.命令控制信号线

来发送初始化LCD的命令---- 然后设置数据地址---- 写入要显示的数据

1

assign  RW = 1'b0;                                           //RW=0时对LCD模块执行写操作
assign  LCD_EN = LCD_EN_Sel ? clk_lcd : 1'b0;                //通过LCD_EN_Sel信号来控制LCD_EN的开启与关闭

always @(posedge clk_lcd or negedge rst)
begin
  if(!rst)
     begin
         state <= Clear_Lcd;                               //复位:清屏并光标复位  
         RS <= 1'b0;                                       //复位:RS=0时为写指令;                      
         DB8 <= 8'b0;                                      //复位:使DB8总线输出全0
         LCD_EN_Sel <= 1'b1;                               //复位:开启夜晶使能信号

         disp_count <= 4'b0;
     end
  else
     case(state)                                           //初始化LCD模块
     Clear_Lcd:
            begin
               state <= Set_Disp_Mode;
               DB8 <= 8'b00000001;                         //清屏并光标复位  
            end
     Set_Disp_Mode:
            begin
               state <= Disp_On;
               DB8 <= 8'b00111000;                         //设置显示模式:8位2行5x8点阵        
            end
     Disp_On:
            begin
               state <= Shift_Down;
               DB8 <= 8'b00001100;                         //显示器开、光标不显示、光标不允许闪烁    
            end
     Shift_Down:
           begin
               state <= Write_Addr;
               DB8 <= 8'b00000110;                         //文字不动,光标自动右移    
           end
     Write_Addr:
           begin
               state <= Write_Data_First;
               DB8 <= 8'b10000001;                         //写入第一行显示起始地址:第一行第二个位置    
               Data_First_Buf <= Data_First;               //将第一行显示的数据赋给Data_First_Buf?
           end
     Write_Data_First:                                     //写第一行数据
           begin
               if(disp_count == 14)                        //disp_count等于14时表示第一行数据已写完
                   begin
                       DB8 <= 8'b11000001;                 //送入写第二行的指令
                       RS <= 1'b0;
                       disp_count <= 4'b0;
                       Data_Second_Buf <= Data_Second;
                       state <= Write_Data_Second;         //写完第一行进入写第二行状态
                   end
               else
                   begin
                       DB8 <= Data_First_Buf[111:104];
                       Data_First_Buf <= (Data_First_Buf << 8);
                       RS <= 1'b1;                         //RS=1表示写数据
                       disp_count <= disp_count + 1'b1;
                       state <= Write_Data_First;
                   end
           end
     Write_Data_Second:                                    //写第二行数据
           begin
               if(disp_count == 14)
                   begin
                       LCD_EN_Sel <= 1'b0;
                       RS <= 1'b0;
                       disp_count <= 4'b0;
                       state <= Idel;                      //写完进入空闲状态
                   end
               else
                   begin
                       DB8 <= Data_Second_Buf[111:104];
                       Data_Second_Buf <= (Data_Second_Buf << 8);
                       RS <= 1'b1;
                       disp_count <= disp_count + 1'b1;
                       state <= Write_Data_Second;
                   end              
           end
     Idel:    
           begin
               state <=  Idel;                             //在Idel状态循环  
           end
     default:  state <= Clear_Lcd;                         //若state为其他值,则将state置为Clear_Lcd
     endcase
end


PARTNER CONTENT

文章评论1条评论)

登录后参与讨论

用户1847523 2015-8-23 23:45

写的很好,请问1602能直接用fpga的3.3VI/O口驱动吗?

用户1711475 2015-3-16 11:24

好东西。不过标题太误导人。

sunyzz 2015-3-9 20:54

我是晚上收到了,立马就拍照了,在灯光下,所以效果不太好

用户403664 2015-3-9 10:01

1、低调,嘿嘿 2、木有被调包,淡定。3、拍照技术太烂啦,以后怎么帮女朋友拍照?

相关推荐阅读
liang890319_284707880 2016-03-22 11:41
[博客大赛]我在搞嵌入式 我有罪
  我在搞嵌入式 我有罪 做嵌入式也有几年了 刚学习的时候书上说嵌入式的定义是以应用为中心,以计算机技术为基础,软硬件可裁剪,适应应用系统对功能、可靠性、成本、体积、功耗等严格要求的专用计...
liang890319_284707880 2015-10-22 11:57
帕萨特迈腾蒙迪欧哪个好
氵灬清风灬说:太小了,没法穿了,懒得换了 junyao00022说:............................... jd272475byp说:宝贝收到啦,衣服质量非常不错,...
liang890319_284707880 2015-10-22 11:56
二手荣威550和二手起亚k2哪个好
二手荣威550和二手起亚k2哪个好   风之乞说:衣服挺好的,就是偏小,已经更换了 梦里水乡0609说:不错 很好  不了不错  赞 四灵之首说:衣服质量不错,韵达快递不行~ ...
liang890319_284707880 2015-10-22 11:55
澳大利亚深海鱼油哪个牌子好
hgjfhgj说:不错  价格便宜  款式不错  开始买中码小了一点  免费给换的  好店家 小杰c子说:非常合适。也很有气质 天佑945说:还可以,性价比高。。。。。。。。。。 Ab...
liang890319_284707880 2015-10-19 11:03
常用DDR sdram和Flash型号
  以下是代码片段: http://blog.csdn.net/myarrow/article/details/7854863   主要是三星 现代 ...
liang890319_284707880 2013-09-29 17:00
ROM FLASH RAM
EPROM、EEPROM、FLASH的总结性区别   http://xdc0363.blog.163.com/blog/static/11546200220...
我要评论
1
28
关闭 站长推荐上一条 /3 下一条