STEP FPGA驅(qū)動溫度傳感器DS18B20Z

 行業(yè)動態(tài)     |      2023-11-29 09:00:17    |      作者

硬件說明

DS18B20是我們?nèi)粘TO(shè)計中常用的一款溫度傳感器芯片,只需要一根總線就可以實現(xiàn)通信,非常的方便,我們的STEP-BaseBoard底板上就集成了溫度傳感器DS18B20Z,下面我們就一起來學(xué)習(xí)一下它的硬件鏈接及驅(qū)動方法。

DS18B20Z只有一根總線,硬件電路非常簡單,但是一定記得總線需要做上拉處理,如下圖總線上連接了10K(上拉電阻取值可以一定范圍內(nèi)自行調(diào)整)的上拉電阻,另外我們使用FPGA驅(qū)動,一定記得將FPGA對應(yīng)的管腳同樣作上拉配置,重要的事情說三遍,總線上拉,總線上拉,總線上拉。

聊完硬件連接,接下來簡要介紹如何驅(qū)動(更加詳細(xì)的信息需要大家參考數(shù)據(jù)手冊),不同的功能需求對應(yīng)不同寄存器配置,本設(shè)計執(zhí)行的操作案例如下。

下面為大家展示上述案例中每個環(huán)節(jié)的時序要求:


Verilog代碼

//-------------------------------------------------------------------- //>>>>>>>>>>>>>>>>>>>>>>>>>COPYRIGHTNOTICE<<<<<<<<<<<<<<<<<<<<<<<<< //-------------------------------------------------------------------- //Module:DS18B20Z // //Author:Step // //Description:DriveDS18B20Ztogettemperaturecode // //-------------------------------------------------------------------- //CodeRevisionHistory: //-------------------------------------------------------------------- //Version:|Mod.Date:|ChangesMade: //V1.0|2015/11/11|Initialver //-------------------------------------------------------------------- moduleDS18B20Z( input clk_in, //系統(tǒng)時鐘 input rst_n_in, //系統(tǒng)復(fù)位,低有效 inout one_wire, //DS18B20Z傳感器單總線,雙向管腳 output reg [15:0] data_out //DS18B20Z有效溫度數(shù)據(jù)輸出) ; /* 本設(shè)計通過驅(qū)動DS18B20Z芯片獲取溫度數(shù)據(jù), 需要了解inout類型的接口如何實現(xiàn)雙向通信, 中間涉及各種不同的延時和寄存器指令操作,注釋部分以作簡要說明,更多詳情需參考數(shù)據(jù)手冊 */ localparam IDLE = 3'd0; localparam MAIN = 3'd1; localparam INIT = 3'd2; localparam WRITE = 3'd3; localparam READ = 3'd4; localparam DELAY = 3'd5; //計數(shù)器分頻產(chǎn)生1MHz的時鐘信號 reg clk_1mhz; reg [2:0] cnt_1mhz; always@(posedgeclk_inornegedgerst_n_in)begin if(!rst_n_in)begin cnt_1mhz<=3'd0; clk_1mhz<=1'b0; endelseif(cnt_1mhz>=3'd5)begin cnt_1mhz<=3'd0; clk_1mhz<=~clk_1mhz; //產(chǎn)生1MHz分頻 endelsebegin cnt_1mhz<=cnt_1mhz+1'b1; end end reg [2:0] cnt; reg one_wire_buffer; reg [3:0] cnt_main; reg [7:0] data_wr; reg [7:0] data_wr_buffer; reg [2:0] cnt_init; reg [19:0] cnt_delay; reg [19:0] num_delay; reg [3:0] cnt_write; reg [2:0] cnt_read; reg [15:0] temperature; reg [7:0] temperature_buffer; reg [2:0] state=IDLE; reg [2:0] state_back=IDLE; //使用1MHz時鐘信號做觸發(fā)完成下面狀態(tài)機的功能 always@(posedgeclk_1mhzornegedgerst_n_in)begin if(!rst_n_in)begin state<=IDLE; state_back<=IDLE; cnt<=1'b0; cnt_main<=1'b0; cnt_init<=1'b0; cnt_write<=1'b0; cnt_read<=1'b0; cnt_delay<=1'b0; one_wire_buffer<=1'bz; temperature<=16'h0; endelsebegin case(state) IDLE:begin //IDLE狀態(tài),程序設(shè)計的軟復(fù)位功能,各狀態(tài)異常都會跳轉(zhuǎn)到此狀態(tài) state<=MAIN; //軟復(fù)位完成,跳轉(zhuǎn)之MAIN狀態(tài)重新工作 state_back<=MAIN; cnt<=1'b0; cnt_main<=1'b0; cnt_init<=1'b0; cnt_write<=1'b0; cnt_read<=1'b0; cnt_delay<=1'b0; one_wire_buffer<=1'bz; end MAIN:begin //MAIN狀態(tài)控制狀態(tài)機在不同狀態(tài)間跳轉(zhuǎn),實現(xiàn)完整的溫度數(shù)據(jù)采集 if(cnt_main>=4'd11)cnt_main<=1'b0; elsecnt_main<=cnt_main+1'b1; case(cnt_main) 4'd0:beginstate<=INIT; end //跳轉(zhuǎn)至INIT狀態(tài)進(jìn)行芯片的復(fù)位及驗證 4'd1:begindata_wr<=8'hcc; state<=WRITE; end //主設(shè)備發(fā)出跳轉(zhuǎn)ROM指令 4'd2:begindata_wr<=8'h44; state<=WRITE; end //主設(shè)備發(fā)出溫度轉(zhuǎn)換指令 4'd3:beginnum_delay<=20'd750000; state<=DELAY; state_back<=MAIN; end //延時750ms等待轉(zhuǎn)換完成 4'd4:beginstate<=INIT; end //跳轉(zhuǎn)至INIT狀態(tài)進(jìn)行芯片的復(fù)位及驗證 4'd5:begindata_wr<=8'hcc; state<=WRITE; end //主設(shè)備發(fā)出跳轉(zhuǎn)ROM指令 4'd6:begindata_wr<=8'hbe; state<=WRITE; end //主設(shè)備發(fā)出讀取溫度指令 4'd7:beginstate<=READ; end //跳轉(zhuǎn)至READ狀態(tài)進(jìn)行單總線數(shù)據(jù)讀取 4'd8:begintemperature[7:0]<=temperature_buffer; end //先讀取的為低8位數(shù)據(jù) 4'd9:beginstate<=READ; end //跳轉(zhuǎn)至READ狀態(tài)進(jìn)行單總線數(shù)據(jù)讀取 4'd10:begintemperature[15:8]<=temperature_buffer; end //后讀取的為高8為數(shù)據(jù) 4'd11:beginstate<=IDLE; data_out<=temperature; end //將完整的溫度數(shù)據(jù)輸出并重復(fù)以上所有操作 default:state<=IDLE; endcase end INIT:begin //INIT狀態(tài)完成DS18B20Z芯片的復(fù)位及驗證功能 if(cnt_init>=3'd6)cnt_init<=1'b0; elsecnt_init<=cnt_init+1'b1; case(cnt_init) 3'd0:beginone_wire_buffer<=1'b0; end //單總線復(fù)位脈沖拉低 3'd1:beginnum_delay<=20'd500; state<=DELAY; state_back<=INIT;end //復(fù)位脈沖保持拉低500us時間 3'd2:beginone_wire_buffer<=1'bz; end //單總線復(fù)位脈沖釋放,自動上拉 3'd3:beginnum_delay<=20'd100; state<=DELAY; state_back<=INIT;end //復(fù)位脈沖保持釋放100us時間 3'd4:beginif(one_wire)state<=IDLE; elsestate<=INIT; end //根據(jù)單總線的存在檢測結(jié)果判定是否繼續(xù) 3'd5:beginnum_delay<=20'd400; state<=DELAY; state_back<=INIT; end //如果檢測正常繼續(xù)保持釋放400us時間 3'd6:beginstate<=MAIN; end //INIT狀態(tài)操作完成,返回MAIN狀態(tài) default:state<=IDLE; endcase end WRITE:begin //按照DS18B20Z芯片單總線時序進(jìn)行寫操作 if(cnt<=3'd6)begin //共需要發(fā)送8bit的數(shù)據(jù),這里控制循環(huán)的次數(shù) if(cnt_write>=4'd6)begincnt_write<=1'b1; cnt<=cnt+1'b1; end elsebegincnt_write<=cnt_write+1'b1; cnt<=cnt;end endelsebegin if(cnt_write>=4'd8)begincnt_write<=1'b0; cnt<=1'b0; end //兩個變量都恢復(fù)初值 elsebegincnt_write<=cnt_write+1'b1; cnt<=cnt; end end //對于WRITE狀態(tài)中cnt_write來講,執(zhí)行過程為:0;[1~6]*8;7;8; case(cnt_write) //lockdata_wr 4'd0:begindata_wr_buffer<=data_wr; end //將需要寫出的數(shù)據(jù)緩存 //發(fā)送1bit數(shù)據(jù)的用時在60~120us之間,參考數(shù)據(jù)手冊 4'd1:beginone_wire_buffer<=1'b0;end //總線拉低 4'd2:beginnum_delay<=20'd2; state<=DELAY; state_back<=WRITE; end //延時2us時間,保證15us以內(nèi) 4'd3:beginone_wire_buffer<=data_wr_buffer[cnt]; end //先發(fā)送數(shù)據(jù)最低位 4'd4:beginnum_delay<=20'd80; state<=DELAY; state_back<=WRITE;end //延時80us時間 4'd5:beginone_wire_buffer<=1'bz; end //總線釋放 4'd6:beginnum_delay<=20'd2; state<=DELAY; state_back<=WRITE; end //延時2us時間 //backtomain 4'd7:beginnum_delay<=20'd80; state<=DELAY; state_back<=WRITE; end //延時80us時間 4'd8:beginstate<=MAIN;end //返回MAIN狀態(tài) default:state<=IDLE; endcase end READ:begin //按照DS18B20Z芯片單總線時序進(jìn)行讀操作 if(cnt<=3'd6)begin //共需要接收8bit的數(shù)據(jù),這里控制循環(huán)的次數(shù) if(cnt_read>=3'd5)begincnt_read<=1'b0; cnt<=cnt+1'b1;end elsebegincnt_read<=cnt_read+1'b1; cnt<=cnt;end endelsebegin if(cnt_read>=3'd6)begincnt_read<=1'b0; cnt<=1'b0;end //兩個變量都恢復(fù)初值 elsebegincnt_read<=cnt_read+1'b1;cnt<=cnt; end end case(cnt_read) //讀取1bit數(shù)據(jù)的用時在60~120us之間,總線拉低后15us時間內(nèi)讀取數(shù)據(jù),參考數(shù)據(jù)手冊 3'd0:beginone_wire_buffer<=1'b0; end //總線拉低 3'd1:beginnum_delay<=20'd2; state<=DELAY; state_back<=READ; end //延時2us時間 3'd2:beginone_wire_buffer<=1'bz; end //總線釋放 3'd3:beginnum_delay<=20'd5; state<=DELAY; state_back<=READ; end //延時5us時間 3'd4:begintemperature_buffer[cnt]<=one_wire; end //讀取DS18B20Z返回的總線數(shù)據(jù),先收最低位 3'd5:beginnum_delay<=20'd60; state<=DELAY; state_back<=READ; end //延時60us時間 //backtomain 3'd6:beginstate<=MAIN; end //返回MAIN狀態(tài) default:state<=IDLE; endcase end DELAY:begin //延時控制 if(cnt_delay>=num_delay)begin //延時控制,延時時間由num_delay指定 cnt_delay<=1'b0; state<=state_back; //很多狀態(tài)都需要延時,延時后返回哪個狀態(tài)由state_back指定 endelsecnt_delay<=cnt_delay+1'b1; end endcase end end assign one_wire=one_wire_buffer; endmodule


小結(jié)

本節(jié)主要為大家講解了DS18B20Z的驅(qū)動方法及軟件實現(xiàn),需要大家掌握的同時自己創(chuàng)建工程,通過整個設(shè)計流程,生成FPGA配置文件加載測試。