DS18B20

本文详细介绍了DS18B20的内部结构、温度测量原理、数据时序以及在FPGA中的代码设计和仿真过程。内容包括DS18B20的管脚图、结构方框图,温度寄存器格式,以及温度报警功能。在FPGA实现部分,重点讨论了状态机设计和数据处理,仿真结果显示代码运行正常。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.、一.内部结构框图

1.管脚图

在这里插入图片描述

2.结构方框图

在这里插入图片描述
其中包括:GND接地引脚,VDD电源引脚,DQ总线(当上拉电阻拉高时为由DQ总线为设备供电,当拉低时则为电容向设备供电),CPP内部供电电容,一个64BIT的ROM,中间结果暂存器(温度传感器,报警高触发器,报警低触发器,配置寄存器,8bitCRC发生器)

二.温度测量

1.温度寄存器格式

由8bit的高八位(其中高5位为符号位),8bit低八位组成
在这里插入图片描述
DS18B20的温度输出数据时在摄氏度下校准的;若是在华氏度下应用的话,可以用查表法或者常规的数据换算。温度数据以一个16位标志扩展二进制补码数的形式存储在温度寄存器中(详见图2)。符号标志位(S)温度的正负极性:正数则S=0,负数则S=1。如果DS18B20被定义为12位的转换精度,温度寄存器中的所有位都将包含有效数据。若为11位转换精度,则bit 0为未定义的。若为10位转换精度,则bit 1和bit 0为未定义的。 若为9位转换精度,则bit 2、bit 1和bit 0为未定义的。表格1为在12位转换精度下温度输出数据与相对应温度之间的关系表
温度/数据对应关系
在这里插入图片描述

2.温度报警

在这里插入图片描述
只与温度寄存器数据的4——11位比较,且该寄存器是非易失性的,在每次温度转换完成后,得到的温度会与定义的温度作比较

3.在外部电源模式下

在这里插入图片描述
由外部电源供电,并且有一个上拉电阻在没有数据传输时将总线拉高
64bitrom
在这里插入图片描述
低8位为分类编码。中间48位为序列号,高8位为冗余校验
DS18B20内存映射
暂存寄存器中的Byte 0和Byte 1分别作为温度寄存器的低字节和高字节。同时这两个字节是只读的。Byte 2和Byte 3作为过温和低温(TH和TL)温度报警寄存器。Byte 4保存着配置寄存器的数据,Byte 5、6、7作为内部使用的字节而保留使用,不可被写入。
在这里插入图片描述
暂存寄存器中的Byte 4包含着配置寄存器;如图8所示。用户通过改变表2中R0和R1的值来配置DS18B20的分辨率。上电默认为R0=1及R1=1(12位分辨率)。需要注意的是,转换时间与分辨率之间是有制约关系的。Bit 7和Bit 0至Bit 4作为内部使用而保留使用,不可被写入。
在这里插入图片描述
在这里插入图片描述
测温流程:
在这里插入图片描述
这里只需要发送复位脉冲,并且跳过ROM指令
在这里插入图片描述
这里只需要温度转换,还有从寄存器中读取温度数据

三.数据时序

1.初始化时序

在这里插入图片描述

2.读写时序

写时序
在这里插入图片描述
写时段有两种情况:“写1”时段和“写0”时段。主设备通过写1时段来向DS18B20中写入逻辑1以及通过写0时段来向DS18B20中写入逻辑0。每个写时段最小必须有60us的持续时间且独立的写时段间至少有1us的恢复时间。两个写时段都是由主设备通过将1-Wire总线拉低来进行初始化。
为了形成写1时段,在将1-Wire总线拉低后,主设备必须在15us之内释放总线。当总线释放后,5kΩ的上拉电阻将总线拉至高。为了形成写0时段,在将1-Wire总线拉低后,在整个时段期间主设备必须一直拉低总线(至少60us)。
在主设备初始化写时段后,DS18B20将会在15us至60us的时间窗口内对总线进行采样。如果总线在采样窗口期间是高电平,则逻辑1被写入DS18B20;若总线是低电平,则逻辑0被写入DS18B20。
读时序
在这里插入图片描述

四.代码设计

1.状态机设计

在这里插入图片描述

2.代码

驱动模块,通过主从状态机实现,主状态机控制整个流程,从状态负责数据的发送接收

/**************************************功能介绍***********************************
Date	: 
Author	: WZY.
Version	: 
Description: ws18d20驱动模块
*********************************************************************************/
    
//---------<模块及端口声名>------------------------------------------------------
module ws18d20_dirver( 
    input 	wire				clk		,
    input 	wire				rst_n	,
    input   wire                flag_ws18d20_dirver,
    output  reg     [23:0]      temp_data,
    output  reg                 temp_data_vld,
    inout   wire                dp   
);								 
//---------<参数定义>--------------------------------------------------------- 
//主状态机参数
localparam M_IDLE = 0,//空闲状态
           M_REST = 1,//发送复位脉冲
           M_RELS = 2,//释放总线15~60us
           M_RACK = 3,//接收存在脉冲
           M_ROMS = 4,//发送跳过ROM指令
           M_CONT = 5,//发送温度转换指令
           M_WAIT = 6,//等待温度转换完成
           M_RCMD = 7,//发送读取温度命令
           M_RTMP = 8;//接收温度数据
//副状态机参数
localparam S_IDLE = 0,//空闲状态等待传输请求
           S_LOW  = 1,//读写前拉低大于1us
           S_SEND = 2,//发送1bit数据,持续59us
           S_SAMP = 3,//接收1bit数据,持续59us
           S_RELS = 4,//时隙间隔,大于1us
           S_DOWN = 5;//一次命令或者数据执行完成
parameter  T_CYC    = 20;
//状态机计数器参数
parameter  REST_T = 480_000,
           RELS_T = 60_000,
           RACK_T = 240_000,
           WAIT_T = 750_000_000;
//从状态机计数器参数
parameter  LOW_T    = 1_000,
           SEND_T   = 60_000,
           SAMP_T   = 60_000,
           S_RELS_T = 1_000;
parameter  RX_RACK_T = 20_000;
parameter  RX_SAMP_T = 12_000;

parameter  SKIP     = 8'hCC,
           CONVER   = 8'h44,
           READ     = 8'hBE;





//---------<内部信号定义>-----------------------------------------------------
//主状态机参数
reg 	[3:0]	cstate_M     ;//现态
reg	    [3:0]	nstate_M     ;//次态

wire            midle2rest;
wire            mrest2rels;
wire            mrels2rack;
wire            mrack2roms;
wire            mrack2idle;
wire            mroms2cont;
wire            mroms2rcmd;
wire            mcont2wait;
wire            mwait2rest;
wire            mrcmd2rtmp;
wire            mrtmp2idle;

reg             flag_S;//跳转使能

//从状态机参数
reg 	[5:0]	cstate_S     ;//现态
reg	    [5:0]	nstate_S     ;//次态

wire            sidle2low;
wire            slow2send;
wire            slow2samp;
wire            ssend2rels;
wire            ssamp2rels;
wire            srels2down;
wire            srels2low;
wire            sdown2idle;

reg         cmd_vld;//跳转使能

//三态门判断
reg             OE         ;
wire            din;
reg             dout;

//数据传输
reg     [7:0]   dict;

//数据接收
reg     [15:0]  recept_data;//接收数据
reg     [10:0]  temp_data_w;//原码
wire    [23:0]  temp_data_r; //数据处理        

//主状态机计数器参数
reg			[25:0]	cnt_num_M	   	;
wire				add_cnt_num_M	;
wire				end_cnt_num_M	;
reg         [25:0]  num_M         ;

//从状态机计数器参数
reg			[25:0]	cnt_num_S	   	;
wire				add_cnt_num_S	;
wire				end_cnt_num_S	;
reg         [25:0]  num_S         ;

reg                 slave_rac   ;//数据输入

//bit计数器参数
reg			[15:0]	cnt_bit	   	;
wire				add_cnt_bit	;
wire				end_cnt_bit	;
reg         [15:0]  num_bit;
reg                 flag_bit;




//****************************************************************
//                      主状态机
//****************************************************************

//第一段:时序逻辑描述状态转移
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        cstate_M <= M_IDLE;
    end 
    else begin 
        cstate_M <= nstate_M;
    end 
end

//第二段:组合逻辑描述状态转移规律和状态转移条件
always @(*) begin
    case(cstate_M)
         M_IDLE :   begin
                        if (midle2rest) begin
                            nstate_M = M_REST;
                        end
                        else begin
                            nstate_M = cstate_M;
                        end
                    end
         M_REST :   begin
                        if (mrest2rels) begin
                            nstate_M = M_RELS;
                        end
                        else begin
                            nstate_M = cstate_M;
                        end
                    end
         M_RELS :   begin
                        if (mrels2rack) begin
                            nstate_M = M_RACK;
                        end
                        else begin
                            nstate_M = cstate_M;
                        end
                    end 
         M_RACK :   begin
                        if (mrack2roms) begin
                            nstate_M = M_ROMS;
                        end
                        else if (mrack2idle) begin
                            nstate_M = M_IDLE;
                        end
                        else begin
                            nstate_M = cstate_M;
                        end
                    end
         M_ROMS :   begin
                        if (mroms2cont) begin
                            nstate_M = M_CONT;
                        end
                        else if (mroms2rcmd) begin
                            nstate_M = M_RCMD;
                        end
                        else begin
                            nstate_M = cstate_M;
                        end
                    end
         M_CONT :   begin
                        if (mcont2wait) begin
                            nstate_M = M_WAIT;
                        end
                        else begin
                            nstate_M = cstate_M;
                        end
                    end
         M_WAIT :   begin
                        if (mwait2rest) begin
                            nstate_M = M_REST;
                        end
                        else begin
                            nstate_M = cstate_M;
                        end
                    end
         M_RCMD :   begin
                        if (mrcmd2rtmp) begin
                            nstate_M = M_RTMP;
                        end
                        else begin
                            nstate_M = cstate_M;
                        end
                    end
         M_RTMP :   begin
                        if (mrtmp2idle) begin
                            nstate_M = M_IDLE;
                        end
                        else begin
                            nstate_M = cstate_M;
                        end
                    end
        default : nstate_M = M_IDLE;
    endcase
end

assign midle2rest = cstate_M == M_IDLE && flag_ws18d20_dirver;//主机上电后自动进入复位状态
assign mrest2rels = cstate_M == M_REST && end_cnt_num_M;//复位脉冲计数480us后跳转
assign mrels2rack = cstate_M == M_RELS && end_cnt_num_M;//释放总线
assign mrack2roms = cstate_M == M_RACK && end_cnt_num_M && (slave_rac == 0);//接收存在脉冲
assign mrack2idle = cstate_M == M_RACK && end_cnt_num_M ;//未接收到存在脉冲
assign mroms2cont = cstate_M == M_ROMS && sdown2idle&&(flag_S == 0);//发送完8bit数据指令
assign mroms2rcmd = cstate_M == M_ROMS && sdown2idle&&(flag_S == 1);//发送完8bit数据指令
assign mcont2wait = cstate_M == M_CONT && sdown2idle;//发送完8bit数据指令
assign mwait2rest = cstate_M == M_WAIT && end_cnt_num_M;
assign mrcmd2rtmp = cstate_M == M_RCMD && sdown2idle;//发送完8bit数据指令
assign mrtmp2idle = cstate_M == M_RTMP && sdown2idle;//接收完16bit温度数据

            
//第三段:描述输出,时序逻辑或组合逻辑皆可

//****************************************************************
//                  从状态机
//****************************************************************

//第一段:时序逻辑描述状态转移
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        cstate_S <= S_IDLE;
    end 
    else begin 
        cstate_S <= nstate_S;
    end 
end

//第二段:组合逻辑描述状态转移规律和状态转移条件
always @(*) begin
    case(cstate_S)
        S_IDLE :  begin
                    if (sidle2low) begin
                        nstate_S =  S_LOW;
                    end
                    else begin
                        nstate_S = cstate_S;
                    end
                end
        S_LOW  :  begin
                    if (slow2send) begin
                        nstate_S =  S_SEND;
                    end
                    else if (slow2samp) begin
                        nstate_S = S_SAMP;
                    end
                    else begin
                        nstate_S = cstate_S;
                    end
                end
        S_SEND :  begin
                    if (ssend2rels) begin
                        nstate_S =  S_RELS;
                    end
                    else begin
                        nstate_S = cstate_S;
                    end
                end
        S_SAMP :  begin
                    if (ssamp2rels) begin
                        nstate_S =  S_RELS;
                    end
                    else begin
                        nstate_S = cstate_S;
                    end
                end
        S_RELS :  begin
                    if (srels2down) begin
                        nstate_S =  S_DOWN;
                    end
                    else if (srels2low) begin
                        nstate_S = S_LOW;
                    end
                    else begin
                        nstate_S = cstate_S;
                    end
                end
        S_DOWN :  begin
                    if (sdown2idle) begin
                        nstate_S =  S_IDLE;
                    end
                    else begin
                        nstate_S = cstate_S;
                    end
                end 
        default : ;
    endcase
end
            

assign sidle2low  = cstate_S == S_IDLE && cmd_vld;//主状态机在发送指令或者接收数据状态跳转
assign slow2send  = cstate_S == S_LOW  && end_cnt_num_S && (cstate_M != M_RTMP);//主状态为发送状态
assign slow2samp  = cstate_S == S_LOW  && end_cnt_num_S && (cstate_M == M_RTMP);//主状态为接收状态
assign ssend2rels = cstate_S == S_SEND && end_cnt_num_S;//1bit数据发送完成
assign ssamp2rels = cstate_S == S_SAMP && end_cnt_num_S;//1bit数据发送完成
assign srels2down = cstate_S == S_RELS && end_cnt_num_S && flag_bit;//时隙延迟1us且bit数已经发完
assign srels2low  = cstate_S == S_RELS && end_cnt_num_S;//bit数未发完
assign sdown2idle = cstate_S == S_DOWN && 1;        
//****************************************************************
//                          从状态机跳转使能
//****************************************************************  

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        cmd_vld <= 0;
    end
    else if (mrack2roms||mroms2cont||mroms2rcmd||mrcmd2rtmp) begin
        cmd_vld <= 1;
    end
    else begin
      cmd_vld <= 0;
    end
end         
            
//****************************************************************
//                  主状态机复用计数器
//****************************************************************

always @(posedge clk or negedge rst_n)begin 
   if(!rst_n)begin
        cnt_num_M <= 'd0;
    end 
    else if(add_cnt_num_M)begin 
        if(end_cnt_num_M)begin 
            cnt_num_M <= 'd0;
        end
        else begin 
            cnt_num_M <= cnt_num_M + 1'b1;
        end 
    end
end 

assign add_cnt_num_M =( cstate_M == M_REST)||( cstate_M == M_RELS)||( cstate_M == M_RACK)||(cstate_M == M_WAIT);
assign end_cnt_num_M = add_cnt_num_M && cnt_num_M == num_M-1;

always @(*) begin
    case (cstate_M)
       M_REST : num_M =
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值