這是例程
0.png (46.25 KB, 下載次數(shù): 115)
下載附件
2018-5-25 01:55 上傳
全部資料51hei下載地址:
M07_LCD1602 display character.zip
(18.18 MB, 下載次數(shù): 22)
2018-5-24 15:18 上傳
點擊文件名下載附件
FPGA的1602例程 下載積分: 黑幣 -5
0.png (67.3 KB, 下載次數(shù): 90)
下載附件
2018-5-25 01:57 上傳
0.png (73.32 KB, 下載次數(shù): 84)
下載附件
2018-5-25 01:57 上傳
Quartus 工程 qsf 文件管腳約束命令,把以下命令拷貝到新建 quartus 工程的 qsf 文件即可完成管腳約束(注
意信號名必須相同) :
3 實驗步驟
3.1 綜合
(1)運行綜合工具。
(2)打開項目工程,項目工程存放于以軟件開發(fā)工具命名的文件夾中。
(3)編譯運行或直接點擊下載,下載 FPGA 軟件到目標板。
(4)查看軟件運行效果
3.2 仿真
請參考視頻講解。
主要命令:
切換仿真路徑 cd {仿真庫路徑} ,如:cd {F:\Verilog_demo\M06_Digital clock\clock\sim};
run 100us:仿真運行時間長度 100us ;
do wave.do:運行波形文件;
vlog ../src/*.v:編譯 scr路徑下的所有 v文件
vsim:開始仿真命令
quit –sim:退出仿真
4 實驗結果
4.1 結果演示
4.1.1 MODELSIM 仿真演示
0.png (64.53 KB, 下載次數(shù): 95)
下載附件
2018-5-25 01:58 上傳
圖表 2 modelsim 仿真波形
仿真時可以通過按比例修改數(shù)據(jù)通信時間長度,模擬真實通信協(xié)議,來縮短仿真時間。
4.1.2 MATLAB 數(shù)據(jù)分析
略。
4.1.3 開發(fā)板演示
通過以上的講解,相信各位已經(jīng)可以熟練驅動 LCD1602 了吧,在今后的使用中,可以試著將一些采集的數(shù)據(jù)
用1602 顯示出來顯示,比如傳感器溫度啊,時間啊,AD采集的電壓值啊…等等。
4.2 特別說明
源程序如下:
- //==========================================================================
- //Filename :lcd1602_ctl.v
- //modulename:lcd1602_inf
- //Author :a fei
- //Function :驅動1602,包括初始化和數(shù)據(jù)的寫,寫入數(shù)據(jù)由用戶定義
- //==========================================================================
- `timescale 1ns/1ps
- module lcd1602_ctl
- (
- //sys_signal
- input i_50m_clk ,
- input i_rst_n ,
- input [7:0] i_disp_data ,//寫入的數(shù)據(jù)
- input i_data_trig ,//數(shù)據(jù)觸發(fā)
-
- input i_addr_trig1 ,//第一行地址觸發(fā)信號
- input i_addr_trig2 ,//第二行地址觸發(fā)信號
- input [7:0] i_addr , //地址
-
- output reg o_lcd_rs ,//1602端口
- output reg o_lcd_rw ,
- output reg o_lcd_en ,
- output reg [7:0] o_lcd_data
- );
-
-
- //=============================================================================
- //控制狀態(tài)機狀態(tài)
- //=============================================================================
- parameter Idle = 10'b0000000001 ;//
- parameter Set_mode = 10'b0000000010 ;//模式設置
- parameter Disp_on_off = 10'b0000000100 ;//顯示開和關
- parameter Cursor = 10'b0000001000 ;//光標設置
- parameter Clear = 10'b0000010000 ;//數(shù)據(jù)地址清零
- parameter Stand_by = 10'b0000100000 ;//準備就緒,初始化完成
- parameter Wr_address1 = 10'b0001000000 ;//寫第一行首地址
- parameter Wr_data1 = 10'b0010000000 ;//寫第一行數(shù)據(jù)
- parameter Wr_address2 = 10'b0100000000 ;//寫第二行首地址
- parameter Wr_data2 = 10'b1000000000 ;//寫第二行數(shù)據(jù)
-
- reg [9:0] crt_state , next_state ;
- //=================================================================
- reg [15:0] cnt_4000 ;//TC,en脈沖寬度 4000*20ns=80us
- reg data_trig ;
- reg addr_tirg1 ;
- reg addr_tirg2 ;
- always@( posedge i_50m_clk or negedge i_rst_n )//
- if( !i_rst_n )
- cnt_4000 <= 16'b0 ;
- else if(crt_state!=next_state)
- cnt_4000 <= 16'b0 ;
- else if(!data_trig &&i_data_trig)
- cnt_4000 <= 16'b0 ;
- else if( cnt_4000 == 16'd4000)
- cnt_4000 <= cnt_4000 ;
- else
- cnt_4000 <= cnt_4000 +1'b1 ;
-
- reg [18:0] time_cnt1 ;//5ms計時器,每個指令間隔
- always@( posedge i_50m_clk or negedge i_rst_n )//
- if( !i_rst_n )
- time_cnt1 <= 18'b0 ;
- else if(crt_state!=next_state)
- time_cnt1 <= 18'b0 ;
- else if( time_cnt1 == 18'h3ffff)
- time_cnt1 <= time_cnt1 ;
- else
- time_cnt1 <= time_cnt1 +1'b1 ;
-
- //==================================================================
- //檢測數(shù)據(jù)、地址觸發(fā)信號
- reg[7:0] disp_data ;
- reg[7:0] address ;
- reg[3:0] data_cnt ;
- reg[15:0] time_cnt2 ;
- always@( posedge i_50m_clk or negedge i_rst_n )//
- if( !i_rst_n )
- data_trig <= 1'b0 ;
- else
- data_trig <= i_data_trig ;
-
- always@( posedge i_50m_clk)
- disp_data <= i_disp_data ;
- always@( posedge i_50m_clk)
- addr_tirg1 <= i_addr_trig1 ;
- always@( posedge i_50m_clk)
- addr_tirg2 <= i_addr_trig2 ;
-
-
- always@( posedge i_50m_clk)
- address <= i_addr ;
-
- always@( posedge i_50m_clk) //數(shù)據(jù)持續(xù)最小時間控制
- if(crt_state==Wr_data1||crt_state==Wr_data2)
- if(! data_trig &&i_data_trig)
- time_cnt2 <= 16'b0 ;
- else if(time_cnt2==16'hffff)
- time_cnt2 <= time_cnt2 ;
- else
- time_cnt2 <=time_cnt2+1'b1 ;
- else
- time_cnt2 <= 16'b0 ;
- always@( posedge i_50m_clk) //數(shù)據(jù)個數(shù)計數(shù)器
- if(crt_state==Wr_data1||crt_state==Wr_data2)
- if(! data_trig &&i_data_trig)
- data_cnt <= data_cnt +1'b1 ;
- else
- data_cnt <= data_cnt ;
- else
- data_cnt <=4'b0 ;
-
-
- //==================================================================
- //狀態(tài)轉移
- //==================================================================
- reg [19:0] power_up_cnt ;//上電等待時間42ms
-
- always@( posedge i_50m_clk or negedge i_rst_n )//
- if( !i_rst_n )
- power_up_cnt <= 20'b0 ;
- else if(power_up_cnt==20'hfffff)//power_up_cnt==22'hff
- power_up_cnt<= power_up_cnt ;
- else
- power_up_cnt <= power_up_cnt + 1'b1 ;
- //====================================================================
- //????
- //====================================================================
- always@( posedge i_50m_clk or negedge i_rst_n )//
- if( !i_rst_n )
- crt_state <= Idle ;
- else
- crt_state <= next_state ;
- always@( *)
- case(crt_state)
- Idle : if(power_up_cnt==20'hfffff) //時間42ms到
- next_state = Set_mode ;
- else
- next_state = crt_state ;
-
- Set_mode: if(time_cnt1 == 18'h3ffff) //模式設置
- next_state = Clear ;
- else
- next_state = crt_state ;
-
- Clear : if(time_cnt1 == 18'h3ffff)//清零
- next_state = Disp_on_off ;
- else
- next_state = crt_state ;
-
-
- Disp_on_off: if(time_cnt1 == 18'h3ffff)//顯示開、關
- next_state = Cursor ;
- else
- next_state = crt_state ;
-
- Cursor : if(time_cnt1 == 18'h3ffff)//光標設置
- next_state = Stand_by ;
- else
- next_state = crt_state ;
-
-
- Stand_by :if(!addr_tirg1&&i_addr_trig1)//準備就緒
- next_state = Wr_address1 ;
- else if(!addr_tirg2&&i_addr_trig2)
- next_state = Wr_address2 ;
- else
- next_state = crt_state ;
- Wr_address1 : if( !data_trig &&i_data_trig)//寫第一行數(shù)據(jù)
- next_state = Wr_data1 ;
- else
- next_state = crt_state ;
- Wr_data1 : if(data_cnt==4'd6&&time_cnt2 == 16'hffff) //寫第一行數(shù)據(jù),返回準備狀態(tài)
- next_state = Stand_by ;
- else
- next_state = crt_state ;
-
- Wr_address2 : if( !data_trig &&i_data_trig)//第二行數(shù)據(jù)
- next_state = Wr_data2 ;
- else
- next_state = crt_state ;
-
- Wr_data2 : if(data_cnt==4'd4&&time_cnt2==16'hffff) //第二行數(shù)據(jù)
- next_state = Stand_by ;
- else
- next_state = crt_state ;
-
- default :next_state = Idle ;
- endcase
-
-
- //==================================================================端口輸出
-
- ///////lcd_rs,1寫數(shù)據(jù) ,0寫命令
- always@( posedge i_50m_clk or negedge i_rst_n )//
- if( !i_rst_n )
- o_lcd_rs <= 1'b0 ;
- else if((crt_state ==Wr_data2||crt_state ==Wr_data1)&&cnt_4000<16'd4000)
- o_lcd_rs <= 1'b1 ;
- else
- o_lcd_rs <= 1'b0 ;
-
- //==lcd_rw ,總是寫
- always@( posedge i_50m_clk)
- o_lcd_rw <= 1'b0 ;
-
- //====lcd_en
- always@( posedge i_50m_clk or negedge i_rst_n )//
- if( !i_rst_n )
- o_lcd_en <= 1'b0 ;
- else if(crt_state==Stand_by)
- o_lcd_en <= 1'b0 ;
- else if(cnt_4000>5'd10&&cnt_4000<16'd3990)
- o_lcd_en <= 1'b1 ;
- else
- o_lcd_en <= 1'b0 ;
-
-
- //lcd_data ,?????
- always@( *)
- case(crt_state)
- Idle : o_lcd_data = 8'h38 ;
- Set_mode : o_lcd_data = 8'h38 ;//模式設置
- Disp_on_off : o_lcd_data = 8'h0e ;//顯示開、關
- Cursor : o_lcd_data = 8'h06 ;//光標設置
- Clear : o_lcd_data = 8'h01 ;//清零
- Wr_address1,Wr_address2 : o_lcd_data = address [7:0] ; //地址
- Wr_data1 ,Wr_data2 : o_lcd_data = disp_data[7:0] ;//數(shù)據(jù)
- default : o_lcd_data = 8'hff ;
-
- endcase
-
- endmodule
復制代碼
|