spartan-6芯片外挂一颗ds18B20来读取温度,根据此温度来进行加热控制
- 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)
|