找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6160|回复: 5
打印 上一主题 下一主题
收起左侧

FPGA驱动LCD12864显示图像的源码与资料分享

  [复制链接]
跳转到指定楼层
楼主
lcd12864的例子,已经做出来了


FPGA 源程序如下:
  1. //==========================================================================
  2. //Filename  :lcd12864_picture.v                                      
  3. //modulename:lcd12864_picture                                       
  4. //Author    :a fei                                                         
  5. //Date            :2012-7-8                                                      
  6. //Function  :驱动12864,显示图像                  
  7. //Uesedfor  :                                                               
  8. //==========================================================================
  9. `timescale 1ns/1ps

  10. module    lcd12864_picture
  11.    (
  12. //sys_signal
  13.     input               i_50m_clk    ,
  14.     input               i_rst_n      ,
  15.         
  16.             
  17.     output reg             o_lcd_rs      ,//12864端口
  18.     output reg             o_lcd_rw      ,
  19.     output reg             o_lcd_en      ,
  20.     output reg   [7:0]     o_lcd_data    ,
  21.     output                 o_lcd_psb     ,
  22.     output       [1:0]     o_led        
  23.   //  output                 o_lcd_rst
  24.     );  

  25. //assign  o_lcd_rst = 1'b1 ;   
  26. assign  o_lcd_psb = 1'b1 ;   
  27.                               
  28.      
  29. //=============================================================================
  30. //控制状态机状态
  31. //=============================================================================     
  32. parameter Idle          = 11'b00000000001 ;//上电初始状态
  33. parameter Set_mode      = 11'b00000000010 ;//模式设置
  34. parameter clear1        = 11'b00000000100 ;//数据地址清零
  35. parameter Disp_on_off   = 11'b00000001000 ;//显示开和关
  36. parameter Cursor        = 11'b00000010000 ;//光标设置
  37. parameter Stand_by      = 11'b00000100000 ;//延时
  38. parameter Clear2        = 11'b00001000000 ;//数据地址清零
  39. parameter disp_function = 11'b00010000000 ;//开绘图显示
  40. parameter Wr_address_Y  = 11'b00100000000  ;//写行地址
  41. parameter Wr_address_X  = 11'b01000000000  ;//写列地址,列地址自动加1
  42. parameter Wr_data       = 11'b10000000000  ;//写数据  


  43. reg [10:0] crt_state , next_state ;
  44. //=================================================================
  45. reg [15:0] cnt_1000 ;//E、RS信号脉冲宽度计数器 1000*20ns=20us
  46. reg [15:0] time_cnt2;//写数据地址数据间隔计数器

  47. always@( posedge i_50m_clk or negedge i_rst_n )//
  48.     if( !i_rst_n )
  49.            cnt_1000 <= 16'b0 ;
  50.     else if(crt_state!=next_state)
  51.            cnt_1000 <= 16'b0 ;
  52.     else if(time_cnt2==16'hffff)
  53.            cnt_1000 <= 16'b0 ;  
  54.     else if( cnt_1000 == 16'd4000)
  55.            cnt_1000 <= cnt_1000 ;
  56.     else
  57.            cnt_1000 <= cnt_1000 +1'b1  ;
  58.            
  59. reg [18:0]  time_cnt1 ;//5ms计时器,初始化指令间隔
  60. always@( posedge i_50m_clk or negedge i_rst_n )//
  61.     if( !i_rst_n )
  62.            time_cnt1 <= 18'b0 ;
  63.     else if(crt_state!=next_state)
  64.            time_cnt1 <= 18'b0 ;
  65.     else if( time_cnt1 == 18'h3ffff)
  66.            time_cnt1 <= time_cnt1 ;
  67.     else
  68.            time_cnt1 <= time_cnt1 +1'b1  ;   
  69.            
  70. always@( posedge i_50m_clk or negedge i_rst_n )//写数据或地址时间间隔,写一个字节数据命令的耗时时间
  71.     if( !i_rst_n )
  72.            time_cnt2 <= 16'b0 ;
  73.     else if(crt_state!=next_state)
  74.            time_cnt2 <= 16'b0 ;
  75.     else if( time_cnt2 == 16'hffff)
  76.            time_cnt2 <= 16'h0 ;
  77.     else
  78.            time_cnt2 <= time_cnt2 +1'b1  ;                    
  79.            

  80. //==================================================================
  81.    reg[7:0]  address_Y ;//行地址   
  82. reg[7:0]  address_X ;//列地址   
  83. reg[3:0] cnt_16   ;//列地址计数器
  84. reg[4:0] cnt_32   ;//行地址计数器
  85. reg[9:0] rom_addr ;//图片rom地址
  86. wire[7:0] disp_data ;//图片数据  

  87.       
  88.         
  89. //==================================================================
  90. //上电等待时间                     
  91. //==================================================================
  92. reg [19:0] power_up_cnt ;//上电等待时间42ms

  93. always@( posedge i_50m_clk or negedge i_rst_n )//
  94.     if( !i_rst_n )
  95.             power_up_cnt <= 20'b0   ;         
  96.     else if(power_up_cnt==20'hff)//power_up_cnt==22'hff
  97.            power_up_cnt<= power_up_cnt ;
  98.     else
  99.            power_up_cnt <= power_up_cnt + 1'b1  ;

  100. //====================================================================
  101. //状态转移
  102. //====================================================================
  103. always@( posedge i_50m_clk or negedge i_rst_n )//     
  104.     if( !i_rst_n )
  105.             crt_state <= Idle ;
  106.     else
  107.             crt_state <= next_state ;


  108. always@( *)  
  109.       case(crt_state)
  110.                  Idle : if(power_up_cnt==20'hff) //时间42ms到
  111.                                  next_state = Set_mode ;
  112.                         else
  113.                                  next_state = crt_state ;
  114.                                  
  115.                  Set_mode: if(time_cnt1 == 18'h3ffff) //模式设置
  116.                                  next_state = clear1 ;
  117.                            else
  118.                                  next_state = crt_state ;
  119.                 
  120.            clear1   : if(time_cnt1 == 18'h3ffff)//清零
  121.                            next_state = Disp_on_off ;
  122.                      else
  123.                            next_state = crt_state ;                 
  124.                                   
  125.                                
  126.           Disp_on_off: if(time_cnt1 == 18'h3ffff)//显示开、关
  127.                            next_state = Cursor ;
  128.                        else
  129.                            next_state = crt_state ;  
  130.                            
  131.           Cursor   : if(time_cnt1 == 18'h3ffff)//光标设置
  132.                            next_state = Stand_by ;
  133.                      else
  134.                            next_state = crt_state ;
  135.          
  136.          
  137.            Stand_by   :if(time_cnt1 == 18'h3ffff)//延时5ms
  138.                            next_state = Clear2 ;                                            
  139.                         else
  140.                            next_state = crt_state ;
  141.                            
  142.            Clear2     : if(time_cnt2 == 16'hffff)  //清零
  143.                              next_state = disp_function ;                                            
  144.                         else
  145.                              next_state = crt_state ;  
  146.                              
  147.            disp_function     : if(time_cnt2 == 16'hffff)  //开绘图功能
  148.                              next_state = Wr_address_Y ;                                            
  149.                         else
  150.                              next_state = crt_state ;  
  151.                                     

  152.           Wr_address_Y   : if(time_cnt2 == 16'hffff)//写行地址
  153.                                next_state = Wr_address_X ;           
  154.                            else
  155.                                next_state = crt_state ;
  156.          
  157.            Wr_address_X   : if(time_cnt2 == 16'hffff)//写列地址
  158.                                next_state = Wr_data ;           
  159.                            else
  160.                                next_state = crt_state ;
  161.                               
  162.            Wr_data    : if(rom_addr==10'd1023&&time_cnt2 == 16'hffff)  //1024个字节数据读完时,重新开始读数据
  163.                            next_state =Clear2 ;
  164.                         else if(cnt_16==4'd15&&time_cnt2 == 16'hffff)//没有读完1024个字节数据,写下一行数据
  165.                            next_state = Wr_address_Y ;
  166.                         else
  167.                            next_state = crt_state ;                                                      
  168.                                                    
  169.                                                                   
  170.         default :next_state = Idle ;
  171.      endcase                    

  172. //===================================================================产生地址和数据

  173. always@( posedge i_50m_clk or negedge i_rst_n )//
  174.     if(!i_rst_n )
  175.           cnt_16 <= 4'd0 ;
  176.     else if(crt_state==Clear2)
  177.            cnt_16 <= 4'd0 ;
  178.     else if(crt_state==Wr_data)//没一行16个字节,写完一个字节,计数器加1
  179.            if(time_cnt2==16'hffff)
  180.                 cnt_16 <= cnt_16+1'b1 ;
  181.            else
  182.                 cnt_16 <=cnt_16 ;
  183.     else
  184.               cnt_16 <=4'b0 ;



  185. always@( posedge i_50m_clk or negedge i_rst_n )//
  186.     if(!i_rst_n )
  187.           cnt_32 <= 5'd0 ;
  188.     else if(crt_state==Clear2)
  189.            cnt_32 <= 5'd0 ;
  190.     else if(cnt_16==4'd15&&time_cnt2==16'hffff)//每写完一行,行数加1
  191.             cnt_32 <= cnt_32+1'b1 ;
  192.     else
  193.             cnt_32 <= cnt_32 ;


  194.             
  195.             
  196.             

  197. always@( posedge i_50m_clk or negedge i_rst_n )//分上下屏,半屏的行地址范围8‘h80+(0~31)
  198.     if(!i_rst_n )
  199.            address_Y <=8'b0 ;
  200.     else if(crt_state==Wr_address_Y) //行地址,垂直地址
  201.            address_Y <=8'h80+cnt_32 ;
  202.     else
  203.            address_Y <=address_Y ;

  204. always@( posedge i_50m_clk or negedge i_rst_n )//分上下屏,只需给出首地址,列地址自动加1
  205.     if(!i_rst_n )
  206.            address_X <=8'b0 ;
  207.     else if(crt_state==Wr_address_X)
  208.           if(rom_addr<10'd512)      //上半屏行起始地址
  209.                address_X <=8'h80 ;
  210.           else                     //下半屏行起始地址
  211.                address_X <=8'h88;
  212.     else
  213.           address_X <=address_X ;     
  214.            

  215. ///=============================================================图像数据
  216. always@( posedge i_50m_clk or negedge i_rst_n )//rom地址
  217.     if(!i_rst_n )
  218.             rom_addr <= 10'd0 ;
  219.     else if(crt_state==Clear2)
  220.             rom_addr <= 10'd0 ;
  221.     else if(crt_state==Wr_data)
  222.             if(time_cnt2==16'hffff)
  223.                   rom_addr <= rom_addr +1'b1 ;
  224.             else
  225.                   rom_addr <= rom_addr ;
  226.     else
  227.             rom_addr <= rom_addr ;

  228. ///rom  一共1024个字节数据

  229. picture_rom u0_picture_rom(
  230.         .address( rom_addr ),
  231.         .clock  ( i_50m_clk),
  232.         .q      ( disp_data)
  233.                     );





  234. //==================================================================端口输出

  235. ///////lcd_rs,1写数据 ,0写命令
  236. always@( posedge i_50m_clk or negedge i_rst_n )//     
  237.     if( !i_rst_n )
  238.            o_lcd_rs <= 1'b0 ;
  239.     else if((crt_state ==Wr_data)&&(cnt_1000<16'd4000))
  240.            o_lcd_rs <= 1'b1 ;
  241.    else
  242.            o_lcd_rs <= 1'b0 ;
  243.             
  244. //==lcd_rw ,总是写
  245. always@( posedge i_50m_clk)
  246.        o_lcd_rw <= 1'b0 ;

  247.    

  248. //====lcd_en

  249. always@( posedge i_50m_clk or negedge i_rst_n )//     
  250.     if( !i_rst_n )
  251.           o_lcd_en <= 1'b0 ;
  252.     else if(crt_state==Stand_by)
  253.           o_lcd_en <= 1'b0 ;
  254.     else if(cnt_1000>6'd5&&cnt_1000<16'd3900)//高电平
  255.            o_lcd_en <= 1'b1 ;        
  256.     else                             
  257.            o_lcd_en <=  1'b0 ;
  258.             
  259.             
  260. //lcd_data ,address            
  261. always@( *)
  262.        case(crt_state)
  263.                Idle                      :  o_lcd_data = 8'h30 ;//模式设置
  264.                Set_mode                  :  o_lcd_data = 8'h30 ;//模式设置
  265.         Disp_on_off               :  o_lcd_data = 8'h0c ;//显示开、关
  266.         Cursor                    :  o_lcd_data = 8'h06 ;//光标设置
  267.         clear1,Clear2             :  o_lcd_data = 8'h01 ;//清零
  268.         disp_function             :   o_lcd_data = 8'h36 ;//绘图功能
  269.         Wr_address_Y                :  o_lcd_data = address_Y   ; //行地址
  270.          Wr_address_X                :  o_lcd_data = address_X   ; //行地址                                                
  271.         Wr_data                   :  o_lcd_data = disp_data ;//数据
  272.          default :     o_lcd_data = 8'hff ;
  273.         
  274.        endcase  
  275.       
  276.   
  277. ///=========================================================================
  278. //LED闪烁,指示fpga工作状态
  279. //==========================================================================  
  280.   
  281. led_block  u0_led_block(
  282.                .i_clk_50M   ( i_50m_clk ) ,
  283.                .i_fpga_clk  ( i_50m_clk ) ,
  284.                .i_rst_n     ( i_rst_n   ) ,
  285.                            
  286.                            
  287.                .o_led       (   o_led   )

  288.                   );  
  289.   
  290.       
  291. endmodule            
复制代码

所有资料51hei提供下载:
M15_LCD12864 display picture.zip (19.46 MB, 下载次数: 90)



评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏4 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:614861 发表于 2019-9-22 17:36 | 只看该作者
好资料
回复

使用道具 举报

板凳
ID:543026 发表于 2019-10-11 23:49 | 只看该作者
哇,楼主真的好人
回复

使用道具 举报

地板
ID:265157 发表于 2019-12-25 23:10 | 只看该作者
好东西
回复

使用道具 举报

5#
ID:726712 发表于 2020-4-11 08:27 来自手机 | 只看该作者
用fpga来驱动黑白屏,楼主辛苦,不错
回复

使用道具 举报

6#
ID:691028 发表于 2020-9-7 10:37 | 只看该作者
很好的资料,谢谢楼主的共享!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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