三,DS18B20的温度测量控制
在该系统中,1-Wire总线上只存在1个DS18B20,在控制DS18B20进行温度测量的时候,根据1-Wire总线的特性和DS18B20的控制要求,可以采用相对简单的控制流程。下面是控制流程图:
我们用状态机来实现这个控制流程。从控制流程图可以看到,系统从空闲状态到读出温度数据,总共有8个大的步骤。而其中2和6,3和7是相同的,用状态机实现的时候,可以用同一个状态表示2和6,用同一个状态表示3和7。这样整个状态机就只需要6个状态。下面表格是状态机所有状态的定义:
状态名称 |
含义 |
TTST_IDLE |
系统空闲状态 |
TTST_RST |
总线初始化 |
TTST_SKPROM |
SKIP ROM 命令 |
TTST_CONVERT |
温度转换命令 |
TTST_WOVER |
等待温度转换结束 |
TTST_GETDATA |
读取温度数据 |
为了区分2和6以及3和7。用IS_CONVERT信号表示总线初始化和SKIP ROM命令是用来执行CONVERT命令的。用~IS_CONVERT信号表示总线初始化和SKIP ROM命令是用来读取温度数据的。在状态机进入TTST_IDLE状态时,令IS_CONVERT为1并保持,当状态机进入TTST_WOVER状态时,令IS_CONVERT为0并保持。
用TEST_EN信号作为温度测量的开始信号,这个信号至少保持1个时钟周期(CLK1MHZ),如果TEST_EN的长度超过了一次测试所需要的总的时间,则在一次测试完成以后,就直接开始进行第二次测量。
用RST_OVER信号作为总线初始化的结束和下一个状态的开始的标志信号。
用WBD_OVER信号作为命令(SKIPROM,CONVERT)结束和下一个状态开始的标志信号。
用RD_BIT_DATA & PHASE_RD_OVER 表示等待温度转换结束和下一个状态开始的信号(详细的原因可参照DS18B20 datasheet的相关部分)。
用BYTE_READ_OVER & PHASENXT_RDSPAD_IDLE表示读取温度数据结束的信号(该两个信号的与表示读DS18B20 9Byte ROM数据状态机完成工作并进入IDLE状态)。
下面是状态机的状态转换图:
下面是verilog的实现:
reg IS_CONVERT;
parameter TTST_IDLE = 6'b00_0001,
TTST_RST = 6'b00_0010,
TTST_SKPROM = 6'b00_0100,
TTST_CONVERT = 6'b00_1000,
TTST_WOVER = 6'b01_0000,
TTST_GETDATA = 6'b10_0000;
reg [5:0] TTSTSM, TTSTSMNXT;
wire PHASE_TTST_IDLE = TTSTSM[0];
wire PHASE_TTST_RST = TTSTSM[1];
wire PHASE_TTST_SKPROM = TTSTSM[2];
wire PHASE_TTST_CONVERT = TTSTSM[3];
wire PHASE_TTST_WOVER = TTSTSM[4];
wire PHASE_TTST_GETDATA = TTSTSM[5];
wire PHASENXT_TTST_IDLE = TTSTSMNXT[0];
always @(posedge CLK1MHZ or negedge RESET)
begin
if(~RESET)
TTSTSM <= TTST_IDLE;
else
TTSTSM <= TTSTSMNXT;
end
always @(posedge CLK1MHZ or negedge RESET)
begin
if(~RESET)
IS_CONVERT <= 1'b1;
else if(PHASE_TTST_IDLE)
IS_CONVERT <= 1'b1;
else if(PHASE_TTST_WOVER)
IS_CONVERT <= 1'b0;
else
IS_CONVERT <= IS_CONVERT;
end
always @(TTSTSM or TEST_EN or RST_OVER or IS_CONVERT or WBD_OVER or RD_BIT_DATA or PHASE_RD_OVER or PHASE_RD_OVER or BYTE_READ_OVER or PHASENXT_RDSPAD_IDLE ) begin
case(TTSTSM)
TTST_IDLE:
if(TEST_EN)
TTSTSMNXT = TTST_RST;
else
TTSTSMNXT = TTST_IDLE;
TTST_RST:
if(RST_OVER)
TTSTSMNXT = TTST_SKPROM;
else
TTSTSMNXT = TTST_RST;
TTST_SKPROM:
if(WBD_OVER)
if(IS_CONVERT)
TTSTSMNXT = TTST_CONVERT;
else
TTSTSMNXT = TTST_GETDATA;
else
TTSTSMNXT = TTST_SKPROM;
TTST_CONVERT:
if(WBD_OVER)
TTSTSMNXT = TTST_WOVER;
else
TTSTSMNXT = TTST_CONVERT;
TTST_WOVER:
if(RD_BIT_DATA & PHASE_RD_OVER)
TTSTSMNXT = TTST_RST;
else
TTSTSMNXT = TTST_WOVER;
TTST_GETDATA:
if(BYTE_READ_OVER & PHASENXT_RDSPAD_IDLE )
TTSTSMNXT = TTST_IDLE;
else
TTSTSMNXT = TTST_GETDATA;
default:
TTSTSMNXT = TTST_IDLE;
endcase
end
assign WD_DATA_OUT = PHASE_TTST_SKPROM ? 8'hcc : (PHASE_TTST_CONVERT ? 8'h44 : ( PHASE_RDSPAD_CMD ? 8'hbe : 8'h00) );
四,DQ总线的控制
1-Wire总线只有一根信号线,是双向的,带上拉电阻的。在FPGA中做DQ的逻辑如下,至于这么做的原因,不再做叙述。当弄懂了1-Wire总线的规范和DS18B20的基本操作的话,很容易就理解了。
wire DQ, DQ_OUT, DQ_IN, DQ_OUT_EN;
assign DQ = DQ_OUT_EN ? DQ_OUT : 1'bz;
assign DQ_IN = DQ;
wire RD_DQ_OUT = ~PHASE_RD_MPL;
wire RD_DQ_OUT_EN = PHASE_RD_MPL ;
wire WD_DQ_OUT = 1’b0;
wire WD_DQ_OUT_EN = PHASE_WD_MPL | (~WD_BIT_DATA & PHASE_WD_MOUT);
wire DQ_RST_OUT = ~ PHASE_RST_MINIT;
wire DQ_RST_EN = PHASE_RST_MINIT;
assign DQ_OUT = RD_DQ_OUT & RD_DQ_OUT_EN | WD_DQ_OUT & WD_DQ_OUT_EN | DQ_RST_OUT & DQ_RST_EN;
assign DQ_OUT_EN = RD_DQ_OUT_EN | WD_DQ_OUT_EN | DQ_RST_EN;
已投稿到: |
排行榜
|
---|