差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
温度传感器模块 [2017/06/06 14:15]
anran [STEP FPGA驱动单总线温度传感器DS18B20Z模块]
温度传感器模块 [2020/01/18 21:36] (当前版本)
gongyu
行 1: 行 1:
-======STEP FPGA驱动温度传感器DS18B20Z======+### STEP FPGA驱动温度传感器DS18B20Z
  
-本节将和大家一起使用FPGA驱动底板上的DS18B20Z传感器进行温度数据的采集。+本节将和大家一起使用FPGA驱动底板上的DS18B20Z单总线温度传感器进行温度数据的采集。
  
- +--- 
-====硬件说明==== +#### 硬件说明 
-------- +DS18B20是我们日常设计常用一款温度传感器芯片只需要一根总线可以实现通信,非常的方便,我们的[[STEP-BaseBoard]]底板上就集成了温度传感器DS18B20Z下面我们就一起来学习一下它的硬件链接及驱动方法
-在前面之前的入门教程[[4. 数码管显示| 数码管独立显示 ]]章节已为大家介绍了数码管独立显示相关内容关于独立显示这里不在赘述。我们的底板上有6位数码管根据驱动方法不同,有以下比较:+
 \\ \\
-独立显示:控制每个数码管至少需要8个I/​O口控制,6位数码管就需要6*8 = 48信号线才能分别显示。独立显示实现简单,但是需要大量信号线。+DS18B20Z只有一线,硬件电路非常简单,但是一定记得总线需要做上拉处理,如下图总线上连接了10K(上拉电阻取值可以一定范围内自行调整)上拉电阻,另外我们使用FPGA驱动,一定记得将FPGA对应的管脚同样作上拉配置,重要的事情说三遍,总线上拉,总线上拉,总线上拉 
 +{{ :​ds18b20z硬件电路.jpg?​800 |}}
 \\ \\
-扫描显示:将每位数码管的同一段选信号连接在一起这样我们就只需8根段选号和6根位选信号14根信号扫描显示可以有效节约I/​O口资源,实现起来稍显复杂。 +聊完硬件连接,接下来简介绍如何驱动(更加详细的息需要大家参考数据手册)不同的功能需求对应不同寄存器配置,本设执行的操作案例如下
-{{ :​6位数码管.jpg?​1600 |}}+
 \\ \\
-我们小脚丫底板上使用的6位共阴极数码管,分析扫描显示的原理如下:+{{ :​ds18b20z驱动案例.jpg?​800 |}}
 \\ \\
-当某一时刻,FPGA控制8根公共段选接口输出数字1对应的数码管字库数据8'​h06(DP=0、G=0、F=0、E=0、D=0、C=1、B=1、A=0),同时控制6位数码管只有第1位使能(DIG1=0、DIG2=1、DIG3=1、DIG4=1、DIG5=1、DIG6=1)这样我们会看到第1位数码管显示数字1,其余5位数码管不显示,如果不明白可以参考入门教程中实验四[[4. 数码管显示| 数码管独立显示 ]]章节+下面为大家展示上述案例中每个环节的时序要求
 \\ \\
-按照扫描的方式,一共分为6个刻,段选端口分别对应输出6位数码管需要显示的字库数据,位选端口保持每个时刻只有1位数码管处于使能状态,6个时刻依次循环,当扫描频率足够高(例如当扫描频率等于100Hz)时,则在人眼看到的数码管显示就是连续的,我们看到的就是6个不同的数字。+{{ :​ds18b20z初始化序.jpg?800 |}}
 \\ \\
-上面为大家介绍了数码管的独立显示和扫描显示两种方法,扫描显示的方式使用了14个I/​O口控制,相对于简单的处理器来讲14个I/​O口也是非常多了,这里我们又使用了一款常见的驱动芯片74HC595,下面我们一起了解一下:+{{ :​ds18b20z读写时序.jpg?​800 |}}
 \\ \\
-74HC595是较为常用的串行并行的芯片,内部集成了一个8位移位寄存器、一个存储器和8个三态缓冲输出。在最简单的情况下我们只需要控制3根引脚输入得到8根引脚并行输出信号,而且可以级联使用,我们使用3个I/​O口控制两个级联的74HC595芯片,产生16路并行输出,连接到扫描显示的6位数码管上,可以轻松完成数码管驱动任务。+{{ :温度换时间.jpg?​800 |}}
 \\ \\
-{{ :74hc595电路.jpg?1000 |}}+{{ :温度编码格式.jpg?800 |}}
 \\ \\
-不同的IC厂家都可以生产74HC595芯片,功能都是一样的,然而不同厂家的芯片手册对于管脚的命名会存在差异,管脚顺序相同,大家可以对应识别 +{{ :温度值对照表.jpg?800 |}}
-上图是本设计中74HC595芯片的硬件电路连接,参考74HC595数据手册了解其具体用法,下图中我们了解到OE#​(G#​)和MR#​(SCLR#​)信号分别为输出使能(低电平输出)和复位管脚(低电平复位),OE#​(G#​)我们接GND让芯片输出使能,MR#​(SCLR#​)我们接VCC让芯片的移位寄存器永远不复位,如此FPGA只需要控制SH_CP(SCK)、ST_CP(RCK)和DS(SER)即可。 +
-\\ +
-{{ :74hc595引脚功能.jpg |74hc595引脚功能}} +
-\\ +
-{{ :​74hc595逻辑图.jpg |74hc595逻辑图}} +
-\\ +
-{{ :​74hc595时序图.jpg |74hc595时序图}} +
-\\ +
-{{ :数管程序框图.jpg?1000 |数码管驱动程序框图}}+
 \\ \\
  
-====Verilog代码==== +--- 
-------+#### Verilog代码
 <code verilog> <code verilog>
- 
 // -------------------------------------------------------------------- // --------------------------------------------------------------------
 // >>>>>>>>>>>>>>>>>>>>>>>>>​ COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<​ // >>>>>>>>>>>>>>>>>>>>>>>>>​ COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<​
 // -------------------------------------------------------------------- // --------------------------------------------------------------------
-// Module:Segment_scan ​+// Module:DS18B20Z ​
 //  // 
 // Author: Step // Author: Step
 //  // 
-// Description: ​Display with Segment tube+// Description: ​Drive DS18B20Z to get temperature code
 //  // 
 // Web: www.stepfpga.com // Web: www.stepfpga.com
行 58: 行 47:
 // V1.0     ​|2015/​11/​11 ​  ​|Initial ver // V1.0     ​|2015/​11/​11 ​  ​|Initial ver
 // -------------------------------------------------------------------- // --------------------------------------------------------------------
-module ​Segment_scan+module ​DS18B20Z
 ( (
-input clk_in,​ //​系统时钟 + input clk_in,​ //​系统时钟 
-input rst_n_in,​ //​系统复位,低有效 + input rst_n_in,​ //​系统复位,低有效 
-input [3:​0] seg_data_1, //SEG1 数码要显示的数据 + inout one_wire, //DS18B20Z传感器单总线,双向 
-input [3:0] seg_data_2,​ //SEG2 数码管要显示的数据 + output reg [15:0] data_out //DS18B20Z有效温度数据输出
-input [3:​0] seg_data_3,​ //​SEG3 数码管要显示的数据 +
-input [3:​0] seg_data_4,​ //​SEG4 数码管要显示的数据 +
-input [3:​0] seg_data_5,​ //​SEG5 数码管要显示的数据 +
-input [3:​0] seg_data_6,​ //​SEG6 数码管要显示的数据 +
-input [5:​0] seg_data_en,​ //​各位数码管数据显示使能,[MSB~LSB]=[SEG6~SEG1] +
-input [5:​0] seg_dot_en,​ //​各位数码管小数点显示使能,[MSB~LSB]=[SEG6~SEG1] +
-output reg rclk_out,​ //​74HC595的RCK管脚 +
-output reg sclk_out,​ //​74HC595的SCK管脚 +
-output reg sdio_out //​74HC595的SER管脚+
 ); );
- 
-parameter CLK_DIV_PERIOD = 600; //​分频系数 
- 
-localparam IDLE = 3'​d0;​ 
-localparam MAIN = 3'​d1;​ 
-localparam WRITE = 3'​d2;​ 
- 
-localparam LOW = 1'​b0;​ 
-localparam HIGH = 1'​b1;​ 
- 
-//​创建数码管的字库,字库数据依段码顺序有关 
-//​这里字库数据[MSB~LSB]={DP,​G,​F,​E,​D,​C,​B,​A} 
-reg[7:0] seg [15:​0]; ​ 
-initial begin 
-    seg[0] = 8'​h3f; ​  // ​ 0 
-    seg[1] = 8'​h06; ​  // ​ 1 
-    seg[2] = 8'​h5b; ​  // ​ 2 
-    seg[3] = 8'​h4f; ​  // ​ 3 
-    seg[4] = 8'​h66; ​  // ​ 4 
-    seg[5] = 8'​h6d; ​  // ​ 5 
-    seg[6] = 8'​h7d; ​  // ​ 6 
-    seg[7] = 8'​h07; ​  // ​ 7 
-    seg[8] = 8'​h7f; ​  // ​ 8 
-    seg[9] = 8'​h6f; ​  // ​ 9 
- seg[10] = 8'​h77; ​  // ​ A 
-    seg[11] = 8'​h7c; ​  // ​ b 
-    seg[12] = 8'​h39; ​  // ​ C 
-    seg[13] = 8'​h5e; ​  // ​ d 
-    seg[14] = 8'​h79; ​  // ​ E 
-    seg[15] = 8'​h71; ​  // ​ F 
-end  
   
-//计数器对系统时钟信号进行计数 + /* 
-reg[9:0] cnt=0+ 本设计通过驱动DS18B20Z芯片获取温度数据, 
-always@(posedge clk_in or negedge rst_n_in) begin + 需要了解inout类型的接口如何实现双向通信, 
- if(!rst_n_in) begin + 中间涉及各种不同的延时和寄存器指令操作,注释部分以作简要说明,更多详情需参考数据手册 
- cnt <= 1'​b0;​ + */ 
- end else begin +  
- if(cnt>=(CLK_DIV_PERIOD-1)) cnt <= 1'b0+ localparam IDLE = 3'​d0;​ 
- else ​cnt <= cnt + 1'b1;+ localparam MAIN = 3'​d1;​ 
 + localparam INIT = 3'​d2;​ 
 + localparam WRITE = 3'​d3;​ 
 + localparam READ = 3'​d4;​ 
 + localparam DELAY = 3'​d5;​ 
 +  
 + //计数器分频产生1MHz的时钟信号 
 + reg clk_1mhz;​ 
 + reg [2:0] cnt_1mhz
 + always@(posedge clk_in or negedge rst_n_in) begin 
 + if(!rst_n_in) begin 
 + cnt_1mhz <= 3'​d0;​ 
 + clk_1mhz ​<= 1'​b0;​ 
 + end else if(cnt_1mhz ​>= 3'd5begin 
 + cnt_1mhz ​<= 3'd0; 
 + clk_1mhz <= ~clk_1mhz;​ //​产生1MHz分频 
 + end else begin 
 + cnt_1mhz ​<= cnt_1mhz ​+ 1'b1; 
 + end
  end  end
-end +  
- + reg [2:​0] cnt;​ 
-//​根据计数器计数的周期产生分频的脉冲信号 + reg one_wire_buffer;​ 
-reg clk_div;  + reg [3:​0] cnt_main
-always@(posedge clk_in or negedge rst_n_in) begin + reg [7:​0] data_wr;​ 
- if(!rst_n_in) begin + reg [7:​0] data_wr_buffer;​ 
- clk_div <= 1'b0+ reg [2:​0] cnt_init
- end else begin + reg [19:​0] cnt_delay
- if(cnt==(CLK_DIV_PERIOD-1)) clk_div <= 1'b1+ reg [19:​0] num_delay
- else clk_div <= 1'b0; + reg [3:0] cnt_write
- end + reg [2:​0] cnt_read
-end + reg [15:0] temperature;​ 
- + reg [7:​0] temperature_buffer
-//​使用状态机完成数码管的扫描和74HC595时序的实现 + reg [2:0] state = IDLE; 
-reg [15:0] data_reg+ reg [2:0] state_back = IDLE; 
-reg [2:​0] cnt_main+ //​使用1MHz时钟信号做触发完成下面状态机的功能 
-reg [5:0] cnt_write+ always@(posedge ​clk_1mhz ​or negedge rst_n_in) begin 
-reg [2:0] state = IDLE; + if(!rst_n_in) begin 
-always@(posedge ​clk_in ​or negedge rst_n_in) begin + state <= IDLE; 
- if(!rst_n_in) begin //​复位状态下,各寄存器置初值 + state_back <= IDLE; 
- state <= IDLE; + cnt <= 1'​b0;​ 
- cnt_main <= 3'd0+ cnt_main <= 1'b0
- cnt_write <= 6'd0+ cnt_init <= 1'​b0;​ 
- sdio_out ​<= 1'​b0;​ + cnt_write <= 1'b0
- sclk_out ​<= LOW+ cnt_read ​<= 1'​b0;​ 
- rclk_out ​<= LOW+ cnt_delay ​<= 1'b0
- end else begin + one_wire_buffer ​<= 1'bz
- case(state) + temperature <= 16'​h0;​ 
- IDLE:​begin //​IDLE作为第一个状态,相当于软复位 + end else begin 
- state <= MAIN; + case(state) 
- cnt_main <= 3'd0+ IDLE:begin //​IDLE状态,程序设计的软复位功能,各状态异常都会跳转到此状态 
- cnt_write <= 6'd0+ state <= MAIN; //​软复位完成,跳转之MAIN状态重新工作 
- sdio_out ​<= 1'​b0;​ + state_back <= MAIN; 
- sclk_out ​<= LOW+ cnt <= 1'​b0;​ 
- rclk_out ​<= LOW+ cnt_main <= 1'b0
- end + cnt_init <= 1'​b0;​ 
- MAIN:​begin + cnt_write <= 1'b0
- if(cnt_main >= 3'd5) cnt_main <= 1'​b0;​ + cnt_read ​<= 1'​b0;​ 
- else cnt_main <= cnt_main + 1'​b1;​ + cnt_delay ​<= 1'b0
- case(cnt_main) + one_wire_buffer ​<= 1'bz
- //对6位数码管逐扫描 + end 
- 3'd0: begin  + MAIN:begin //​MAIN状态控制状态机在不同状态间跳转,实现完整的温度数据采集 
- state <= WRITE; //在配置完给74HC595的数据同时跳转至WRITE状态,完成串时序 + if(cnt_main >= 4'd11) cnt_main <= 1'​b0;​ 
- data_reg ​<= {seg[seg_data_1]|(seg_dot_en[0]?​8'h80:8'h00),​seg_data_en[0]?​8'​hfe:8'hff}+ else cnt_main <= cnt_main + 1'​b1;​ 
- //data_reg[15:8]为段选,data_reg[7:0]为位选 + case(cnt_main) 
- //seg[seg_data_1] ​ 是根据端口的输入获相应字库数据 + 4'​d0:​ begin state <= INIT; end //跳转至INIT状态进行芯片的复及验证 
- //seg_dot_en[0]?​8'h80:8'​h00 ​ 是根据小数点显示使能信号 控制SEG1数码管的小数点DP段的电平 + 4'd1: begin data_wr <= 8'​hcc;​state <= WRITE; end //​主设备发出跳转ROM指令 
- //seg_data_en[0]?​8'​hfe:​8'​hff ​ 是根据数据显示使能信号 控制SEG1数码管的位选引脚的电平 + 4'​d2:​ begin data_wr <= 8'h44;state <= WRITE; ​end //主设备出温度转换指令 
- end + 4'​d3:​ begin num_delay <= 20'​d750000;​state <= DELAY;​state_back <= MAIN; end //延750ms等待转换完成 
- 3'd1:​ begin ​ +  
- state <= WRITE; + 4'​d4:​ begin state <= INIT; end //跳转至INIT状态芯片的复位及验证 
- data_reg ​<= {seg[seg_data_2]|(seg_dot_en[1]?​8'​h80:8'​h00),​seg_data_en[1]?​8'​hfd:​8'​hff};  + 4'​d5:​ begin data_wr ​<= 8'hcc;state <= WRITE; end //​主设备发出跳转ROM指令 
- end + 4'd6begin data_wr <= 8'hbe;state <= WRITE; end //​主设备发出读取温度指令 
- 3'​d2: begin  +  
- state ​<= WRITE+ 4'​d7:​ begin state <= READ; end //跳转至READ状态进行单总线数据读取 
- data_reg ​<= {seg[seg_data_3]|(seg_dot_en[2]?​8'​h80:​8'h00),​seg_data_en[2]?​8'hfb:8'hff} + 4'​d8begin temperature[7:0] <= temperature_buffer;​ end //先读的为低8位数据 
- end +  
- 3'd3:​ begin ​ + 4'​d9:​ begin state <= READ; end //跳转至READ状态进行单总线数据读取 
- state <= WRITE; + 4'd10: begin temperature[15:8] <= temperature_buffer;​ end //后读取的为高8数据 
- data_reg ​<= {seg[seg_data_4]|(seg_dot_en[3]?8'h80:8'h00),​seg_data_en[3]?8'hf7:8'hff} +  
- end + 4'd11: begin state <= IDLE;data_out ​<= temperature;​ end //​将完整的温度数据输出并重复以上所有操作 
- 3'​d4:​ begin ​ + defaultstate <= IDLE
- state <= WRITE; + endcase 
- data_reg ​<= {seg[seg_data_5]|(seg_dot_en[4]?​8'​h80:​8'​h00),​seg_data_en[4]?​8'​hef:​8'​hff}; + end 
- end + INIT:begin //​INIT状态完成DS18B20Z芯片的复位及验证功能 
- 3'​d5:​ begin ​ + if(cnt_init >= 3'd6) cnt_init ​<= 1'b0
- state <= WRITE; + else cnt_init ​<= cnt_init + 1'b1; 
- data_reg ​<= {seg[seg_data_6]|(seg_dot_en[5]?​8'h80:8'​h00),​seg_data_en[5]?​8'​hdf:​8'​hff} + case(cnt_init) 
- end + 3'd0begin one_wire_buffer <= 1'b0; end //​单总线复位脉冲拉低 
- default: state <= IDLE; + 3'd1: begin num_delay <= 20'​d500;​state <= DELAY;state_back ​<= INIT; end //​复位脉冲保持拉低500us时间 
- endcase + 3'd2begin one_wire_buffer <= 1'bz; end //​单总线复位脉冲释放,自动上拉 
- end + 3'd3begin num_delay <= 20'd100;state <= DELAY;​state_back <= INIT; end //​复位脉冲保持释放100us时间 
- WRITE:​begin + 3'd4: begin if(one_wire) ​state <= IDLEelse state <= INIT; end //​根据单总线的存在检测结果判定是否继续 
- if(clk_div) begin //74HC595的串行时钟有速度要求,需要按照分频后节拍 + 3'd5: begin num_delay <= 20'​d400;​state <= DELAY;state_back ​<= INIT; end //​如果检测正常继续保持释放400us时间 
- if(cnt_write >= 6'd33) cnt_write <= 1'​b0;​ + 3'd6begin state <= MAIN; end //​INIT状态操作完成,返回MAIN状态 
- else cnt_write <= cnt_write + 1'b1;+ default: state <= IDLE; 
 + endcase 
 + end 
 + WRITE:​begin //​按照DS18B20Z芯片单总线时序进行写操作 
 + if(cnt <= 3'd6) begin //需要发送8bit数据,这里控制循环的次数 
 + if(cnt_write >= 4'd6) begin cnt_write <= 1'b1; cnt <= cnt + 1'b1; end 
 + else begin cnt_write <= cnt_write + 1'b1; cnt <= cnt; end 
 + end else begin 
 + if(cnt_write >= 4'd8begin cnt_write <= 1'​b0; ​cnt <= 1'b0; end //​两个变量都恢复初值 
 + else begin cnt_write <= cnt_write + 1'b1; cnt <= cnt; end 
 + end 
 + //​对于WRITE状态中cnt_write来讲,执行过程为:0;​[1~6]*8;​7;​8;
  case(cnt_write)  case(cnt_write)
- //74HC595是串行转并行的芯片,3路输入可产生8路输出,而且可以级联使用 + //lock data_wr 
- //​74HC595的时序实现,参考74HC595的芯片手册 + 4'd0: begin data_wr_buffer ​<= data_wr; end //将需要写出的数据缓存 
- 6'​d0: ​ begin sclk_out ​<= LOW; sdio_out <= data_reg[15]; end //SCK下降沿SER更新数据 + //​发送 1bit 数据的用在60~120us之间,参考数据手册 
- 6'​d1: ​ begin sclk_out ​<= HIGH; end //SCK上升沿时SER数据稳定 + 4'd1: begin one_wire_buffer ​<= 1'b0; end //总线拉低 
- 6'​d2: ​ begin sclk_out ​<= LOWsdio_out ​<= data_reg[14]end + 4'd2: begin num_delay ​<= 20'd2;state <= DELAY;state_back ​<= WRITE; end //​延时2us时间,保证15us以内 
- 6'​d3: ​ begin sclk_out ​<= HIGH; end + 4'd3: begin one_wire_buffer ​<= data_wr_buffer[cnt]; end //​先发送数据最低位 
- 6'd4 begin sclk_out ​<= LOW; sdio_out <= data_reg[13]; end + 4'd4: begin num_delay ​<= 20'd80;​state ​<= DELAY;state_back ​<= WRITE; end //​延时80us时间 
- 6'd5 begin sclk_out ​<= HIGH; end + 4'd5: begin one_wire_buffer ​<= 1'bz; end //​总线释放 
- 6'd6:  begin sclk_out ​<= LOWsdio_out ​<= data_reg[12]; end + 4'd6: begin num_delay ​<= 20'd2;state <= DELAY;state_back ​<= WRITE; end //​延时2us时间 
- 6'd7 begin sclk_out ​<= HIGH; end + //back to main 
- 6'd8 begin sclk_out ​<= LOWsdio_out ​<= data_reg[11]end + 4'd7: begin num_delay ​<= 20'd80;state <= DELAY;state_back ​<= WRITE; end //​延时80us时间 
- 6'​d9: ​ begin sclk_out ​<= HIGH; end + 4'd8: begin state <= MAIN; end //​返回MAIN状态 
- 6'd10: begin sclk_out <= LOW; sdio_out <= data_reg[10];​ end + defaultstate <= IDLE; 
- 6'd11: begin sclk_out ​<= HIGHend + endcase 
- 6'​d12:​ begin sclk_out ​<= LOWsdio_out ​<= data_reg[9]; end + end 
- 6'd13: begin sclk_out ​<= HIGH; end + READ:begin //​按照DS18B20Z芯片单总线时序进行读操作 
- 6'd14begin sclk_out ​<= LOW; sdio_out <= data_reg[8]; end + if(cnt ​<= 3'd6) begin //​共需要接收8bit的数据,这里控制循环的次数 
- 6'​d15: begin sclk_out ​<= HIGH; end + if(cnt_read >= 3'd5) begin cnt_read ​<= 1'b0cnt <= cnt + 1'b1; end 
- 6'd16: begin sclk_out ​<= LOWsdio_out ​<= data_reg[7];​ end + else begin cnt_read ​<= cnt_read + 1'b1cnt <= cnt; end 
- 6'd17: begin sclk_out <= HIGH; end + end else begin 
- 6'​d18: ​begin sclk_out ​<= LOWsdio_out ​<= data_reg[6]; end + if(cnt_read >= 3'd6) begin cnt_read ​<= 1'b0cnt <= 1'b0; end //​两个变量都恢复初值 
- 6'​d19:​ begin sclk_out <= HIGH; end + else begin cnt_read ​<= cnt_read + 1'b1cnt <= cnt; end 
- 6'd20: begin sclk_out ​<= LOWsdio_out ​<= data_reg[5];​ end + end 
- 6'd21: begin sclk_out <= HIGH; end + case(cnt_read) 
- 6'​d22: ​begin sclk_out ​<= LOWsdio_out ​<= data_reg[4]; end + //读取 1bit 数据的用时在60~120us之间,总线拉低后15us时间内读取数据,参考数据手册 
- 6'd23: begin sclk_out ​<= HIGH; end + 3'd0: begin one_wire_buffer ​<= 1'b0; end //​总线拉低 
- 6'd24: begin sclk_out ​<= LOWsdio_out ​<= data_reg[3]end + 3'd1: begin num_delay ​<= 20'd2;state <= DELAY;state_back ​<= READ; end //​延时2us时间 
- 6'​d25:​ begin sclk_out ​<= HIGH; end + 3'd2: begin one_wire_buffer ​<= 1'bz; end //​总线释放 
- 6'd26: begin sclk_out ​<= LOW; sdio_out <= data_reg[2]; end + 3'd3: begin num_delay ​<= 20'd5;​state ​<= DELAY;state_back ​<= READ; end //​延时5us时间 
- 6'd27: begin sclk_out ​<= HIGH; end + 3'd4: begin temperature_buffer[cnt] ​<= one_wire; end //​读取DS18B20Z返回的总线数据,先收最低位 
- 6'd28: begin sclk_out ​<= LOWsdio_out ​<= data_reg[1]; end + 3'd5: begin num_delay ​<= 20'd60;state <= DELAY;state_back ​<= READ; end //​延时60us时间 
- 6'd29: begin sclk_out ​<= HIGH; end + //back to main 
- 6'd30: begin sclk_out ​<= LOWsdio_out ​<= data_reg[0]end + 3'd6: begin state <= MAIN; end //​返回MAIN状态
- 6'​d31:​ begin sclk_out ​<= HIGH; end +
- 6'd32: begin rclk_out <= HIGH; end //当16位数据传送完成后RCK拉高,输出生效 +
- 6'd33: begin rclk_out <= LOW; state <= MAIN; end+
  default:​ state <= IDLE;  default:​ state <= IDLE;
  endcase  endcase
- end else begin 
- sclk_out <= sclk_out; 
- sdio_out <= sdio_out; 
- rclk_out <= rclk_out; 
- cnt_write <= cnt_write; 
- state <= state; 
  end  end
- end + DELAY:begin //​延时控制 
- defaultstate <= IDLE+ if(cnt_delay >= num_delay) begin //​延时控制,延时时间由num_delay指定 
- endcase+ cnt_delay ​<= 1'b0
 + state <= state_back; ​ //​很多状态都需要延时,延时后返回哪个状态由state_back指定 
 + end else cnt_delay <= cnt_delay + 1'​b1;​ 
 + end 
 + endcase 
 + end
  end  end
-end +  
 + assign one_wire = one_wire_buffer;​ 
 +
 endmodule endmodule
- 
 </​code>​ </​code>​
- 
-\\  ​ 
 \\  ​ \\  ​
  
-====小结==== +--- 
------- +#### 小结 
-本节主要为大家讲解了数码管显示相关原理及软件设计,需要大家掌握的同时自己创建工程,通过整个设计流程,生成FPGA配置文件加载测试。+本节主要为大家讲解了DS18B20Z驱动方法及软件实现,需要大家掌握的同时自己创建工程,通过整个设计流程,生成FPGA配置文件加载测试。
 \\ \\
 如果你对Diamond软件的使用不了解,请参考这里:[[lattice_diamond的使用|Diamond的使用]]。 如果你对Diamond软件的使用不了解,请参考这里:[[lattice_diamond的使用|Diamond的使用]]。
  
-====相关资料==== +--- 
-------+#### 相关资料
 \\ \\
-使用[[STEP-MXO2第二代]]的数码管扫描程序: ​ 后续会有下载连接 ​ 待更新+使用[[STEP-MXO2第二代]]的基于DS18B20Z的温度计设计程序: ​ 后续会有下载连接 ​ 待更新
 \\ \\
-使用[[STEP-MAX10]]的数码管扫描程序: ​ 后续会有下载连接 ​ 待更新+使用[[STEP-MAX10]]的基于DS18B20Z的温度计设计程序: ​ 后续会有下载连接 ​ 待更新
 \\ \\