DS18B20
0. 注意
典型的 DS18B20 电路的 inout 端口需要一个 4.7k 上拉电阻
1. DS18B20简介
1.1 DS18B20特性
1.2 DS18B20引脚
1.3 DS18B20内部结构图
1.4 DS18B20的高速缓存器
1.4 DS18B20的温度寄存器
共16位,5位S表示符号位
红色的9-12表示精度为9-12时的有效位;精度为9时,后三位无效,默认精度为12位,即16位全部有效
举例:
+125℃ 0000_0111_1101_0000 12位精度
0000_0为符号位,0表示正数
111_1101_0000B = 2000
2000*0.0625 = 125
1.5 DS18B20的时序
1.5.1 初始化时序
1.5.2 写时序
1.5.3 读时序
2. 系统框图
3. 状态转移图
4. 时序图
4.1 生成clk_us信号
4.2 INIT - WR_CMD的时序
4.3 WAIT - INIT_AGAIN - RD_CMD的时序
4.4 RD_TEMP - INIT的时序
5. 设计文件
5.1 ds18b20.v
`timescale 1ns/1ns
module ds18b20
(
input wire sys_clk ,
input wire sys_rst_n ,
inout wire dq ,
output wire [7:0] sel , //数码管位选信号
output wire [7:0] seg //数码管段选信号
);
wire [19:0] data_out;
ds18b20_ctrl ds18b20_ctrl_inst
(
.sys_clk (sys_clk ),
.sys_rst_n (sys_rst_n),
.dq (dq ),
.data_out (data_out )
);
seg_dynamic
#(
.CNT_MAX(17'd99_999)
)
seg_dynamic_inst
(
.sys_clk (sys_clk ),
.sys_rst_n (sys_rst_n),
.data (data_out ),
.sel (sel ),
.seg (seg )
);
endmodule
5.2 ds18b20_ctrl.v
`timescale 1ns/1ns
module ds18b20_ctrl
(
input wire sys_clk ,
input wire sys_rst_n ,
inout wire dq ,
output wire [19:0] data_out ,
);
parameter INIT = 6'b000_001,
WR_CMD = 6'b000_010,
WAIT = 6'b000_100,
INIT_AGAIN = 6'b001_000,
RD_CMD = 6'b010_000,
RD_TEMP = 6'b100_000;
parameter WAIT_MAX = 20'd750_000;
parameter WR_CC_44 = 16'h44_cc,
WR_CC_BE = 16'hbe_cc;
reg clk_us ;
reg [5:0] cnt ;
reg [5:0] state ;
reg [19:0] cnt_us ;
reg flag ;
reg [3:0] bit_cnt ;
reg [15:0] data_temp ;
reg [19:0] data ;
reg dq_en ;
reg dq_out ;
assign dq = (dq_en == 1'b1) ? dq_out : 1'bz;
assign data_out = (data * 625) / 10;
//cnt,计数50次,实现1us
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt <= 6'd0;
else if(cnt == 6'd49)
cnt <= 6'd0;
else
cnt <= cnt + 1'b1;
//clk_us,1us的时钟
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
clk_us <= 1'b0;
else if(cnt == 6'd49)
clk_us <= ~clk_us;
else
clk_us <= clk_us;
//cnt_us,1us 时钟计数器,用于状态跳转
always@(posedge clk_us or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_us <= 20'd0;
else if(((state == INIT || state == INIT_AGAIN) && (cnt_us == 20'd999))
|| ((state == WR_CMD || state == RD_CMD || state == RD_TEMP) && (cnt_us == 20'd64))
|| ((state == WAIT && cnt_us == WAIT_MAX)))
cnt_us <= 20'd0;
else
cnt_us <= cnt_us + 1'b1;
//bit_cnt,bit 计数器,写 1bit 或读 1bit 加 1,一次写完之后清零
always@(posedge clk_us or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
bit_cnt <= 4'd0;
else if((state == WR_CMD || state == RD_CMD || state == RD_TEMP)
&& (bit_cnt == 4'd15) && (cnt_us == 20'd64))
bit_cnt <= 4'd0;
else if((state == WR_CMD || state == RD_CMD || state == RD_TEMP)
&& (cnt_us == 20'd64))
bit_cnt <= bit_cnt + 1'b1;
//flag
always@(posedge clk_us