• <li id="00i08"><input id="00i08"></input></li>
  • <sup id="00i08"><tbody id="00i08"></tbody></sup>
    <abbr id="00i08"></abbr>
  • 新聞中心

    EEPW首頁 > 嵌入式系統 > 設計應用 > STEP FPGA驅動溫度傳感器DS18B20Z

    STEP FPGA驅動溫度傳感器DS18B20Z

    作者: 時間:2023-11-28 來源:電子森林 收藏

    硬件說明

    DS18B20是我們日常設計中常用的一款芯片,只需要一根總線就可以實現通信,非常的方便,我們的STEP-BaseBoard底板上就集成了DS18B20Z,下面我們就一起來學習一下它的硬件鏈接及驅動方法。

    本文引用地址:http://www.czjhyjcfj.com/article/202311/453369.htm

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

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

    下面為大家展示上述案例中每個環節的時序要求:


    Verilog代碼

    // --------------------------------------------------------------------
    // >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
    // --------------------------------------------------------------------
    // Module:DS18B20Z 
    // 
    // Author: Step
    // 
    // Description: Drive DS18B20Z to get temperature code
    // 
    // --------------------------------------------------------------------
    // Code Revision History :
    // --------------------------------------------------------------------
    // Version: |Mod. Date:   |Changes Made:
    // V1.0     |2015/11/11   |Initial ver
    // --------------------------------------------------------------------
    module DS18B20Z(
    	input				clk_in,			//系統時鐘
    	input				rst_n_in,		//系統復位,低有效
    	inout				one_wire,		//DS18B20Z傳感器單總線,雙向管腳
    	output	reg	[15:0]	data_out		//DS18B20Z有效溫度數據輸出)
    	; 	
    	/*
    	本設計通過驅動DS18B20Z芯片獲取溫度數據,
    	需要了解inout類型的接口如何實現雙向通信,
    	中間涉及各種不同的延時和寄存器指令操作,注釋部分以作簡要說明,更多詳情需參考數據手冊
    	*/ 	
    	localparam	IDLE	=	3'd0;
    	localparam	MAIN	=	3'd1;
    	localparam	INIT	=	3'd2;
    	localparam	WRITE	=	3'd3;
    	localparam	READ	=	3'd4;
    	localparam	DELAY	=	3'd5; 	//計數器分頻產生1MHz的時鐘信號
    	reg					clk_1mhz;
    	reg		[2:0]		cnt_1mhz;
    	always@(posedge clk_in or negedge rst_n_in) begin
    		if(!rst_n_in) begin
    			cnt_1mhz <= 3'd0;
    			clk_1mhz <= 1'b0;
    		end else if(cnt_1mhz >= 3'd5) begin
    			cnt_1mhz <= 3'd0;
    			clk_1mhz <= ~clk_1mhz;	//產生1MHz分頻
    		end else begin
    			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時鐘信號做觸發完成下面狀態機的功能
    	always@(posedge clk_1mhz or negedge rst_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;
    		end else begin
    			case(state)
    				IDLE:begin		//IDLE狀態,程序設計的軟復位功能,各狀態異常都會跳轉到此狀態
    						state <= MAIN;	//軟復位完成,跳轉之MAIN狀態重新工作
    						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狀態控制狀態機在不同狀態間跳轉,實現完整的溫度數據采集
    						if(cnt_main >= 4'd11) cnt_main <= 1'b0;
    						else cnt_main <= cnt_main + 1'b1;
    						case(cnt_main)
    							4'd0: begin state <= INIT; 
    							end	//跳轉至INIT狀態進行芯片的復位及驗證
    							4'd1: begin data_wr <= 8'hcc;
    							state <= WRITE; 
    							end	//主設備發出跳轉ROM指令
    							4'd2: begin data_wr <= 8'h44;
    							state <= WRITE; 
    							end	//主設備發出溫度轉換指令
    							4'd3: begin num_delay <= 20'd750000;
    							state <= DELAY;
    							state_back <= MAIN; 
    							end	//延時750ms等待轉換完成
    							4'd4: begin state <= INIT; 
    							end	//跳轉至INIT狀態進行芯片的復位及驗證
    							4'd5: begin data_wr <= 8'hcc;
    							state <= WRITE; 
    							end	//主設備發出跳轉ROM指令
    							4'd6: begin data_wr <= 8'hbe;
    							state <= WRITE; 
    							end	//主設備發出讀取溫度指令
    							4'd7: begin state <= READ; 
    							end	//跳轉至READ狀態進行單總線數據讀取
    							4'd8: begin temperature[7:0] <= temperature_buffer; 
    							end	//先讀取的為低8位數據
    							4'd9: begin state <= READ; 
    							end	//跳轉至READ狀態進行單總線數據讀取
    							4'd10: begin temperature[15:8] <= temperature_buffer;
    							end	//后讀取的為高8為數據
    							4'd11: begin state <= IDLE;
    							data_out <= temperature; 
    							end	//將完整的溫度數據輸出并重復以上所有操作
    							default: state <= IDLE;
    						endcase
    					end
    				INIT:begin		//INIT狀態完成DS18B20Z芯片的復位及驗證功能
    						if(cnt_init >= 3'd6) cnt_init <= 1'b0;
    						else cnt_init <= cnt_init + 1'b1;
    						case(cnt_init)
    							3'd0: begin one_wire_buffer <= 1'b0; 
    							end	//單總線復位脈沖拉低
    							3'd1: begin num_delay <= 20'd500;
    							state <= DELAY;
    							state_back <= INIT; end	//復位脈沖保持拉低500us時間
    							3'd2: begin one_wire_buffer <= 1'bz; 
    							end	//單總線復位脈沖釋放,自動上拉
    							3'd3: begin num_delay <= 20'd100;
    							state <= DELAY;
    							state_back <= INIT; end	//復位脈沖保持釋放100us時間
    							3'd4: begin if(one_wire) state <= IDLE; 
    							else state <= INIT; 
    							end	//根據單總線的存在檢測結果判定是否繼續
    							3'd5: begin num_delay <= 20'd400;
    							state <= DELAY;
    							state_back <= INIT; 
    							end	//如果檢測正常繼續保持釋放400us時間
    							3'd6: begin state <= MAIN; 
    							end	//INIT狀態操作完成,返回MAIN狀態
    							default: state <= IDLE;
    						endcase
    					end
    				WRITE:begin		//按照DS18B20Z芯片單總線時序進行寫操作
    						if(cnt <= 3'd6) begin	//共需要發送8bit的數據,這里控制循環的次數
    							if(cnt_write >= 4'd6) begin cnt_write <= 1'b1; 
    							cnt <= cnt + 1'b1; 
    							end
    							else begin cnt_write <= cnt_write + 1'b1; 
    							cnt <= cnt; end
    						end else begin
    							if(cnt_write >= 4'd8) begin cnt_write <= 1'b0; 
    							cnt <= 1'b0; 
    							end	//兩個變量都恢復初值
    							else begin cnt_write <= cnt_write + 1'b1; 
    							cnt <= cnt; 
    							end
    						end
    						//對于WRITE狀態中cnt_write來講,執行過程為:0;[1~6]*8;7;8;
    						case(cnt_write)
    							//lock data_wr
    							4'd0: begin data_wr_buffer <= data_wr; 
    							end	//將需要寫出的數據緩存
    							//發送 1bit 數據的用時在60~120us之間,參考數據手冊
    							4'd1: begin one_wire_buffer <= 1'b0; end	//總線拉低
    							4'd2: begin num_delay <= 20'd2;
    							state <= DELAY;
    							state_back <= WRITE; 
    							end	//延時2us時間,保證15us以內
    							4'd3: begin one_wire_buffer <= data_wr_buffer[cnt]; 
    							end	//先發送數據最低位
    							4'd4: begin num_delay <= 20'd80;
    							state <= DELAY;
    							state_back <= WRITE; end	//延時80us時間
    							4'd5: begin one_wire_buffer <= 1'bz; 
    							end	//總線釋放
    							4'd6: begin num_delay <= 20'd2;
    							state <= DELAY;
    							state_back <= WRITE; 
    							end	//延時2us時間
    							//back to main
    							4'd7: begin num_delay <= 20'd80;
    							state <= DELAY;
    							state_back <= WRITE; 
    							end	//延時80us時間
    							4'd8: begin state <= MAIN; end	//返回MAIN狀態
    							default: state <= IDLE;
    						endcase
    					end
    				READ:begin		//按照DS18B20Z芯片單總線時序進行讀操作
    						if(cnt <= 3'd6) begin	//共需要接收8bit的數據,這里控制循環的次數
    							if(cnt_read >= 3'd5) begin cnt_read <= 1'b0; 
    							cnt <= cnt + 1'b1; end
    							else begin cnt_read <= cnt_read + 1'b1; 
    							cnt <= cnt; end
    						end else begin
    							if(cnt_read >= 3'd6) begin cnt_read <= 1'b0; 
    							cnt <= 1'b0; end	//兩個變量都恢復初值
    							else begin cnt_read <= cnt_read + 1'b1; cnt <= cnt; 
    							end
    						end
    						case(cnt_read)
    							//讀取 1bit 數據的用時在60~120us之間,總線拉低后15us時間內讀取數據,參考數據手冊
    							3'd0: begin one_wire_buffer <= 1'b0; 
    							end	//總線拉低
    							3'd1: begin num_delay <= 20'd2;
    							state <= DELAY;
    							state_back <= READ; 
    							end	//延時2us時間
    							3'd2: begin one_wire_buffer <= 1'bz; 
    							end	//總線釋放
    							3'd3: begin num_delay <= 20'd5;
    							state <= DELAY;
    							state_back <= READ; 
    							end	//延時5us時間
    							3'd4: begin temperature_buffer[cnt] <= one_wire; 
    							end	//讀取DS18B20Z返回的總線數據,先收最低位
    							3'd5: begin num_delay <= 20'd60;
    							state <= DELAY;
    							state_back <= READ; 
    							end	//延時60us時間
    							//back to main
    							3'd6: begin state <= MAIN; 
    							end	//返回MAIN狀態
    							default: state <= IDLE;
    						endcase
    					end
    				DELAY:begin		//延時控制
    						if(cnt_delay >= num_delay) begin	//延時控制,延時時間由num_delay指定
    							cnt_delay <= 1'b0;
    							state <= state_back; 	//很多狀態都需要延時,延時后返回哪個狀態由state_back指定
    						end else cnt_delay <= cnt_delay + 1'b1;
    					end
    			endcase
    		end
    	end 	
    	assign	one_wire = one_wire_buffer; 
    	endmodule

    小結

    本節主要為大家講解了DS18B20Z的驅動方法及軟件實現,需要大家掌握的同時自己創建工程,通過整個設計流程,生成FPGA配置文件加載測試。



    評論


    相關推薦

    技術專區

    關閉
    主站蜘蛛池模板: 云龙县| 富蕴县| 天津市| 读书| 碌曲县| 虎林市| 集贤县| 云安县| 遂溪县| 临潭县| 峡江县| 从江县| 沂南县| 兰州市| 广西| 钟祥市| 平和县| 岑巩县| 文昌市| 久治县| 泊头市| 原平市| 天镇县| 奈曼旗| 永吉县| 龙游县| 斗六市| 昌黎县| 吉木乃县| 兴海县| 常山县| 盐池县| 余姚市| 贵定县| 永宁县| 徐水县| 珠海市| 论坛| 蚌埠市| 南投县| 云南省|