新聞中心

        EEPW首頁(yè) > 嵌入式系統(tǒng) > 牛人業(yè)話 > 【從零開(kāi)始走進(jìn)FPGA】 LCD1602 Hello World

        【從零開(kāi)始走進(jìn)FPGA】 LCD1602 Hello World

        作者: 時(shí)間:2015-04-24 來(lái)源:網(wǎng)絡(luò) 收藏

          前面說(shuō)過(guò),在C,C++等語(yǔ)言學(xué)習(xí)中,“Hello World”將會(huì)是第一個(gè)學(xué)習(xí)的代碼,但是在中由于電路驅(qū)動(dòng)的復(fù)雜性,與單片機(jī)雷同,我們無(wú)法在電腦上實(shí)現(xiàn)“Hello World”的顯示,而必須依靠相關(guān)硬件。因此我們不得不在一定的基礎(chǔ)上,才能講解關(guān)于字符液晶的驅(qū)動(dòng),以及Hello World的顯示。

        本文引用地址:http://www.104case.com/article/273149.htm

          雷同于前面MCU按鍵消抖動(dòng)移植代碼,此處也可以移植MCU 驅(qū)動(dòng)代碼。本例程不是Bingo原創(chuàng),是按照網(wǎng)友“小時(shí)不識(shí)月”的代碼,移植修改最后定型為Bingo版本(O(∩_∩)O哈哈~)。

          電路圖此處不解釋,太簡(jiǎn)單了。

          一、驅(qū)動(dòng)說(shuō)明

          由于的高速并行操作,并非順序執(zhí)行,在代碼上與MCU有所不同。此處先講解驅(qū)動(dòng)原理:

          (1)分頻以得到500KHz固定的頻率,初始化。如下圖所示,LCD_EN的頻率應(yīng)該控制在2M以內(nèi)(不同的LCD1602參數(shù)會(huì)有所不同)。

          

        wps_clip_image-31116

         

          (2)通過(guò)三段式狀態(tài)機(jī),來(lái)初始化以及給數(shù)據(jù)。

          (3)通過(guò)循環(huán)讀取某一“數(shù)組”,循環(huán)給LCD1602數(shù)據(jù),以接口形式方便改變。

          二、 LCD1602 FSM

          1. 代碼

          /*************************************************

          * Module Name : lcd1602_driver

          * Engineer : Crazy Bingo

          * Target Device : EP2C8Q208C8

          * Tool versions : Quartus II 11.0

          * Create Date : 2011-7-3

          * Revision : v1.0

          * Description :

          **************************************************/

          module lcd1602_driver

          (

          input clk,

          input rst_n,

          output lcd_en, // lcd enable

          output reg lcd_rs, // record,statement

          output lcd_rw,

          output reg [7:0] lcd_data

          );

          parameter [127:0] line_rom1 = "I am CrazyBingo!";

          parameter [127:0] line_rom2 = "Hello World*^_^*";

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

          reg [15:0] cnt;

          always @ (posedge clk or negedge rst_n)

          begin

          if(!rst_n)

          cnt <= 0;

          else

          cnt <= cnt + 1'b1;

          end

          assign lcd_en = cnt[15]; //lcd enable,keep same time

          assign lcd_rw = 1'b0; //write only

          wire cmd_flag = (cnt == 16'h7FFF) ? 1'b1 : 1'b0; //when lcd_en is steady,write a cmd

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

          // Gray code : 40 states

          parameter IDLE = 8'h00; // IDLE

          // lcd init

          parameter DISP_SET = 8'h01; // display mode

          parameter DISP_OFF = 8'h03; // off display

          parameter CLR_SCR = 8'h02; // clear the lcd

          parameter CURSOR_SET1 = 8'h06; // cursor set

          parameter CURSOR_SET2 = 8'h07; // on display, cursor set

          // display 1th line

          parameter ROW1_ADDR = 8'h05;

          parameter ROW1_0 = 8'h04;

          parameter ROW1_1 = 8'h0C;

          parameter ROW1_2 = 8'h0D;

          parameter ROW1_3 = 8'h0F;

          parameter ROW1_4 = 8'h0E;

          parameter ROW1_5 = 8'h0A;

          parameter ROW1_6 = 8'h0B;

          parameter ROW1_7 = 8'h09;

          parameter ROW1_8 = 8'h08;

          parameter ROW1_9 = 8'h18;

          parameter ROW1_A = 8'h19;

          parameter ROW1_B = 8'h1B;

          parameter ROW1_C = 8'h1A;

          parameter ROW1_D = 8'h1E;

          parameter ROW1_E = 8'h1F;

          parameter ROW1_F = 8'h1D;

          // display 2th line

          parameter ROW2_ADDR = 8'h1C;

          parameter ROW2_0 = 8'h14;

          parameter ROW2_1 = 8'h15;

          parameter ROW2_2 = 8'h17;

          parameter ROW2_3 = 8'h16;

          parameter ROW2_4 = 8'h12;

          parameter ROW2_5 = 8'h13;

          parameter ROW2_6 = 8'h11;

          parameter ROW2_7 = 8'h10;

          parameter ROW2_8 = 8'h30;

          parameter ROW2_9 = 8'h31;

          parameter ROW2_A = 8'h33;

          parameter ROW2_B = 8'h32;

          parameter ROW2_C = 8'h36;

          parameter ROW2_D = 8'h37;

          parameter ROW2_E = 8'h35;

          parameter ROW2_F = 8'h34;

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

          reg [5:0] current_state, next_state;

          // FSM: always1

          always @ (posedge clk or negedge rst_n)

          begin

          if(!rst_n)

          current_state <= IDLE;

          else if(cmd_flag)

          current_state <= next_state;

          end

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

          // FSM: always2

          always@*

          begin

          case(current_state)

          // lcd init

          IDLE : next_state = DISP_SET;

          DISP_SET : next_state = DISP_OFF;

          DISP_OFF : next_state = CLR_SCR;

          CLR_SCR : next_state = CURSOR_SET1;

          CURSOR_SET1 : next_state = CURSOR_SET2;

          CURSOR_SET2 : next_state = ROW1_ADDR;

          // display 1th line

          ROW1_ADDR : next_state = ROW1_0;

          ROW1_0 : next_state = ROW1_1;

          ROW1_1 : next_state = ROW1_2;

          ROW1_2 : next_state = ROW1_3;

          ROW1_3 : next_state = ROW1_4;

          ROW1_4 : next_state = ROW1_5;

          ROW1_5 : next_state = ROW1_6;

          ROW1_6 : next_state = ROW1_7;

          ROW1_7 : next_state = ROW1_8;

          ROW1_8 : next_state = ROW1_9;

          ROW1_9 : next_state = ROW1_A;

          ROW1_A : next_state = ROW1_B;

          ROW1_B : next_state = ROW1_C;

          ROW1_C : next_state = ROW1_D;

          ROW1_D : next_state = ROW1_E;

          ROW1_E : next_state = ROW1_F;

          ROW1_F : next_state = ROW2_ADDR;

          // display 2th line

          ROW2_ADDR : next_state = ROW2_0;

          ROW2_0 : next_state = ROW2_1;

          ROW2_1 : next_state = ROW2_2;

          ROW2_2 : next_state = ROW2_3;

          ROW2_3 : next_state = ROW2_4;

          ROW2_4 : next_state = ROW2_5;

          ROW2_5 : next_state = ROW2_6;

          ROW2_6 : next_state = ROW2_7;

          ROW2_7 : next_state = ROW2_8;

          ROW2_8 : next_state = ROW2_9;

          ROW2_9 : next_state = ROW2_A;

          ROW2_A : next_state = ROW2_B;

          ROW2_B : next_state = ROW2_C;

          ROW2_C : next_state = ROW2_D;

          ROW2_D : next_state = ROW2_E;

          ROW2_E : next_state = ROW2_F;

          ROW2_F : next_state = ROW1_ADDR;

          default : next_state = IDLE ;

          endcase

          end

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

          // FSM: always3

          always @ (posedge clk or negedge rst_n)

          begin

          if(!rst_n)

          begin

          lcd_rs <= 0;

          lcd_data <= 8'hXX;

          end

          else if(cmd_flag)

          begin

          // write statement

          case(next_state)

          IDLE : lcd_rs <= 0; //statement

          //lcd init

          DISP_SET : lcd_rs <= 0; //statement

          DISP_OFF : lcd_rs <= 0; //statement

          CLR_SCR : lcd_rs <= 0; //statement

          CURSOR_SET1 : lcd_rs <= 0; //statement

          CURSOR_SET2 : lcd_rs <= 0; //statement

          // display 1th line

          ROW1_ADDR : lcd_rs <= 0; //statement

          ROW1_0 : lcd_rs <= 1; //record

          ROW1_1 : lcd_rs <= 1; //record

          ROW1_2 : lcd_rs <= 1; //record

          ROW1_3 : lcd_rs <= 1; //record

          ROW1_4 : lcd_rs <= 1; //record

          ROW1_5 : lcd_rs <= 1; //record

          ROW1_6 : lcd_rs <= 1; //record

          ROW1_7 : lcd_rs <= 1; //record

          ROW1_8 : lcd_rs <= 1; //record

          ROW1_9 : lcd_rs <= 1; //record

          ROW1_A : lcd_rs <= 1; //record

          ROW1_B : lcd_rs <= 1; //record

          ROW1_C : lcd_rs <= 1; //record

          ROW1_D : lcd_rs <= 1; //record

          ROW1_E : lcd_rs <= 1; //record

          ROW1_F : lcd_rs <= 1; //record

          // display 2th line

          ROW2_ADDR : lcd_rs <= 0; //statement

          ROW2_0 : lcd_rs <= 1; //record

          ROW2_1 : lcd_rs <= 1; //record

          ROW2_2 : lcd_rs <= 1; //record

          ROW2_3 : lcd_rs <= 1; //record

          ROW2_4 : lcd_rs <= 1; //record

          ROW2_5 : lcd_rs <= 1; //record

          ROW2_6 : lcd_rs <= 1; //record

          ROW2_7 : lcd_rs <= 1; //record

          ROW2_8 : lcd_rs <= 1; //record

          ROW2_9 : lcd_rs <= 1; //record

          ROW2_A : lcd_rs <= 1; //record

          ROW2_B : lcd_rs <= 1; //record

          ROW2_C : lcd_rs <= 1; //record

          ROW2_D : lcd_rs <= 1; //record

          ROW2_E : lcd_rs <= 1; //record

          ROW2_F : lcd_rs <= 1; //record

          endcase

          // write lcd_data

          case(next_state)

          IDLE : lcd_data <= 8'hxx;

          //lcd init

          DISP_SET : lcd_data <= 8'h38; //set 16X2,5X7 ,8 bits record

          DISP_OFF : lcd_data <= 8'h08; //off display

          CLR_SCR : lcd_data <= 8'h01; //clear lcd

          CURSOR_SET1 : lcd_data <= 8'h06; //cursor set

          CURSOR_SET2 : lcd_data <= 8'h0C; //on display

          // display 1th line

          ROW1_ADDR : lcd_data <= 8'h80;

          ROW1_0 : lcd_data <= line_rom1[127:120];

          ROW1_1 : lcd_data <= line_rom1[119:112];

          ROW1_2 : lcd_data <= line_rom1[111:104];

          ROW1_3 : lcd_data <= line_rom1[103: 96];

          ROW1_4 : lcd_data <= line_rom1[ 95: 88];

          ROW1_5 : lcd_data <= line_rom1[ 87: 80];

          ROW1_6 : lcd_data <= line_rom1[ 79: 72];

          ROW1_7 : lcd_data <= line_rom1[ 71: 64];

          ROW1_8 : lcd_data <= line_rom1[ 63: 56];

          ROW1_9 : lcd_data <= line_rom1[ 55: 48];

          ROW1_A : lcd_data <= line_rom1[ 47: 40];

          ROW1_B : lcd_data <= line_rom1[ 39: 32];

          ROW1_C : lcd_data <= line_rom1[ 31: 24];

          ROW1_D : lcd_data <= line_rom1[ 23: 16];

          ROW1_E : lcd_data <= line_rom1[ 15: 8];

          ROW1_F : lcd_data <= line_rom1[ 7: 0];

          // display 2th line

          ROW2_ADDR : lcd_data <= 8'hC0;

          ROW2_0 : lcd_data <= line_rom2[127:120];

          ROW2_1 : lcd_data <= line_rom2[119:112];

          ROW2_2 : lcd_data <= line_rom2[111:104];

          ROW2_3 : lcd_data <= line_rom2[103: 96];

          ROW2_4 : lcd_data <= line_rom2[ 95: 88];

          ROW2_5 : lcd_data <= line_rom2[ 87: 80];

          ROW2_6 : lcd_data <= line_rom2[ 79: 72];

          ROW2_7 : lcd_data <= line_rom2[ 71: 64];

          ROW2_8 : lcd_data <= line_rom2[ 63: 56];

          ROW2_9 : lcd_data <= line_rom2[ 55: 48];

          ROW2_A : lcd_data <= line_rom2[ 47: 40];

          ROW2_B : lcd_data <= line_rom2[ 39: 32];

          ROW2_C : lcd_data <= line_rom2[ 31: 24];

          ROW2_D : lcd_data <= line_rom2[ 23: 16];

          ROW2_E : lcd_data <= line_rom2[ 15: 8];

          ROW2_F : lcd_data <= line_rom2[ 7: 0];

          endcase

          end

          end

          endmodule

          2. 狀態(tài)機(jī)

          (1)以下是State machine如下所示:

          

        wps_clip_image-31119

         

          (2)模塊可分為一下幾個(gè)狀態(tài)

          

        image

         

          3. “Hello World”實(shí)物顯示

          parameter [127:0] line_rom1 = "I am CrazyBingo!";

          parameter [127:0] line_rom2 = "Hello World*^_^*";

          

        wps_clip_image-31174

        fpga相關(guān)文章:fpga是什么


        c++相關(guān)文章:c++教程




        關(guān)鍵詞: FPGA LCD1602

        評(píng)論


        相關(guān)推薦

        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 三江| 青岛市| 三穗县| 克拉玛依市| 伊金霍洛旗| 佛教| 大田县| 体育| 阳曲县| 廉江市| 重庆市| 栾城县| 宁波市| 穆棱市| 界首市| 敦化市| 龙口市| 临江市| 文安县| 班戈县| 德保县| 松溪县| 称多县| 民县| 阿尔山市| 长兴县| 永清县| 安龙县| 仙居县| 盐津县| 托克托县| 纳雍县| 长治市| 自治县| 枣强县| 上杭县| 漯河市| 宁陵县| 苍梧县| 师宗县| 榆中县|