标题:
Spartan-6 FPGA驱动ds18B20的源程序
[打印本页]
作者:
hu_junbo
时间:
2018-12-11 15:13
标题:
Spartan-6 FPGA驱动ds18B20的源程序
spartan-6芯片外挂一颗ds18B20来读取温度,根据此温度来进行加热控制
1544512037.png
(36.33 KB, 下载次数: 82)
下载附件
ds18B20电路图
2018-12-11 15:08 上传
module DS18B20_drive
(
input clk,rst_n,
inout temp_dq,
output reg [15:0] temp
);
reg ds,flag;
//延时参数
parameter TIME_1us = 32'd50,
TIME_2us = 32'd100,
TIME_4us = 32'd200,
TIME_8us = 32'd400,
TIME_550us = 32'd27500,
TIME_500us = 32'd25000,
TIME_66us = 32'd3300,
TIME_20us = 32'd1000,
TIME_1s = 32'd50_000_000;
parameter RESET1 = 3'd0,
DELAY1 = 3'd1,
WRITE1 = 3'd2,
DELAY2 = 3'd3,
RESET2 = 3'd4,
DELAY3 = 3'd5,
WRITE2 = 3'd6,
READ = 3'd7;
`define delay_1us cnt_clk_r == TIME_1us
`define delay_2us cnt_clk_r == TIME_2us
`define delay_4us cnt_clk_r == TIME_4us
`define delay_8us cnt_clk_r == TIME_8us
`define delay_20us cnt_clk_r == TIME_20us
`define delay_550us cnt_clk_r == TIME_550us
`define delay_500us cnt_clk_r == TIME_500us
`define delay_66us cnt_clk_r == TIME_66us
`define delay_1s cnt_clk_r == TIME_1s
//状态变重
reg [2:0] work_state,
state_rest1,
state_write1,
state_rest2,
state_write2,
state_read;
reg [4:0] i;
reg [4:0] j;
reg [15:0] value;
//reg flag;
/*
parameter val1 = 16'h44CC,
val2 = 16'hBECC;
*/
reg [15:0] vala;
reg [15:0] val2;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)begin
ds <= 1'b1;
work_state <= 3'd0;
state_rest1 <= 3'd0;
state_write1<= 3'd0;
state_rest2 <= 3'd0;
state_write2<= 3'd0;
state_read <= 3'd0;
vala <= 16'h44CC;
val2 <= 16'hBECC;
i <= 5'd0;
j <= 5'd0;
flag <= 1'b1;
end
else begin
case(work_state)
//复位1
RESET1:
case(state_rest1)
3'd0: //ds=1 延时1us
begin
state_rest1 <= (`delay_1us) ? 3'd1:3'd0;
ds <= 1'b1;
end
3'd1: //ds=0 延时550us 要求480~960us
begin
state_rest1 <= (`delay_550us) ? 3'd2:3'd1;
ds <= 1'b0;
end
3'd2: //ds=z 延时66us 释放总线等待15-60us使ds18B20发出低脉再
begin
state_rest1 <= (`delay_66us) ? 3'd3:3'd2;
ds <= 1'bz;
end
3'd3://获取低脉再
begin
state_rest1 <= 3'd4;
flag <= ds;
end
3'd4:
begin
if(flag==1'b0)
begin
ds <= 1'bz;
work_state <= DELAY1;
end
else
begin
state_rest1 <= 3'd0;
ds <= 1'b1;
work_state <= work_state;
end
end
default:state_rest1 <= 3'd0;
endcase
DELAY1://等待18B20发出的低脉冲信号完全结束60~240us
begin
work_state <= (`delay_500us) ? WRITE1 : DELAY1;
//flag <= 1'b1;
end
//写数捠写入数据16'hcc 16'h44
WRITE1:
case(state_write1)
3'd0: // ds=1 延时1us 连续写两位间隔大仵s
begin
state_write1 <= (`delay_2us) ? 3'd1:3'd0;
ds <= 1'b1;
end
3'd1: //ds=0 延时4us 将FPGA引脚从高拉至低电平时,就产生写时间隙
begin
state_write1 <= (`delay_4us) ? 3'd2:3'd1;
ds <= 1'b0;
end
3'd2: //写一侥۶时66us
begin
state_write1 <= (`delay_66us) ? 3'd3:3'd2;
ds <= vala[0];
end
3'd3:
begin
if(i <= 14)
begin
vala <= {1'b0,vala[15:1]};
i <= i+1'b1;
state_write1 <= 3'd0;
end
else if(i==15)
begin
state_write1 <= 3'd4;
vala <= {1'b0,vala[15:1]};
end
end
3'd4: //ds=1 延时1us
begin
ds <= 1'bz;
i <= 5'd0;
state_write1 <= (`delay_1us) ? 3'd5:3'd4;
end
3'd5:
begin
work_state <= DELAY2;
end
default:state_write1 <= 3'd0;
endcase
//延时1s,使得芯片完成温度转化(datasheet要求最尿00ms_
DELAY2:
begin
work_state <= (`delay_1s) ? RESET2:DELAY2;
ds <= 1'bz;
end
//复位2
RESET2:
case(state_rest2)
3'd0: //ds=1 延时1us
begin
state_rest2 <= (`delay_1us) ? 3'd1:3'd0;
ds <= 1'b1;
end
3'd1: //ds=0 延时550us 要求480~960us
begin
state_rest2 <= (`delay_550us) ? 3'd2:3'd1;
ds <= 1'b0;
end
3'd2: //ds=z 延时66us 释放总线等待15-60us使ds18B20发出低脉再
begin
state_rest2 <= (`delay_66us) ? 3'd3:3'd2;
ds <= 1'bz;
end
3'd3://获取低脉再
begin
state_rest2 <= 3'd4;
flag <= ds;
end
3'd4:
begin
if(flag==1'b0)
begin
ds <= 1'bz;
work_state <= DELAY3;
end
else
begin
state_rest2 <= 3'd0;
ds <= 1'b1;
work_state <= work_state;
end
end
default:state_rest2 <= 3'd0;
endcase
DELAY3:
begin
work_state <= (`delay_500us) ? WRITE2:DELAY3;
end
//写操你写入16'hcc 16'hBE
WRITE2:
case(state_write2)
3'd0: // ds=1 延时1us 连续写两位间隔大仵s
begin
state_write2 <= (`delay_2us) ? 3'd1:3'd0;
ds <= 1'b1;
end
3'd1: //ds=0 延时4us
begin
state_write2 <= (`delay_4us) ? 3'd2:3'd1;
ds <= 1'b0;
end
3'd2: //写一侥۶时66us
begin
state_write2 <= (`delay_66us) ? 3'd3:3'd2;
ds <= val2[0];
end
3'd3:
begin
if(i <= 14)
begin
val2 <= {1'b0,val2[15:1]};
i <= i+1'b1;
state_write2 <= 3'd0;
end
else if(i==15)
begin
state_write2 <= 3'd4;
val2 <= {1'b0,val2[15:1]};
end
end
3'd4: //ds=z 延时1us
begin
ds <= 1'bz;
i <= 5'd0;
state_write2 <= (`delay_1us) ? 3'd5:3'd4;
end
3'd5:
begin
work_state <= READ;
end
default:state_write2 <= 3'd0;
endcase
//读操位
READ:
case(state_read)
3'd0: // ds=1 延时2us 读两个位之间应大仵s
begin
ds <= 1'b1;
state_read <= (`delay_2us) ? 3'd1:3'd0;
end
3'd1: //ds=0 延时4us 从高拉至低电平时,总线只须保持低电庵s
begin
state_read <= (`delay_4us) ? 3'd2:3'd1;
ds <= 1'b0;
end
3'd2: //ds=1 延时4us 将总线拉高,产生读时间隍
begin
state_read <= (`delay_4us) ? 3'd3:3'd2;
ds <= 1'b1;
end
3'd3:
begin
value[0] <= ds;
state_read <= 3'd4;
end
3'd4:
begin
if(j<=15)
begin
value <= {value[0], value[15:1]};
j <= j+1'b1;
state_read <= 3'd5;
end
else
begin
state_read <= 3'd6;
temp <= value;
j <= 5'd0;
end
end
3'd5://60us~120us内释放总线
begin
state_read <= (`delay_66us) ? 3'd0:3'd5;
end
3'd6:
begin
ds <= 1'b1;
work_state <= RESET1;
state_rest1 <= 3'd0;
state_write1<= 3'd0;
state_rest2 <= 3'd0;
state_write2<= 3'd0;
state_read <= 3'd0;
vala <= 16'h44CC;
val2 <= 16'hBECC;
flag <= 1'b1;
end
default:state_read <= 3'd0;
endcase
default:work_state <= RESET1;
endcase
end
end
//------------------------------------------------------------------------------
//产生18b20时序操作的延旍
//------------------------------------------------------------------------------
reg[31:0] cnt_clk_r; //时钟计数
reg cnt_rst_n; //时钟计数复位信号
always @ (posedge clk or negedge rst_n)
if(!rst_n) cnt_clk_r <= 32'd0; //计数寄存器复位
else if(!cnt_rst_n) cnt_clk_r <= 32'd0; //计数寄存器清雍
else cnt_clk_r <= cnt_clk_r+1'b1; //启动计数延时
always @(*)begin
case(work_state)
RESET1:
begin
case(state_rest1)
3'd0:cnt_rst_n <= (`delay_1us) ? 1'b0:1'b1;
3'd1:cnt_rst_n <= (`delay_550us) ? 1'b0:1'b1;
3'd2:cnt_rst_n <= (`delay_66us) ? 1'b0:1'b1;
default:cnt_rst_n <= 1'b0;
endcase
end
DELAY1:
begin
cnt_rst_n <= (`delay_500us) ? 1'b0:1'b1;
end
WRITE1:
begin
case(state_write1)
3'd0:cnt_rst_n <= (`delay_2us) ? 1'b0:1'b1;
3'd1:cnt_rst_n <= (`delay_4us) ? 1'b0:1'b1;
3'd2:cnt_rst_n <= (`delay_66us) ? 1'b0:1'b1;
3'd4:cnt_rst_n <= (`delay_1us) ? 1'b0:1'b1;
default:cnt_rst_n <= 1'b0;
endcase
end
DELAY2:
begin
cnt_rst_n <= (`delay_1s) ? 1'b0:1'b1;
end
RESET2:
begin
case(state_rest2)
3'd0:cnt_rst_n <= (`delay_1us) ? 1'b0:1'b1;
3'd1:cnt_rst_n <= (`delay_550us) ? 1'b0:1'b1;
3'd2:cnt_rst_n <= (`delay_66us) ? 1'b0:1'b1;
default:cnt_rst_n <= 1'b0;
endcase
end
WRITE2:
begin
case(state_write2)
3'd0:cnt_rst_n <= (`delay_2us) ? 1'b0:1'b1;
3'd1:cnt_rst_n <= (`delay_4us) ? 1'b0:1'b1;
3'd2:cnt_rst_n <= (`delay_66us) ? 1'b0:1'b1;
3'd4:cnt_rst_n <= (`delay_1us) ? 1'b0:1'b1;
default:cnt_rst_n <= 1'b0;
endcase
end
DELAY3:
begin
cnt_rst_n <= (`delay_500us) ? 1'b0:1'b1;
end
READ:
begin
case(state_read)
3'd0:cnt_rst_n <= (`delay_2us) ? 1'b0:1'b1;
3'd1:cnt_rst_n <= (`delay_4us) ? 1'b0:1'b1;
3'd2:cnt_rst_n <= (`delay_4us) ? 1'b0:1'b1;
3'd5:cnt_rst_n <= (`delay_66us) ? 1'b0:1'b1;
default:cnt_rst_n <= 1'b0;
endcase
end
default:cnt_rst_n <= 1'b0;
endcase
end
assign temp_dq = ds;
/*
//chipscope观察输出和输入的数据,检查数据是否正硿
wire [35:0] CONTROL0;
wire [255:0] TRIG0;
chipscope_icon icon_debug (
.CONTROL0(CONTROL0) // INOUT BUS [35:0]
);
chipscope_ila ila_filter_debug (
.CONTROL(CONTROL0), // INOUT BUS [35:0]
// .CLK(dma_clk), // IN
.CLK(clk), // IN
.TRIG0(TRIG0) // IN BUS [255:0]
//.TRIG_OUT(TRIG_OUT0)
);
assign TRIG0[15:0] = temp;
assign TRIG0[31:16] = ~temp;
*/
endmodule
复制代码
全部资料51hei下载地址:
DS18B20_drive.zip
(2.36 KB, 下载次数: 31)
2018-12-11 15:13 上传
点击文件名下载附件
源码
下载积分: 黑币 -5
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1