(总结)(原创)LCD屏的学习总结

(总结)(原创)LCD屏的学习总结(针对ST7920)

  前言:这么长时间一直没有写博客,是因为总结的东西不能随便的发出来,因为不够完善,尤其对于我这种初学者,但经过一段时间的经历,必须要有深思熟虑,有自己的亲身经历在里面。在这两个星期的时间里,在一个简单的LCD屏的驱动上汲取了许多 营养。该有个学习总结了。

     1、学习态度和做事的方式。

  认真、全面、仔细、耐心。这是最重要的几点,我一共写了多达3个完全不同的版本去驱动LCD,却一直没有我想要的结果,一直在怀疑我的软件问题,可到最后在发现是我没有仔细阅读通信协议,在初始化的过程中 少了一个指令。另外在仿真的时候也没有对所有的情况做一个完整的检查。

  2、将组合电路和时序电路的分离。

  一个好用的设计应该是在设计的初期就应该预想到寄存器的个数和它的功能,我认为在电路设计中有很大的部分是在于决定我的寄存器的安放。 在我最后的设计中,我使用了一个移位寄存器,一个发送数据缓冲器,对于每行的数据存储区的输出也有一个数据缓冲,以应对于作出显示内容的选择。我在初学设计的时候使用的都是时序和组合混合的方式,但在这次的设计中我使用的是分开描述的方式,这样书写的方式有利于对于整个系统的理解和实现,对于电路综合后有一个预测和把握。刚开始的时候应用的不是很熟练,渐渐的发现自己对于Verilog的语句和实现方式都没有很好的理解,比如阻塞赋值和非阻塞赋值没有很好的理解,对于begin和end块语句的顺序执行方式也没有体会到。

  3、软件代码和说明

  (1)我没有使用专门的ROM是直接自己书写的ROM。

  (2)我对于发送数据的方式有点问题,应该是先发高位再发低位,我做成了先发低位再发高位,只需要将右移改为左移,将高8位输出。

  (3)控制方式,我将每行要发送的汉字存储到ROM里,然后根据输入的显示编码,就达到文字的改变(这是因为我是为任意波形发生器写的专门的调节显示模块的,经过改进可以应用于其他方式),然后向LCD发送数据是从第一行向最后一行不断地重复扫描。

  (4)希望大家提出建议,诚恳的需要大家的批评。

  (5) 本文是针对st7920写的驱动。 

  4、源代码如下:

 

 //-----------------------------------------------------

// Design Name : lcd
// File Name   : gz_lcd_v3.v
// Function    : lcd
// Aurthor     : guanzhou
//Vertion      : v 3.0
//Date         : 2009.10.22
//-----------------------------------------------------
`timescale  1ns/100ps
module lcd
    (
    
//input 
    rclk,rst,
    addr_f,addr_p,addr_m,
    control,
    
//ouput 
    e,rs,rw,
    data
    );
    
parameter    max_count_f  =  4_749_999;
    
//parameter    max_count_f  =  2;
    parameter    wide_count_f  =  23;
    
parameter    wide_f  =  3,
                wide_p  
=  3,
                wide_m  
=  3;
                
    
parameter    word_size  =  11;
    
parameter    max_b  =  63;
    
    
parameter   order_set = 8'b0011_0000,
                cursor_set  =  8'b0000_1110,
                addr_set  =  8'b0000_0001,
                display_set  =  8'b0000_0100;
    parameter    idle  =  4'b0001,
                mode  =  4'b0010,
                freq  =  4'b0100,
                phase  =  4'b1000;
    input rclk,rst;
    
input [wide_f-1:0] addr_f;
    
input [wide_p-1:0] addr_p;
    
input [wide_m-1:0] addr_m;
    
input [2:0] control;
    
output e,rs,rw;
    
output [7:0] data;
    
reg shift;
    
//========================================================
    
//分频
    
//========================================================
    reg  [wide_count_f-1:0] count_f;
    
reg clk;
    
always @(posedge rclk or negedge rst)
    
begin
        
if(!rst)
            
begin
                count_f  
<=  0;
                clk  
<=  0;
            
end
        
else if(count_f==max_count_f)
            
begin
                count_f  
<=  0;
                clk  
<=  ~clk;
            
end
        
else
            count_f  
<=  count_f  +  1'b1;
    end
    
wire e;
    
assign e  =  clk;                        //读写信号为4Hz的时钟信号
    reg [max_b+15:0]     data_f,
                        data_p,
                        data_m;
    
always @(addr_m or addr_f or addr_p)          //定义ROM
    begin
        
case(addr_m)
            
3'd0:  data_m[max_b-1:0]  =  64'hCEF7_D3CA_CEA2_B5E7;
            
3'd1:  data_m[max_b-1:0]  =  64'hCFE0_CEBB_CFE0_CEBB;
            
3'd2:  data_m[max_b-1:0]  =  64'hC6B5_C2CA_C6B5_C2CA;
            
3'd3:  data_m[max_b-1:0]  =  64'hCEF7_D3CA_CEA2_B5E7;
            
3'd4:  data_m[max_b-1:0]  =  64'hCEF7_D3CA_CEA2_B5E7;
            
3'd5:  data_m[max_b-1:0]  =  64'hCFE0_CEBB_CFE0_CEBB;
            
3'd6:  data_m[max_b-1:0]  =  64'hC6B5_C2CA_C6B5_C2CA;
            
3'd7:  data_m[max_b-1:0]  =  64'hCEF7_D3CA_CEA2_B5E7;
        
endcase
        
case(addr_f)
            
3'd0:  data_f[max_b-1:0]  =  64'hC6B5_C2CA_C6B5_C2CA;
            
3'd1:  data_f[max_b-1:0]  =  64'hCFE0_CEBB_CFE0_CEBB;
            
3'd2:  data_f[max_b-1:0]  =  64'hCEF7_D3CA_CEA2_B5E7;
            
3'd3:  data_f[max_b-1:0]  =  64'hCFE0_CEBB_CFE0_CEBB;
            
3'd4:  data_f[max_b-1:0]  =  64'hC6B5_C2CA_C6B5_C2CA;
            
3'd5:  data_f[max_b-1:0]  =  64'hCEF7_D3CA_CEA2_B5E7;
            
3'd6:  data_f[max_b-1:0]  =  64'hCFE0_CEBB_CFE0_CEBB;
            
3'd7:  data_f[max_b-1:0]  =  64'hCEF7_D3CA_CEA2_B5E7;
        
endcase
        
case(addr_p)
            
3'd0:  data_p[max_b-1:0]  =  64'hCFE0_CEBB_CFE0_CEBB;
            
3'd1:  data_p[max_b-1:0]  =  64'hC6B5_C2CA_C6B5_C2CA;
            
3'd2:  data_p[max_b-1:0]  =  64'hCFE0_CEBB_CFE0_CEBB;
            
3'd3:  data_p[max_b-1:0]  =  64'hCEF7_D3CA_CEA2_B5E7;
            
3'd4:  data_p[max_b-1:0]  =  64'hC6B5_C2CA_C6B5_C2CA;
            
3'd5:  data_p[max_b-1:0]  =  64'hCFE0_CEBB_CFE0_CEBB;
            
3'd6:  data_p[max_b-1:0]  =  64'hCEF7_D3CA_CEA2_B5E7;
            
3'd7:  data_p[max_b-1:0]  =  64'hC6B5_C2CA_C6B5_C2CA;
        
endcase
    
end
    
    
always @(control)                               //要求在每一行前面加上指示星号,表明当前的波形设置
    begin
        
case(control)
            
3'b001:
                begin
                    data_m[max_b
+15:max_b]  <=  16'hA1F2;
                    data_f[max_b+15:max_b]  <=  16'hA2A0;
                    data_p[max_b+15:max_b]  <=  16'hA2A0;
                end
            
3'b010:
                begin
                    data_m[max_b
+15:max_b]  <=  16'hA2A0;
                    data_f[max_b+15:max_b]  <=  16'hA1F2;
                    data_p[max_b+15:max_b]  <=  16'hA2A0;
                end
            
3'b100:
                begin
                    data_m[max_b
+15:max_b]  <=  16'hA2A0;
                    data_f[max_b+15:max_b]  <=  16'hA2A0;
                    data_p[max_b+15:max_b]  <=  16'hA1F2;
                end
            
default:
                
begin
                    data_m[max_b
+15:max_b]  <=  16'hA2A0;
                    data_f[max_b+15:max_b]  <=  16'hA2A0;
                    data_p[max_b+15:max_b]  <=  16'hA2A0;
                end
        
endcase
    
end
    
//========================================================
    
//行扫描循环控制状态机
    
//========================================================
    reg [7:0] data;
    
reg rs,rw;
    
reg [4:0] bit_count;
    
reg [4:0] state,next_state;
    
reg [max_b+15:0] data_shift;
    
always @(state or bit_count)
    
begin
        shift 
=  0;
        next_state  
=  state;
        
case(state)
            idle:
                
begin                       
                    
if(bit_count==word_size-2)
                            shift  
=  1;
                    
if(bit_count==word_size-3)
                        next_state  
=  mode;
                
end
            mode:
                
begin
                    
if(bit_count==word_size-2)
                            shift  
=  1;
                    
if(bit_count==word_size-3)
                        next_state  
=  freq;
                
end            
            freq:
                
begin
                    
if(bit_count==word_size-2)
                            shift  
=  1;
                    
if(bit_count==word_size-3)
                        next_state  
=  phase;
                
end
            phase:
                
begin
                    
if(bit_count==word_size-2)
                            shift  
=  1;
                    
if(bit_count==word_size-3)
                        next_state  
=  mode;
                
end
            
default:    
                
begin
                    shift 
=  0;
                    next_state  
=  state;
                
end
        
endcase
                    
    
end
    
always @(posedge clk or negedge rst)
    
begin
        
if(!rst)
            state  
<=  idle;
        
else
            state  
<=  next_state;
    
end
    
//==========================================================
    
//发送文字信息数据
    
//==========================================================
    always @(posedge clk or negedge rst)
    
begin
        
if(!rst)
            
begin
                data  
<=  order_set;
                bit_count  
<=  0;
                data_shift  
<=  {39'd0,display_set,addr_set,cursor_set,order_set,order_set};
            end
        
else
            
begin
                
                
if(shift)                   // ?????
                    case(state)
                        idle:
                            
begin
                                data_shift  
<=  {39'd0,display_set,addr_set,cursor_set,order_set,order_set};
                                data  <=  order_set;
                            
end
                        mode: 
                            
begin
                                data_shift  
<=  data_m;
                                data  
<=  8'h90;
                            end
                        freq:
                            
begin
                                data_shift  
<=  data_f;
                                data  
<=  8'h80;
                            end
                        phase:
                            
begin
                                data_shift  
<=  data_p;
                                data  
<=  8'h98;
                            end
                        
default
                            
begin
                                data_shift  
<=  data_shift;
                                data  
<= 8'h00;
                            end
                    
endcase
                
else
                    
begin
                        data  
<=  data_shift[7:0];
                        data_shift  
<=  {8'b1111_1111,data_shift[max_b+15:8]};
                    end
                
                
if(shift)
                    bit_count  
<=  0;
                
else
                    bit_count  
<= bit_count  +  1'b1;
            end
    
end
    
//================================================================
    
//发送数据格式指令
    
//================================================================
    always @(posedge clk or negedge rst)
    
begin
        
if(!rst)
            
begin
                rw  
<=     1;
                rs  
<=  1;
            
end
        
else
            
if(state==idle)
                
begin
                    rs  
<=  0;
                    rw  
<=  0;
                
end
            
else if(shift)
                
begin
                    rs  
<=  0;
                    rw  
<=  0;
                
end
            
else
                
begin
                    rs  
<=  1;
                    rw  
<=  0;
                
end
    
end                
endmodule                
                    
            
            
        
                
                
                
    

 

 

posted @ 2009-10-28 22:31  六度  阅读(717)  评论(2编辑  收藏  举报