首页 > 代码库 > lcd1602如何自定义汉字(verilog)

lcd1602如何自定义汉字(verilog)

今天一鼓作气,再研究了一下如何用LCD1602自定义汉字

1、用字模软件获取汉字所对应的数据(因为嫌麻烦所以直接用了网上一个帖子里有关“电”的数据,如下:04,1f,15,1f,15,15,1f,04,07)帖子链接:http://www.51hei.com/mcu/3696.html

2、主要知识点

(1)lcd1602的11个指令集与lcd1602的基本显示,前两篇文章已经详细说过,链接如下  

http://www.cnblogs.com/aslmer/p/5801363.html

http://www.cnblogs.com/aslmer/p/5819422.html

(2)DDRAM 与 CGRAM 的区别,根据数据手册知道我们可以定义8个汉字,具体更多知识点请自己百度。

(3)主要的两个指令 Set CGRAM Address 、 Write data to RAM 。

3、在上篇文章的基础上修改代码如下:
难点就在状态机的控制,重点修改部分都用红色标注
module lcd_1602_driver(                clk    ,                rst_n  ,                lcd_en ,                lcd_rw ,                lcd_rs ,                lcd_data              );input        clk    ;input        rst_n  ;output       lcd_en ;output       lcd_rw ;output       lcd_rs ;output [7:0] lcd_data;wire         clk ;wire         rst_n  ;wire         lcd_en ;wire         lcd_rw;reg  [7:0]   lcd_data;reg          lcd_rs  ;reg [7:0]    c_state ;reg [7:0]    n_state ;wire  [127:0]  row_1;wire write_flag;//wire  [127:0]  row_2;assign row_1 ="i am liu xiao yi" ;//assign row_2 ="happy everyday !";//----------------------------------------------------------------------//initialize//first step is waitng more than 20 ms.parameter TIME_15MS = 1000_000 ; //20000000/20=1000_000//parameter TIME_15MS = 9‘h100 ; //just for testparameter TIME_500HZ= 100_000  ; ////parameter TIME_500HZ= 4‘hf;  //just for test//use gray codeparameter         IDLE=    8h00  ;                             parameter SET_FUNCTION=    8h01  ;parameter     DISP_OFF=    8h03  ;parameter   DISP_CLEAR=    8h02  ;parameter   ENTRY_MODE=    8h06  ;parameter   DISP_ON   =    8h07  ;parameter    ROW1_ADDR=    8h05  ;//----------------------修改1,增添这两个状态parameter  CGRAM_ADDR   =   8hf1;parameter  CGRAM_DATA   =   http://www.mamicode.com/8hf2;//-----------------------parameter       ROW1_0=    8h04  ;parameter       ROW1_1=    8h0C  ;parameter       ROW1_2=    8h0D  ;parameter       ROW1_3=    8h0F  ;parameter       ROW1_4=    8h0E  ;parameter       ROW1_5=    8h0A  ;parameter       ROW1_6=    8h0B  ;parameter       ROW1_7=    8h09  ;parameter       ROW1_8=  8h08  ;parameter       ROW1_9=    8h18  ;parameter       ROW1_A=    8h19  ;parameter       ROW1_B=    8h1B  ;parameter       ROW1_C=    8h1A  ;parameter       ROW1_D=    8h1E  ;parameter       ROW1_E=    8h1F  ;parameter       ROW1_F=    8h1D  ;parameter    ROW2_ADDR=    8h1C  ;parameter       ROW2_0=    8h14  ;parameter       ROW2_1=    8h15  ;parameter       ROW2_2=    8h17  ;parameter       ROW2_3=    8h16  ;parameter       ROW2_4=    8h12  ;parameter       ROW2_5=    8h13  ;parameter       ROW2_6=    8h11  ;parameter       ROW2_7=    8h10  ;parameter       ROW2_8=    8h30  ;parameter       ROW2_9=    8h31  ;parameter       ROW2_A=    8h33  ;parameter       ROW2_B=    8h32  ;parameter       ROW2_C=    8h36  ;parameter       ROW2_D=    8h37  ;parameter       ROW2_E=    8h35  ;parameter       ROW2_F=    8h34  ;reg [19:0] cnt_15ms ;always  @(posedge clk or negedge rst_n)begin    if(rst_n==1b0)begin        cnt_15ms<=0;    end    else if(cnt_15ms == TIME_15MS -1)begin        cnt_15ms<=cnt_15ms;    end    else        cnt_15ms<=cnt_15ms + 1 ;endwire delay_done = (cnt_15ms==TIME_15MS-1)? 1b1 : 1b0 ;//----------------------------------------------------------------------//500nsreg [19:0] cnt_500hz;always  @(posedge clk or negedge rst_n)begin    if(rst_n==1b0)begin        cnt_500hz <= 0;    end    else if(delay_done==1)begin        if(cnt_500hz== TIME_500HZ - 1)            cnt_500hz<=0;        else            cnt_500hz<=cnt_500hz + 1 ;    end    else        cnt_500hz<=0;endassign lcd_en = (cnt_500hz>(TIME_500HZ-1)/2)? 1b0 : 1b1;  //下降沿assign write_flag = (cnt_500hz==TIME_500HZ - 1) ? 1b1 : 1b0 ;//set_function ,display off ,display clear ,entry mode set//----------------------------------------------------------------------always  @(posedge clk or negedge rst_n)begin    if(rst_n==1b0)begin        c_state <= IDLE    ;    end    else if(write_flag==1) begin        c_state<= n_state  ;    end    else        c_state<=c_state   ;end//-------------------------修改2 因为自定义一个汉字需要写8次地址并且给8次数据,所以用num和num1来控制。reg [2:0]num,num1;always  @(posedge clk or negedge rst_n)begin    if(rst_n==1b0)begin        num<=0;    end    else if(c_state== CGRAM_ADDR&&write_flag) begin        if(num==7)            num<=0;        else            num<=num+8b1;    end    else        num<=num;endalways  @(posedge clk or negedge rst_n)begin    if(rst_n==1b0)begin        num1<=0;    end    else if(c_state== CGRAM_DATA&&write_flag) begin        if(num1==7)            num1<=0;        else            num1<=num1+8b1;    end    else        num1<=num1;end//------------------------------------------------------------always  @(*)begin    case (c_state)        IDLE: n_state = SET_FUNCTION ;SET_FUNCTION: n_state = DISP_OFF     ;    DISP_OFF: n_state = DISP_CLEAR   ;  DISP_CLEAR: n_state = ENTRY_MODE   ;  ENTRY_MODE: n_state = DISP_ON      ;  DISP_ON   : n_state = CGRAM_ADDR   ;  //------------------------------------------------ 修改3 当8个数据都写进相应地址里的时候,状态机才跳到ROW1_ADDR状态  CGRAM_ADDR: n_state = CGRAM_DATA   ;   // 8‘hfe;  CGRAM_DATA:   if(num1==7)                  n_state = ROW1_ADDR;                else                  n_state= CGRAM_ADDR;  //------------------------------------------------    ROW1_ADDR: n_state = ROW1_0       ;      ROW1_0: n_state = ROW1_1       ;      ROW1_1: n_state = ROW1_2       ;      ROW1_2: n_state = ROW1_3       ;      ROW1_3: n_state = ROW1_4       ;      ROW1_4: n_state = ROW1_5       ;      ROW1_5: n_state = ROW1_6       ;      ROW1_6: n_state = ROW1_7       ;      ROW1_7: n_state = ROW1_8       ;      ROW1_8: n_state = ROW1_9       ;      ROW1_9: n_state = ROW1_A       ;      ROW1_A: n_state = ROW1_B       ;      ROW1_B: n_state = ROW1_C       ;      ROW1_C: n_state = ROW1_D       ;      ROW1_D: n_state = ROW1_E       ;      ROW1_E: n_state = ROW1_F       ;      ROW1_F: n_state = ROW2_ADDR    ;   ROW2_ADDR: n_state = ROW2_0       ;      ROW2_0: n_state = ROW2_1       ;      ROW2_1: n_state = ROW2_2       ;      ROW2_2: n_state = ROW2_3       ;      ROW2_3: n_state = ROW2_4       ;      ROW2_4: n_state = ROW2_5       ;      ROW2_5: n_state = ROW2_6       ;      ROW2_6: n_state = ROW2_7       ;      ROW2_7: n_state = ROW2_8       ;      ROW2_8: n_state = ROW2_9       ;      ROW2_9: n_state = ROW2_A       ;      ROW2_A: n_state = ROW2_B       ;      ROW2_B: n_state = ROW2_C       ;      ROW2_C: n_state = ROW2_D       ;      ROW2_D: n_state = ROW2_E       ;      ROW2_E: n_state = ROW2_F       ;      ROW2_F: n_state = ROW1_ADDR    ;     default: n_state = n_state      ;   endcase    end      assign lcd_rw = 0;   always  @(posedge clk or negedge rst_n)begin       if(rst_n==1b0)begin           lcd_rs <= 0 ;   //order or data  0: order 1:data       end       else if(write_flag == 1)begin           if((n_state==SET_FUNCTION)||(n_state==DISP_OFF)||              (n_state==DISP_CLEAR)||(n_state==ENTRY_MODE)||              (n_state==DISP_ON ) ||(n_state==ROW1_ADDR)||              (n_state==ROW2_ADDR)||(n_state==CGRAM_ADDR))begin //修改4           lcd_rs<=0 ;           end            else  begin           lcd_rs<= 1;           end       end       else begin           lcd_rs<=lcd_rs;       end        end                      always  @(posedge clk or negedge rst_n)begin       if(rst_n==1b0)begin           lcd_data<=0 ;       end       else  if(write_flag)begin           case(n_state)                 IDLE: lcd_data <= 8hxx;         SET_FUNCTION: lcd_data <= 8h38; //2*16 5*8 8位数据             DISP_OFF: lcd_data <= 8h08;           DISP_CLEAR: lcd_data <= 8h01;           ENTRY_MODE: lcd_data <= 8h06;           DISP_ON   : lcd_data <= 8h0c;  //显示功能开,没有光标,且不闪烁,// ------------------------------------修改5           CGRAM_ADDR:   begin                    case(num)                        0: lcd_data <= 8h40;                        1: lcd_data <= 8h41;                        2: lcd_data <= 8h42;                        3: lcd_data <= 8h43;                        4: lcd_data <= 8h44;                        5: lcd_data <= 8h45;                        6: lcd_data <= 8h46;                        7: lcd_data <= 8h47;                            endcase                     end           CGRAM_DATA:  begin                    case(num1)                        0: lcd_data <= 8h04;                        1: lcd_data <= 8h1f;                        2: lcd_data <= 8h15;                        3: lcd_data <= 8h1f;                        4: lcd_data <= 8h15;                        5: lcd_data <= 8h1f;                        6: lcd_data <= 8h04;                        7: lcd_data <= 8h07;                    endcase                    end   //-------------------------------------修改6第一行显示 i am liu xiao yi  第二行全部显示汉字电            ROW1_ADDR: lcd_data <= 8h80; //00+80               ROW1_0: lcd_data <= row_1 [127:120];               ROW1_1: lcd_data <= row_1 [119:112];               ROW1_2: lcd_data <= row_1 [111:104];               ROW1_3: lcd_data <= row_1 [103: 96];               ROW1_4: lcd_data <= row_1 [ 95: 88];               ROW1_5: lcd_data <= row_1 [ 87: 80];               ROW1_6: lcd_data <= row_1 [ 79: 72];               ROW1_7: lcd_data <= row_1 [ 71: 64];               ROW1_8: lcd_data <= row_1 [ 63: 56];               ROW1_9: lcd_data <= row_1 [ 55: 48];               ROW1_A: lcd_data <= row_1 [ 47: 40];               ROW1_B: lcd_data <= row_1 [ 39: 32];               ROW1_C: lcd_data <= row_1 [ 31: 24];               ROW1_D: lcd_data <= row_1 [ 23: 16];               ROW1_E: lcd_data <= row_1 [ 15:  8];               ROW1_F: lcd_data <= row_1 [  7:  0];            ROW2_ADDR: lcd_data <= 8hc0;      //40+80               ROW2_0: lcd_data <=8h00; //电               ROW2_1: lcd_data <=8h00;               ROW2_2: lcd_data <=8h00;               ROW2_3: lcd_data <=8h00;               ROW2_4: lcd_data <=8h00;               ROW2_5: lcd_data <=8h00;               ROW2_6: lcd_data <=8h00;               ROW2_7: lcd_data <=8h00;               ROW2_8: lcd_data <=8h00;               ROW2_9: lcd_data <=8h00;               ROW2_A: lcd_data <=8h00;               ROW2_B: lcd_data <=8h00;               ROW2_C: lcd_data <=8h00;               ROW2_D: lcd_data <=8h00;               ROW2_E: lcd_data <=8h00;               ROW2_F: lcd_data <=8h00;           endcase                            end       else              lcd_data<=lcd_data ;   endendmodule

4、显示结果

技术分享

 

 转载请注明出处:http://www.cnblogs.com/aslmer/p/5819868.html

lcd1602如何自定义汉字(verilog)