DS18B20 是单总线数字温度传感器,其可直接将温度 转化成数字信号输出,具有体积小、低功耗、抗干扰能力强、精度高等优点。
同红外遥控,时间有点远。不再给出数码管显示模块代码,只是给出DS18B20代码。
状态机:
DS18B20模块:
代码:
module DS18B20 (
input wire clk_sys ,
input wire rst_n_sys ,
inout wire dq ,
output reg [19:0]data ,
output reg sign
);
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 INIT_CNT =20'D999 ,
WAIT_CNT =20'D750_000 ,
CMD_CNT =20'D64 ,
CMD_CNT_GET =20'D30 ,
TEMP_CNT_GET=20'D13 ;
parameter CNT_BIT_CMD_MAX =4'd15 ,
CNT_BIT_TEMP_MAX =4'D15 ;
parameter WR_44_CC =16'H44_CC ,
RD_BE_CC =16'HBE_CC ;
reg us_clk ;
reg [4:0]cnt_us ;
reg [5:0]state ;
reg [19:0]cnt_state ;
reg [3:0]cnt_bit ;
reg flag_init ;
reg [15:0]temp ;
reg [11:0]reg_date ;
reg dq_en ;
reg dq_out ;
assign dq= (dq_en==1'b1)?dq_out:1'bz ;
always@(posedge clk_sys or negedge rst_n_sys)
if(!rst_n_sys)
cnt_us<=5'b0 ;
else if (cnt_us==5'd24)
cnt_us<=5'b0 ;
else
cnt_us<=cnt_us+1'b1 ;
always@(posedge clk_sys or negedge rst_n_sys)
if(!rst_n_sys)
us_clk<=1'b0 ;
else if(cnt_us==5'd24)
us_clk<=~us_clk ;
else
us_clk<=us_clk ;
always@(posedge us_clk or negedge rst_n_sys)
if(!rst_n_sys)
state <= INIT ;
else
case(state)
INIT:
if (flag_init==1'b1 && cnt_state==INIT_CNT)
state<=WR_CMD ;
else
state<=state ;
WR_CMD:
if (cnt_bit==CNT_BIT_CMD_MAX && cnt_state==CMD_CNT)
state<=WAIT ;
else
state<=state ;
WAIT:
if (cnt_state==WAIT_CNT)
state<=INIT_AGAIN ;
else
state<=state ;
INIT_AGAIN:
if (flag_init==1'b1 && cnt_state==INIT_CNT)
state<=RD_CMD ;
else
state<=state ;
RD_CMD:
if (cnt_bit==CNT_BIT_CMD_MAX && cnt_state==CMD_CNT )
state<=RD_TEMP ;
else
state<=state ;
RD_TEMP:
if(cnt_bit==CNT_BIT_TEMP_MAX && cnt_state==CMD_CNT)
state<=INIT ;
else
state<=state ;
default: state<=INIT ;
endcase
always@(posedge us_clk or negedge rst_n_sys)
if(!rst_n_sys)
begin
dq_out<=1'b0 ;
dq_en <=1'b0 ;
end
else
case(state)
INIT:
if(cnt_state<=20'd500)
begin
dq_en <=1'b1 ;
dq_out<=1'b0 ;
end
else
begin
dq_en <=1'b0 ;
dq_out<=1'b0 ;
end
WR_CMD:
if(WR_44_CC[cnt_bit]==1'b0)
if(cnt_state>=20'd63)
begin
dq_en <=1'b1 ;
dq_out<=1'b0 ;
end
else
begin
dq_en <=1'b0 ;
dq_out<=1'b0 ;
end
else if(WR_44_CC[cnt_bit]==1'b1)
if(cnt_state>=20'd2)
begin
dq_en <=1'b1 ;
dq_out<=1'b0 ;
end
else
begin
dq_en <=1'b0 ;
dq_out<=1'b0 ;
end
WAIT:
begin
dq_en <=1'b1 ;
dq_out<=1'b1 ;
end
INIT_AGAIN:
if(cnt_state<=20'd500)
begin
dq_en <=1'b1 ;
dq_out<=1'b0 ;
end
else
begin
dq_en <=1'b0 ;
dq_out<=1'b0 ;
end
RD_CMD:
if(RD_BE_CC[cnt_bit]==1'b0)
if(cnt_state>=20'd63)
begin
dq_en <=1'b1 ;
dq_out<=1'b0 ;
end
else
begin
dq_en <=1'b0 ;
dq_out<=1'b0 ;
end
else if(WR_44_CC[cnt_bit]==1'b1)
if(cnt_state>=20'd2)
begin
dq_en <=1'b1 ;
dq_out<=1'b0 ;
end
else
begin
dq_en <=1'b0 ;
dq_out<=1'b0 ;
end
RD_TEMP:
if(cnt_state<=1)
begin
dq_en <=1'b1 ;
dq_out<=1'b0 ;
end
else
begin
dq_en <=1'b0 ;
dq_out<=1'b0 ;
end
default:
begin
dq_en <=1'b0 ;
dq_out<=1'b0 ;
end
endcase
always@(posedge us_clk or negedge rst_n_sys)
if(!rst_n_sys)
cnt_state<=20'd0 ;
else if (((state==RD_TEMP || state==WR_CMD ||state==RD_CMD)&&cnt_state==CMD_CNT)||
((state==INIT || state==INIT_AGAIN) && cnt_state==INIT_CNT)||
(state==WAIT && cnt_state==WAIT_CNT))
cnt_state<=20'd0 ;
else
cnt_state<=cnt_state+1'b1 ;
always@(posedge us_clk or negedge rst_n_sys)
if(!rst_n_sys)
flag_init<=1'b0 ;
else if(state==INIT_AGAIN || state==INIT )
if(cnt_state==20'd600 && dq==1'b0)
flag_init<=1'b1 ;
else
flag_init<=flag_init ;
else
flag_init <=1'b0 ;
always@(posedge us_clk or negedge rst_n_sys)
if(!rst_n_sys)
cnt_bit<=4'd0 ;
else if((((state==WR_CMD ||state==RD_CMD )&& cnt_bit==CNT_BIT_CMD_MAX ) ||
(state==RD_TEMP && cnt_bit==CNT_BIT_TEMP_MAX))&& cnt_state==CMD_CNT)
cnt_bit<=4'd0 ;
else if(state==RD_TEMP || state==WR_CMD ||state==RD_CMD)
cnt_bit<=cnt_bit+1'b1 ;
else
cnt_bit<=4'b0 ;
always@(posedge us_clk or negedge rst_n_sys)
if(!rst_n_sys)
temp<=1'b0 ;
else if(state==RD_TEMP && cnt_state==TEMP_CNT_GET)
temp[cnt_bit]<=dq ;
else
temp<=temp ;
always@(posedge us_clk or negedge rst_n_sys)
if(!rst_n_sys)
begin
reg_date <=12'd0 ;
sign <=1'b0 ;
end
else if(state==RD_TEMP && cnt_bit==CNT_BIT_TEMP_MAX && cnt_state==20'd60)
if (temp[15]==1'b0)
begin
reg_date <=temp[11:0] ;
sign <=1'b0 ;
end
else
begin
reg_date <=~temp[11:0]+1'b1 ;
sign <=1'b1 ;
end
else
begin
reg_date <=reg_date ;
sign <=sign ;
end
always@(posedge us_clk or negedge rst_n_sys)
if(!rst_n_sys)
data<=19'd0 ;
else
data<=(temp[11:0]*10'd625)/4'd10 ;
endmodule