生活随笔
收集整理的這篇文章主要介紹了
数字温度传感器
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
文章目錄
- 1. DS18B20簡介
- 1.1 命令
- 1.2 數(shù)據(jù)格式
- 1.3 數(shù)據(jù)時(shí)序
- 2. 程序設(shè)計(jì)
1. DS18B20簡介
DS18B20是常用的數(shù)字溫度傳感器,其輸出數(shù)字信號(hào)來表示溫度,具有體積小,硬件開發(fā)開銷低,抗干擾能力強(qiáng),精度高的特點(diǎn)。
由于封裝形式多樣,適用于各種狹小空間設(shè)備數(shù)字測(cè)溫和控制領(lǐng)域,也可應(yīng)用于鍋爐測(cè)溫,機(jī)房測(cè)溫,農(nóng)業(yè)大棚測(cè)溫,潔凈室測(cè)溫,彈藥庫測(cè)溫等各種場合。
DS18B20測(cè)量溫度范圍為-55~+125℃,精度為+/-0.5℃,最大轉(zhuǎn)換時(shí)間為750ms。
1.1 命令
DS18B20的命令分為兩類,分別是ROM功能命令和RAM功能命令。
ROM功能命令是對(duì)64位ROM進(jìn)行操作:
33H:讀ROM
55H:匹配ROM
CCH:跳過ROM
F0H:搜索ROM
ECH:報(bào)警搜索命令
如果主機(jī)只對(duì)一個(gè)DS18B20進(jìn)行操作,就不需要讀取ROM編碼以及匹配ROM編碼,只要用跳過ROM(CCH),就可以進(jìn)行下一步對(duì)高速緩存器的操作。
主機(jī)發(fā)出對(duì)ROM的操作命令之后,就進(jìn)一步發(fā)出對(duì)RAM的命令。
如果使用寄生電源,總控制器必須在發(fā)出溫度轉(zhuǎn)換后立即啟動(dòng)強(qiáng)上拉,并保持500ms
1.2 數(shù)據(jù)格式
DS18B20在出廠時(shí)默認(rèn)配置溫度數(shù)據(jù)位為12位(補(bǔ)碼),其中最高位為符號(hào)位。即溫度值共11位,最低四位為小數(shù)位;低11位的二進(jìn)制數(shù)轉(zhuǎn)化為十進(jìn)制數(shù)后再乘以0.0625得到所測(cè)的實(shí)際溫度值。BYTE1前5位同時(shí)變化,前5位均為1時(shí),讀取的溫度為負(fù)值。
1.3 數(shù)據(jù)時(shí)序
主機(jī)和從機(jī)(DS18B20)間的任何通訊都需要以初始化序列開始:
每次讀寫操作至少需要60us,在兩次寫操作之間至少需要1us的恢復(fù)時(shí)間;
寫操作起始于主機(jī)拉低數(shù)據(jù)總線:
寫0:在主機(jī)拉低數(shù)據(jù)線后,保持低電平即可(至少60us);
寫1:主機(jī)拉低總線(至少1us)后,接著必須在15us之內(nèi)釋放總線
在寫操作開始后15us~60us期間,單總線期間采樣總電平狀態(tài)。
如果在此期間采樣值為高電平,則邏輯1寫入期間;如果為0,寫入邏輯0。
每次讀操作至少要60us,在兩次讀操作期間至少需要1us的恢復(fù)時(shí)間;
讀操作由主機(jī)發(fā)起,至少拉低總線1us。
在主機(jī)發(fā)起讀操作之后,單總線器件才開始在總線上發(fā)送0或1.
若主機(jī)發(fā)送1,則保持總線為高電平;若發(fā)出0,則拉低總線。
從機(jī)發(fā)出的數(shù)據(jù)在其實(shí)時(shí)隙之后,保持有效時(shí)間15us,因此主機(jī)在讀時(shí)隙器件必須釋放總線,并且在時(shí)隙起始后的15us之內(nèi)采樣總線狀態(tài)。
DS18B20的典型溫度讀取過程:
初始化->發(fā)跳過ROM命令(CCH)->發(fā)溫度轉(zhuǎn)換命令(44H)->延時(shí)->初始化->發(fā)跳過ROM命令(CCH)->發(fā)讀存儲(chǔ)器命令(BEH)->連續(xù)讀出兩個(gè)字節(jié)溫度數(shù)據(jù)->結(jié)束或開始下一循環(huán)。
2. 程序設(shè)計(jì)
使用FOGA開發(fā)板通過DS18B20采集溫度,并將采集的溫度值(帶符號(hào)位)用數(shù)碼管顯示。
系統(tǒng)框圖
代碼
module
temp_disp(input sys_clk
, input sys_rst_n
, inout dq
, output
[5:0] sel
, output
[7:0] seg_led
);
parameter POINT
= 6'b000100
;
wire
[19:0] temp_data
;
wire sign
;
seg_led
u_seg_led(.clk
(sys_clk
), .rst_n
(sys_rst_n
), .seg_sel
(sel
), .seg_led
(seg_led
), .data
(temp_data
), .point
(POINT
), .en
(1'b1
), .sign
(sign
)
);
ds18b20_dri
u1_ds18b20_dri(.clk
(sys_clk
), .rst_n
(sys_rst_n
), .dq
(dq
), .temp_data
(temp_data
), .sign
(sign
)
);endmodule
module
ds18b20_dri(input clk
, input rst_n
, inout dq
, output reg
[19:0] temp_data
, output reg sign
);
localparam ROM_SKIP_CMD
= 8'hcc
;
localparam CONVERT_CMD
= 8'h44
;
localparam READ_TEMP
= 8'hbe
;
localparam init
= 3'd1
;
localparam rom_skip
= 3'd2
;
localparam wr_byte
= 3'd3
;
localparam temp_convert
= 3'd4
;
localparam delay
= 3'd5
;
localparam rd_temp
= 3'd6
;
localparam rd_byte
= 3'd7
;
reg
[ 4:0] cnt
;
reg clk_1us
;
reg
[19:0] cnt_1us
;
reg
[ 2:0] cur_state
;
reg
[ 2:0] next_state
;
reg
[ 3:0] flow_cnt
;
reg
[ 3:0] wr_cnt
;
reg
[ 4:0] rd_cnt
;
reg
[ 7:0] wr_data
;
reg
[ 4:0] bit_width
;
reg
[15:0] rd_data
;
reg
[15:0] org_data
;
reg
[10:0] data1
;
reg
[ 3:0] cmd_cnt
;
reg init_done
;
reg st_done
;
reg cnt_1us_en
;
reg dq_out
;
wire
[19:0] data2
;
assign dq
= dq_out
;
always @
(posedge clk or negedge rst_n
) begin
if (!rst_n
) begincnt
<= 5'b0
;clk_1us
<= 1'b0
;end
else if(cnt
< 5'd24
) begincnt
<= cnt
+ 1'b1
;clk_1us
<= clk_1us
;end
else begincnt
<= 5'b0
;clk_1us
<= ~clk_1us
;end
end
always @
(posedge clk_1us or negedge rst_n
) begin
if (!rst_n
)cnt_1us
<= 20'b0
;else if (cnt_1us_en
)cnt_1us
<= cnt_1us
+ 1'b1
;elsecnt_1us
<= 20'b0
;
end
always @
(posedge clk_1us or negedge rst_n
) begin
if(!rst_n
)cur_state
<= init
;else cur_state
<= next_state
;
end
always @
( * ) begin
case(cur_state
)init
: begin
if (init_done
)next_state
= rom_skip
;elsenext_state
= init
;endrom_skip
: begin
if(st_done
)next_state
= wr_byte
;elsenext_state
= rom_skip
;endwr_byte
: begin
if(st_done
)case(cmd_cnt
) 4'b1
: next_state
= temp_convert
;4'd2
: next_state
= delay
;4'd3
: next_state
= rd_temp
;4'd4
: next_state
= rd_byte
;default: next_state
= temp_convert
;endcase
elsenext_state
= wr_byte
;endtemp_convert
: begin
if(st_done
)next_state
= wr_byte
;elsenext_state
= temp_convert
;enddelay
: begin
if(st_done
)next_state
= init
;elsenext_state
= delay
;endrd_temp
: begin
if(st_done
)next_state
= wr_byte
;elsenext_state
= rd_temp
;endrd_byte
: begin
if(st_done
)next_state
= init
;elsenext_state
= rd_byte
;end
default: next_state
= init
;endcase
end
always @
(posedge clk_1us or negedge rst_n
) begin
if(!rst_n
) beginflow_cnt
<= 4'b0
;init_done
<= 1'b0
;cnt_1us_en
<= 1'b1
;dq_out
<= 1'bZ
;st_done
<= 1'b0
;rd_data
<= 16'b0
;rd_cnt
<= 5'd0
;wr_cnt
<= 4'd0
;cmd_cnt
<= 3'd0
;end
else beginst_done
<= 1'b0
;case (next_state
)init
:begin init_done
<= 1'b0
;case(flow_cnt
)4'd0
:flow_cnt
<= flow_cnt
+ 1'b1
;4'd1
: begin cnt_1us_en
<= 1'b1
; if(cnt_1us
< 20'd500
)dq_out
<= 1'b0
; else begincnt_1us_en
<= 1'b0
;dq_out
<= 1'bz
;flow_cnt
<= flow_cnt
+ 1'b1
;endend
4'd2
:begin cnt_1us_en
<= 1'b1
;if(cnt_1us
< 20'd30
)dq_out
<= 1'bz
;elseflow_cnt
<= flow_cnt
+ 1'b1
;end
4'd3
: begin
if(!dq
)flow_cnt
<= flow_cnt
+ 1'b1
;elseflow_cnt
<= flow_cnt
;end
4'd4
: begin
if(cnt_1us
== 20'd500
) begincnt_1us_en
<= 1'b0
;init_done
<= 1'b1
; flow_cnt
<= 4'd0
;end
elseflow_cnt
<= flow_cnt
;end
default: flow_cnt
<= 4'd0
;endcaseendrom_skip
: begin wr_data
<= ROM_SKIP_CMD
;flow_cnt
<= 4'd0
;st_done
<= 1'b1
;endwr_byte
: begin
if(wr_cnt
<= 4'd7
) begin
case (flow_cnt
)4'd0
: begindq_out
<= 1'b0
; cnt_1us_en
<= 1'b1
; flow_cnt
<= flow_cnt
+ 1'b1
;end
4'd1
: begin flow_cnt
<= flow_cnt
+ 1'b1
;end
4'd2
: begin
if(cnt_1us
< 20'd60
) dq_out
<= wr_data
[wr_cnt
];else if(cnt_1us
< 20'd63
) dq_out
<= 1'bz
; elseflow_cnt
<= flow_cnt
+ 1'b1
;end
4'd3
: begin flow_cnt
<= 0;cnt_1us_en
<= 1'b0
;wr_cnt
<= wr_cnt
+ 1'b1
;end
default : flow_cnt
<= 0;endcaseend
else begin st_done
<= 1'b1
;wr_cnt
<= 4'b0
;cmd_cnt
<= (cmd_cnt
== 3'd4
) ? 3'd1 : (cmd_cnt+ 1'b1
);endendtemp_convert
: begin wr_data
<= CONVERT_CMD
;st_done
<= 1'b1
;enddelay
: begin cnt_1us_en
<= 1'b1
;if(cnt_1us
== 20'd500000
) beginst_done
<= 1'b1
;cnt_1us_en
<= 1'b0
;end end rd_temp
: begin wr_data
<= READ_TEMP
;bit_width
<= 5'd16
; st_done
<= 1'b1
;endrd_byte
: begin
if(rd_cnt
< bit_width
) begin
case(flow_cnt
)4'd0
: begincnt_1us_en
<= 1'b1
;dq_out
<= 1'b0
; flow_cnt
<= flow_cnt
+ 1'b1
;end
4'd1
: begindq_out
<= 1'bz
; if(cnt_1us
== 20'd14
) beginrd_data
<= {dq
,rd_data
[15:1]};flow_cnt
<= flow_cnt
+ 1'b1
;endend
4'd2
: begin
if (cnt_1us
<= 20'd64
) dq_out
<= 1'bz
;else beginflow_cnt
<= 4'd0
; rd_cnt
<= rd_cnt
+ 1'b1
;cnt_1us_en
<= 1'b0
;endend
default : flow_cnt
<= 4'd0
;endcaseend
else beginst_done
<= 1'b1
;org_data
<= rd_data
;rd_cnt
<= 5'b0
;endend
default: ;endcaseend
end
always @
(posedge clk_1us or negedge rst_n
) begin
if(!rst_n
) beginsign
<= 1'b0
;data1
<= 11'b0
;end
else if(org_data
[15] == 1'b0
) beginsign
<= 1'b0
;data1
<= org_data
[10:0];end
else if(org_data
[15] == 1'b1
) beginsign
<= 1'b1
;data1
<= ~org_data
[10:0] + 1'b1
;end
end
assign data2
= (data1
* 11'd625)/ 7'd100
;
always @
(posedge clk_1us or negedge rst_n
) begin
if(!rst_n
)temp_data
<= 20'b0
;elsetemp_data
<= data2
;
endendmodule
module
seg_led(input clk
, input rst_n
, input
[19:0] data
, input
[5:0] point
, input en
, input sign
, output reg
[5:0] seg_sel
, output reg
[7:0] seg_led
);
localparam CLK_DIVIDE
= 4'd10
;
localparam MAX_NUM
= 13'd5000
;
reg
[ 3:0] clk_cnt
;
reg dri_clk
;
reg
[23:0] num
;
reg
[12:0] cnt0
;
reg flag
;
reg
[2:0] cnt_sel
;
reg
[3:0] num_disp
;
reg dot_disp
;
wire
[3:0] data0
;
wire
[3:0] data1
;
wire
[3:0] data2
;
wire
[3:0] data3
;
wire
[3:0] data4
;
wire
[3:0] data5
;
assign data0
= data
% 4'd10
;
assign data1
= data
/ 4'd10 % 4'd10
;
assign data2
= data
/ 7'd100 % 4'd10
;
assign data3
= data
/ 10'd1000 % 4'd10
;
assign data4
= data
/ 14'd10000 % 4'd10
;
assign data5
= data
/ 17'd100000
;
always @
(posedge clk or negedge rst_n
) begin
if(!rst_n
) beginclk_cnt
<= 4'd0
;dri_clk
<= 1'b1
;end
else if(clk_cnt
== CLK_DIVIDE
/2 - 1'd1
) beginclk_cnt
<= 4'd0
;dri_clk
<= ~dri_clk
;end
else beginclk_cnt
<= clk_cnt
+ 1'b1
;dri_clk
<= dri_clk
;end
end
always @
(posedge dri_clk or negedge rst_n
) begin
if (!rst_n
)num
<= 24'b0
;else begin
if (data5
|| point
[5]) begin num
[23:20] <= data5
; num
[19:16] <= data4
;num
[15:12] <= data3
;num
[11:8] <= data2
;num
[ 7:4] <= data1
;num
[ 3:0] <= data0
;end
else begin
if (data4
|| point
[4]) begin num
[19:0] <= {data4
,data3
,data2
,data1
,data0
};if(sign
) num
[23:20] <= 4'd11
; elsenum
[23:20] <= 4'd10
; end
else begin
if (data3
|| point
[3]) beginnum
[15: 0] <= {data3
,data2
,data1
,data0
};num
[23:20] <= 4'd10
; if(sign
) num
[19:16] <= 4'd11
;else num
[19:16] <= 4'd10
;end
else begin
if (data2
|| point
[2]) beginnum
[11: 0] <= {data2
,data1
,data0
};num
[23:16] <= {2{4'd10
}};if(sign
) num
[15:12] <= 4'd11
;else num
[15:12] <= 4'd10
;end
else begin
if (data1
|| point
[1]) beginnum
[ 7: 0] <= {data1
,data0
};num
[23:12] <= {3{4'd10
}};if(sign
) num
[11:8] <= 4'd11
;else num
[11:8] <= 4'd10
;end
else begin num
[3:0] <= data0
;num
[23:8] <= {4{4'd10
}};if(sign
) num
[7:4] <= 4'd11
;else num
[7:4] <= 4'd10
;endendendendendend
end
always @
(posedge dri_clk or negedge rst_n
) begin
if (rst_n
== 1'b0
) begincnt0
<= 13'b0
;flag
<= 1'b0
;end
else if (cnt0
< MAX_NUM
- 1'b1
) begincnt0
<= cnt0
+ 1'b1
;flag
<= 1'b0
;end
else begincnt0
<= 13'b0
;flag
<= 1'b1
;end
end
always @
(posedge dri_clk or negedge rst_n
) begin
if (rst_n
== 1'b0
)cnt_sel
<= 3'b0
;else if(flag
) begin
if(cnt_sel
< 3'd5
)cnt_sel
<= cnt_sel
+ 1'b1
;elsecnt_sel
<= 3'b0
;end
elsecnt_sel
<= cnt_sel
;
end
always @
(posedge dri_clk or negedge rst_n
) begin
if(!rst_n
) beginseg_sel
<= 6'b111111
; num_disp
<= 4'b0
; dot_disp
<= 1'b1
; end
else begin
if(en
) begin
case (cnt_sel
)3'd0
:beginseg_sel
<= 6'b111110
; num_disp
<= num
[3:0] ; dot_disp
<= ~point
[0]; end
3'd1
:beginseg_sel
<= 6'b111101
; num_disp
<= num
[7:4] ;dot_disp
<= ~point
[1];end
3'd2
:beginseg_sel
<= 6'b111011
; num_disp
<= num
[11:8];dot_disp
<= ~point
[2];end
3'd3
:beginseg_sel
<= 6'b110111
; num_disp
<= num
[15:12];dot_disp
<= ~point
[3];end
3'd4
:beginseg_sel
<= 6'b101111
; num_disp
<= num
[19:16];dot_disp
<= ~point
[4];end
3'd5
:beginseg_sel
<= 6'b011111
; num_disp
<= num
[23:20];dot_disp
<= ~point
[5];end
default :beginseg_sel
<= 6'b111111
;num_disp
<= 4'b0
;dot_disp
<= 1'b1
;endendcaseend
else beginseg_sel
<= 6'b111111
; num_disp
<= 4'b0
;dot_disp
<= 1'b1
;endend
end
always @
(posedge dri_clk or negedge rst_n
) begin
if (!rst_n
)seg_led
<= 8'hc0
;else begin
case (num_disp
)4'd0 : seg_led <= {dot_disp,7'b1000000
}; 4'd1 : seg_led <= {dot_disp,7'b1111001
}; 4'd2 : seg_led <= {dot_disp,7'b0100100
}; 4'd3 : seg_led <= {dot_disp,7'b0110000
}; 4'd4 : seg_led <= {dot_disp,7'b0011001
}; 4'd5 : seg_led <= {dot_disp,7'b0010010
}; 4'd6 : seg_led <= {dot_disp,7'b0000010
}; 4'd7 : seg_led <= {dot_disp,7'b1111000
}; 4'd8 : seg_led <= {dot_disp,7'b0000000
}; 4'd9 : seg_led <= {dot_disp,7'b0010000
}; 4'd10: seg_led <= 8'b11111111
; 4'd11: seg_led <= 8'b10111111
; default: seg_led
<= {dot_disp
,7'b1000000
};endcaseend
endendmodule
總結(jié)
以上是生活随笔為你收集整理的数字温度传感器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。