ds18b20实现温度采集

ds18b20实现温度采集

  • 一、传感器
    • 1、基本认识
    • 2、主要特征
    • 3、结构功能
    • 4、操作指令
    • 5、温度测量
  • 二、执行及时序
    • 1、执行顺序
    • 2、相关时序
      • 1、初始化
      • 2、写时序
      • 3、读时序
  • 三、工程分析
    • 1、功能说明
    • 2、模块划分
    • 3、三态门
    • 4、状态机设计
    • 5、时间参数
  • 四、具体实现
    • 1、传感器驱动
    • 2、控制模块
    • 3、顶层
  • 五、参考资料

一、传感器

1、基本认识

  • DS18B20是常用的数字温度传感器,其输出的是数字信号,具有体积小,硬件开销低,抗干扰能力强,精度高的特点;
  • DS18B20数字温度传感器接线方便,封装成后可应用于多种场合,如管道式,螺纹式,磁铁吸附式,不锈钢封装式,型号多种多样,有LTM8877,LTM8874等等;
  • 主要根据应用场合的不同而改变其外观。封装后的DS18B20可用于电缆沟测温,高炉水循环测温,锅炉测温,机房测温,农业大棚测温,洁净室测温,弹药库测温等各种非极限温度场合;
  • 耐磨耐碰,体积小,使用方便,封装形式多样,适用于各种狭小空间设备数字测温和控制领域。

引脚分配
ds18b20实现温度采集_第1张图片
引脚说明

引脚 名称 描述
GND Ground 接地
DQ Data In/Out 输入输出
VDD Power Supply Voltage 供电电源
NC No Connect 无连接【悬空】

2、主要特征

ds18b20的主要特性:

  1. 适应电压范围更宽,电压范围:3.0~5.5V,在寄生电源方式下可由数据线供电
  2. 独特的单线接口方式,DS18B20在与微处理器连接时仅需要一条口线即可实现微处理器与DS18B20的双向通讯;
  3. DS18B20支持多点组网功能,多个DS18B20可以并联在唯一的三线上,实现组网多点测温
  4. DS18B20在使用中不需要任何外围元件,全部 传感元件及转换电路集成在形如一只三极管的集成电路内;
  5. 测温范围-55℃~+125℃,在-10~+85℃时精度为±0.5℃
  6. 可编程的分辨率为9~12位,对应的可分辨温度分别为0.5℃、0.25℃、0.125℃和0.0625℃,可实现高精度测温
  7. 在9位分辨率时最多在 93.75ms内把温度转换为数字,12位分辨率时最多在750ms内把温度值转换为数字,速度更快;
  8. 测量结果直接输出数字温度信号,以"一 线总线"串行传送给CPU,同时可传送CRC校验码,具有极强的抗干扰纠错能力
  9. 负压特性:电源极性接反时,芯片不会因发热而烧毁, 但不能正常工作。

DS18B20的另一个特性是能够在没有外部电源的情况下工作。当总线高时,通过DQ线针供电。高总线信号还为内部电容器(CPP)充电,当总线低时,CPP向设备供电。这种从1线总线中获得功率的方法被称为“寄生虫功率”。作为一种替代方案,DS18B20也可以由VDD上的外部电源供电。

3、结构功能

ds18b20内部结构主要由四部分组成64位光刻ROM、温度传感器、非挥发的温度报警传感器TH和TL、配置寄存器
ds18b20实现温度采集_第2张图片
每只ds18b20都有一个唯一的长达64位的只读存储器,存放在ROM中,低8位是ds18b20的单总线温度传感器,高8位是CRC循环冗余校验码,用以校正前56位是否正常,中间48位是一个唯一序列号,此64位只读寄存器常用于元器件的识别和匹配
ds18b20实现温度采集_第3张图片
64位ROM和ROM操作控制区允许DS18B20作为单总线协议工作,只有建立了ROM操作协议,才能对DS18B20进行控制操作,单总线的所有ROM操作,都从一个初始化序列开始,单总线控制器提供了5个ROM操作命令和6个RAM操作命令。

4、操作指令

ROM操作指令

  • Read ROM【33h】:允许总线控制器读取传感器ROM序列,总线上存在单个器件时才能使用,否则会发生数据冲突;
  • Match ROM【55h】:匹配ROM指令,后跟64位ROM序列,此后所有操作都对该器件进行;
  • Skip ROM【CCh】:此后的指令将对在线所有器件起作用;
  • Search ROM【F0h】:允许总线控制器识别总线上所有从机编码;
  • Alarm ROM【ECh】:响应最近一次测温遇到符合报警条件的情况。

RAM操作指令

  • Write Scratchpad【4E】:向DS18B20的暂存器中写入数据;
  • Read Scratchpad【BEh】:读取暂存器的内容;
  • Copy Scratchpad【48h】:将温度报警触发字节存入非易失性存储器里;
  • Convert T【44h】:启动一次温度转换而无需其他数据;
  • 【B8h】:把报警触发器里的值拷回暂存器,上电时自动执行;
  • Read Power Supply【B4h】:获取器件的电源模式“0”=寄生电源,“1”=外部电源

5、温度测量

温度寄存格式
ds18b20实现温度采集_第4张图片

  • DS18B20的核心功能是其直接到数字的温度传感器。该温度传感器的分辨率可被用户配置为9、10、11或12位,分别对应于0.5°C、0.25°C、0.125°C和0.0625°C的增量。
  • 通电时的默认分辨率为12位。
  • DS18B20在低功率空闲状态下通电,要启动温度测量和A到D的转换,主机必须发出转换T【44h】命令。转换后得到的数据存于2字节温度寄存器中,并返回空闲状态。
  • 如果由外部电源供电,则主电源可以在转换命令后发出“读取时隙。”
  • 进行温度转换时响应0;转换完成响应1;如果是寄生电源;则不能使用这种通知技术【总线被拉高】

温度数据关系
ds18b20实现温度采集_第5张图片

温度寄存器的通电复位值为+85°C.

重要提示:

温度寄存格式:
0~3【温度小数位】;
4~10【温度整数位】
11~15【温度符号位】:0是正数;1是负数
负温需要取反加1

温度计算举例
温度为正数

①+10.125
二进制:0000 0000 1010 0010
符号位:蓝色 温度整数:红色 温度小数:粉红
0000 0000 10100010
符号位:0是正数+
2 3 + 2 1 = 10 2^3+2^1=10 23+21=10
2 1 = 2 ∗ 0.625 = 0.125 2^1=2*0.625=0.125 21=20.625=0.125

温度为负数

①-10.125
二进制:1111 1111 0101 1110
符号位:蓝色 温度整数:红色 温度小数:粉红
1111 1111 01011110
符号位:1是负数—
取反:0000 0000 1010 0001
加1:0000 0000 1010 0010
2 3 + 2 1 = 10 2^3+2^1=10 23+21=10
2 1 = 2 ∗ 0.625 = 0.125 2^1=2*0.625=0.125 21=20.625=0.125

报警触发器寄存器格式
在这里插入图片描述

符号位(S)表示该值是正数还是负数:对于正数S=0和负数S=1。

由于TH和TL是8位寄存器,因此在TH和TL比较中只使用温度寄存器的第11至第4位。如果测量的温度低于或等于TL或高于TH,则存在报警条件,并在DS18B20内设置报警标志。每次温度测量后更新,如果报警条件消失,则在下一次温度转换后关闭。

配置寄存器
在这里插入图片描述
温度计分辨率配置
ds18b20实现温度采集_第6张图片

二、执行及时序

1、执行顺序

  • 初始化
  • ROM命令
  • DS18B20功能命令
  1. 初始化序列:1线总线上的所有事务都以一个初始化序列开始。初始化序列由由总线主机发送的复位脉冲和由从端发送的存在脉冲组成。
  2. 主机检测到存在脉冲后,发出ROM命令。这些命令对每个从设备的唯一的64位ROM代码进行操作,如果在1wire总线上存在许多命令,则允许主命令挑出一个特定的设备。
  3. 使用ROM命令处理它希望与其通信的DS18B20之后,主线可以发出DS18B20功能命令之一。这些命令允许主服务器对DS18B20的结果暂存存储器进行写入和读取,启动温度转换并确定电源模式。

2、相关时序

1、初始化

初始化由主机的复位脉冲和DS18B20的存在脉冲组成;总线拉低【大于480us】发送复位脉冲,然后主机释放总线进入接收模式,上拉电阻拉高总线;ds18b20检测到上升沿时等待【15~60us】; 拉低总线【 60-240us】发送存在脉冲
ds18b20实现温度采集_第7张图片

2、写时序

在写入时间槽期间将数据写入DS18B20,并在读取时间槽期间从DS18B20读取数据

总线使用写入时隙“1”或“0”将逻辑1或0写入ds18b20,写入时间段持续时间至少为60us,恢复时间至少为1us。写入“1”由主线拉低而启动;拉低后需要在15us内释放总线,再由上拉电阻拉高总线;写入“0”拉低总线后需要保持总线拉低。
ds18b20实现温度采集_第8张图片

3、读时序

主机须在发送读取暂存寄存器命令【BEh】或读取电源【B4h】命令后生成读取时序,便于ds18b20可以提供所请求的数据。主机也可在发出转换【44h】或【B8h】命令后产生时序,用于查找ds18b20功能命令操作状态。
ds18b20实现温度采集_第9张图片

三、工程分析

1、功能说明

  • 上位机通过串口发送命令控制系统启动或关闭,命令格式为ASCII码;
  • 控制温度传感器的启动或关闭;
  • 控制数码管的启动或关闭,并用数码管显示温度数值;
  • 控制串口启动或关闭,传回温度值。

RTL图
ds18b20实现温度采集_第10张图片

2、模块划分

系统框图:
ds18b20实现温度采集_第11张图片
模块功能说明:

  • ds18b20驱动模块:实现ds18b20的控制流程以及通信时序;
  • 串口接收模块【uart_rx】:接收上位机发送的命令;
  • 命令解析模块【cmd_analy】:解析上位机发送的命令,输出使能信号;
  • 数码管驱动模块【seg_driver】:数码管开启时,显示温度值;
  • 控制模块【control】:控制向上位机发送温度值使能、数码管显示温度使能;
  • 串口发送模块【uart_tx】:上位机发送读取温度值命令时,向上位机发送温度值;
  • ASCII码转十六进制:将上位机发送的ASCII码转换为十六进制;
  • 十六进制转ASCII码:十六进制的温度值,发给上位机。

3、三态门

由于ds18b20是1wire总线协议,数据输入输出都由dq进行,故将其拆分为三态门。有关三态门可参考:
三态门介绍

基本概念

  • 三态门(Three-state gate)是一种重要的总线接口电路。三态指其输出既可以是一般二值逻辑电路,即正常的高电平(逻辑1)或低电平(逻辑0),又可以保持特有的高阻抗状态。高阻态相当于隔断状态(电阻很大,相当于开路)。
  • 高阻态是一个数字电路里常见的术语,指的是电路的一种输出状态,既不是高电平也不是低电平,如果高阻态再输入下一级电路的话,对下级电路无任何影响,和没接一样,如果用万用表测的话有可能是高电平也有可能是低电平,随它后面接的东西定。
  • 处于高阻抗状态时,输出电阻很大,相当于开路,没有任何逻辑控制功能。高阻态的意义在于实际电路中不可能断开电路。三态电路的输出逻辑状态的控制,是通过一个输入引脚实现的。
  • 三态门都有一个EN控制使能端,来控制门电路的通断。 可以具备这三种状态的器件就叫做三态器件。当EN有效时,三态电路呈现正常的“0”或“1”的输出;当EN无效时,三态电路给出高阻态输出

形式及真值表
【a】和【b】相同
ds18b20实现温度采集_第12张图片
a的真值表
ds18b20实现温度采集_第13张图片
【c】和【d】相同
ds18b20实现温度采集_第14张图片
c的真值表
ds18b20实现温度采集_第15张图片

4、状态机设计

状态转移图
ds18b20实现温度采集_第16张图片
状态说明:
主状态机

  • M_REST:发复位脉冲;
  • M_RELS:主机释放主线;
  • M_RACK:主机接收存在脉冲;
  • M_RSKP:主机发送跳过ROM命令;
  • M_SCON:主机发温度转换命令;
  • M_WAIT:等待温度转换完成;
  • M_SRTM:主机发送温度读取命令;
  • M_READ:主机读取温度值。

从状态机

  • S_LOW:主机拉低总线;
  • S_SEND:主机发送1bit数据;
  • S_SAMP:主机接收1bit数据;
  • S_RELS:主机释放总线;
  • S_DONE:传输1bit数据完成。

5、时间参数

发送复位脉冲,释放总线、等待温度转换完成以及接收存在脉冲等时间参数

TIME_1US  = 50,      //基本时间1us
TIME_RST  = 480,     //复位脉冲 500us
TIME_REL  = 20,      //主机释放总线 20us
TIME_PRE  = 200,     //主机接收存在脉冲 200us
TIME_WAIT = 750000,  //主机发完温度转换命令 等待750ms
TIME_LOW  = 2,       //主机拉低总线 2us
TIME_RW   = 60,      //主机读、写1bit 60us
TIME_REC  = 2;       //主机读写完1bit释放总线 3us

四、具体实现

有关串口以及数码管,前面文章有详细介绍。这里主要介绍传感器驱动。

1、传感器驱动

传感器驱动信号输出

//计数器 1us计数器
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            cnt_1us <= 0;
        end 
        else if(add_cnt_1us)begin 
            if(end_cnt_1us)begin 
                cnt_1us <= 0;
            end
            else begin 
                cnt_1us <= cnt_1us + 1;
            end 
        end
    end 
    assign add_cnt_1us = add_flag;
    assign end_cnt_1us = add_cnt_1us && cnt_1us == TIME_1US-1;
//add_flag 计数开始标志
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            add_flag <= 0;
        end 
        else if(add_flag == 1'b0 & enable & m_state_c == M_IDLE)begin 
            add_flag <= 1'b1;
        end 
        else if(add_flag & enable == 1'b0 & m_state_c == M_IDLE)begin 
            add_flag <= 1'b0;
        end 
    end
    //时间计数器
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            cnt <= 0;
        end 
        else if(add_cnt)begin 
            if(end_cnt)begin 
                cnt <= 0;
            end
            else begin 
                cnt <= cnt + 1;
            end 
        end
    end 
    assign add_cnt = end_cnt_1us;
    assign end_cnt = add_cnt && cnt == X-1;
    //时间参数
    always @(*)begin 
        if(m_state_c == M_REST)begin 
            X = TIME_RST;
        end 
        else if(m_state_c == M_RELE)begin 
            X = TIME_REL;
        end 
        else if(m_state_c == M_RACK)begin 
            X = TIME_PRE;
        end 
        else if(m_state_c == M_WAIT)begin 
            X = TIME_WAIT;
        end
        else begin 
            if(s_state_c == S_LOW)
                X = TIME_LOW;
            else if(s_state_c == S_SEND || s_state_c == S_SAMP)
                X = TIME_RW;
            else 
                X = TIME_REC;
        end 
    end
    //数据传输bit计数器
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            cnt_bit <= 0;
        end 
        else if(add_cnt_bit)begin 
            if(end_cnt_bit)begin 
                cnt_bit <= 0;
            end
            else begin 
                cnt_bit <= cnt_bit + 1;
            end 
        end
    end 
    assign add_cnt_bit = s_state_c == S_RELE && end_cnt;
    assign end_cnt_bit = add_cnt_bit && cnt_bit == ((m_state_c == M_RTMP)?16-1:8-1);
//slave_ack  采样传感器的存在脉冲
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            slave_ack <= 1'b1;
        end 
        else if(m_state_c == M_RACK && cnt == 60 && end_cnt_1us)begin 
            slave_ack <= dq_in;
        end 
    end
    //flag=0:发温度转换命令 flag=1:发温度读取命令
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            flag <= 0;
        end 
        else if(m_wait2m_rest)begin//等待转换到复位
            flag <= 1'b1;//转换完成,读取温度
        end 
        else if(m_rtmp2m_idle)begin//读温度到初始
            flag <= 1'b0;
        end 
    end
//输出信号
    //dq_out
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            dq_out <= 0;
        end 
        else if(m_idle2m_rest | s_idle2s_low | m_wait2m_rest | s_rele2s_low)begin 
            dq_out <= 1'b0;
        end 
        else if(s_low2s_send)begin 
            dq_out <= wr_data[cnt_bit];
        end 
    end
    //dq_out_en
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            dq_out_en <= 0;
        end 
        else if(m_idle2m_rest | s_idle2s_low | s_rele2s_low | m_wait2m_rest)begin 
            dq_out_en <= 1'b1;      //输出 dq_out
        end 
        else if(m_rest2m_rele | s_send2s_rele | s_low2s_samp)begin 
            dq_out_en <= 1'b0;      //不输出 dq_out
        end 
    end
/*  注意: 
         在主机发完复位脉冲后要释放总线;
         发完1bit数据后要释放总线;
         在继续发下一bit的时候,仍然要先拉低总线;
         在读数据时,拉低总线1us后要释放总线;
*/
//wr_data 
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            wr_data <= 0;
        end 
        else if(m_rack2m_roms)begin 
            wr_data <= CMD_ROMS;
        end 
        else if(m_roms2m_cont)begin 
            wr_data <= CMD_CONT;
        end
        else if(m_roms2m_rcmd)begin 
            wr_data <= CMD_RTMP;
        end 
    end
//orign_data  串并转换
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            orign_data <= 0;
        end 
        else if(s_state_c == S_SAMP && cnt == 11 && end_cnt_1us)begin 
            orign_data[cnt_bit] <= dq_in; 
        end 
    end
//temp_data
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            temp_data <= 0;
        end 
        else if(s_state_c == S_SAMP && cnt_bit == 15 && s_samp2s_rele)begin 
            if(orign_data[15])
                temp_data <= ~orign_data[10:0] + 1'b1;  //负温 则取反加1 
            else 
                temp_data <= orign_data[10:0];          //正温
        end 
    end

/*  实际的温度值为 temp_data * 0.0625;
    为了保留4位小数精度,将实际温度值放大了10000倍,
    即 temp_data * 625;
*/
    assign temp_data_w = temp_data * 625;
//temp_out
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            temp_out <= 0;
        end 
        else if(m_state_c == M_RTMP && s_rele2s_done)begin 
            temp_out <= temp_data_w;
        end 
    end
//temp_out_vld
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            temp_out_vld <= 0;
        end 
        else begin 
            temp_out_vld <= m_state_c == M_RTMP && s_rele2s_done;
        end 
    end
//temp_sign
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            temp_sign <= 0;
        end 
        else if(s_state_c == S_SAMP && cnt_bit == 15 && s_samp2s_rele)begin 
            temp_sign <= orign_data[15];
        end 
    end

2、控制模块

信号输出

//dec_tmp_data 
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            dec_tmp_data <= 0;
            dec_tmp_data_vld <= 1'b0;
        end 
        else if(dec_tmp_din_vld)begin 
            dec_tmp_data <= dec_tmp_din;
            dec_tmp_data_vld <= 1'b1;
        end 
        else begin 
            dec_tmp_data <= dec_tmp_data;
            dec_tmp_data_vld <= 1'b0;
        end 
    end
//cnt
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            cnt <= 0;
        end 
        else if(add_cnt)begin 
            if(end_cnt)begin 
                cnt <= 0;
            end
            else begin 
                cnt <= cnt + 1;
            end 
        end
    end 
    assign add_cnt = add_flag;
    assign end_cnt = add_cnt && cnt == 11-1;    
//add_flag
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            add_flag <= 0;
        end 
        else if(uart_enable & ascii_data_vld)begin 
            add_flag <= 1'b1;
        end 
        else if(end_cnt)begin 
            add_flag <= 1'b0;
        end 
    end
    assign bcd_en = (uart_enable | seg_enable) & dec_tmp_data_vld;
    assign hex_data = bcd_tmp[23:0];
    assign hex_data_vld = bcd_tmp_vld;
    
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            ascii_data <= 0;
            ascii_data_vld <= 1'b0;
        end 
        else if(ascii_tmp_vld)begin 
            ascii_data <= {ascii_sign,ascii_tmp[47:32],ascii_dot,ascii_tmp[31:0],8'ha1,8'he6,8'h0a};
            ascii_data_vld <= 1'b1;
        end 
        else begin 
            ascii_data <= ascii_data;
            ascii_data_vld <= 1'b0;
        end 
    end

    assign ascii_sign = dec_temp_sign?8'h2d:8'h2b;      //符号的ascii码
    assign ascii_dot  = 8'h2e;   //小数点的ascii码

//seg_data
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            seg_data <= 0;
            seg_data_vld <= 1'b0;
        end 
        else if(seg_enable & bcd_tmp_vld)begin 
            seg_data <= {bcd_sign,bcd_tmp[23:4]};
            seg_data_vld <= 1'b1;
        end 
        else begin 
            seg_data <= seg_data ;
            seg_data_vld <= 1'b0;
        end 
    end

    assign disp_data = seg_data;
    assign disp_data_vld = seg_data_vld;

    assign bcd_sign = dec_temp_sign?4'ha:4'hb;

//tx_data
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            tx_data <= 0;
            tx_data_vld <= 1'b0;
        end 
        else begin 
            tx_data <= rd_dout;
            tx_data_vld <= rd_req;
        end 
    end

    assign ascii_dout     = tx_data;
    assign ascii_dout_vld = tx_data_vld;

//fifo
    //fifo_rd_flag
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            fifo_rd_flag <= 0;
        end 
        else begin 
            fifo_rd_flag <= empty == 1'b0;
        end  
    end

//rd_req    
    always @(*)begin 
      if(fifo_rd_flag & uart_tx_busy == 1'b0)begin 
            rd_req <= 1'b1;
        end 
        else begin 
            rd_req <= 1'b0;
        end 
    end

控制模块例化

 ascii2hex u_ascii2hex(      //ascii码转十六进制
    /*input             */.clk          (clk            ),
    /*input             */.rst_n        (rst_n          ),
    /*input     [7:0]   */.ascii_din    (ascii_din      ),
    /*input             */.ascii_din_vld(ascii_din_vld  ),
    /*output    [7:0]   */.hex_dout     (cmd_byte       ),
    /*output            */.hex_dout_vld (cmd_byte_vld   )
    );

    cmd_analy u_cmd_analy(  //命令解析模块
    /*input             */.clk           (clk           ),
    /*input             */.rst_n         (rst_n         ),
    /*input    [7:0]    */.hex_din       (cmd_byte      ),
    /*input             */.hex_din_vld   (cmd_byte_vld  ),

    /*output            */.sensor_enable (sensor_enable ),
    /*output            */.seg_enable    (seg_enable    ),
    /*output            */.uart_enable   (uart_enable   )
    );

    binary2bcd#(.DIN_W(21),.DOUT_W(25)) u_binary2bcd(   //将十进制温度值转换为BCD码格式的数据
    /*input                         */.clk         (clk                 ),//时钟
    /*input                         */.rst_n       (rst_n               ),//复位
    /*input                         */.en          (bcd_en              ),
    /*input          [DIN_W-1:0]    */.binary_din  (dec_tmp_data[20:0]  ),//输入二进制数据
    //输出信号定义
    /*output    reg  [DOUT_W-1:0]   */.bcd_dout    (bcd_tmp             ),   //输出BCD码数据
    /*output    reg                 */.bcd_dout_vld(bcd_tmp_vld         )
    );

    hex2ascii u_hex2ascii(      //将BCD码格式的温度值转换为ASCII码,输出给uart_tx模块
    /*input                         */.clk              (clk                ),//时钟
    /*input                         */.rst_n            (rst_n              ),//复位
    /*input     [23:0]              */.hex_din          (hex_data           ),//hex输入
    /*input                         */.hex_din_vld      (hex_data_vld       ),

    /*output    [47:0]              */.ascii_dout       (ascii_tmp          ),
    /*output                        */.ascii_dout_vld   (ascii_tmp_vld      )   
    );

    //fifo例化
    fifo	u_fifo (
    .aclr   (~rst_n     ), 
	.clock  (clk        ),
	.data   (wr_din     ),
	.rdreq  (rd_req     ),
	.wrreq  (wr_req     ),
	.empty  (empty      ),
	.full   (full       ),
	.q      (rd_dout    )
	);

3、顶层

顶层模块例化

uart_rx u_uart_rx(
    /*input             */.clk         (clk           ),
    /*input             */.rst_n       (rst_n         ),
    /*input             */.uart_rxd    (uart_rxd      ),
    /*output    [7:0]   */.rx_data     (rx_byte       ),
    /*output            */.rx_data_vld (rx_byte_vld   )
    );


    ds18b20_driver u_ds18b20_driver(
    /*input             */.clk          (clk          ),
    /*input             */.rst_n        (rst_n        ),
    /*input             */.enable       (sensor_enable),//传感器开关信号
    /*input             */.dq_in        (dq_in        ),//传感器输入
    /*output            */.dq_out       (dq_out       ),//传感器输出
    /*output            */.dq_out_en    (dq_out_en    ),//传感器输出使能
    /*output            */.temp_sign    (temp_sign    ),//温度值符号位 0:正 1:负温
    /*output    [23:0]  */.temp_out     (dec_temp     ),//十进制格式的温度值
    /*output            */.temp_out_vld (dec_temp_vld ) //温度值有效标志信号    
    );

    controler u_controler(
    /*input               */.clk            (clk            ),
    /*input               */.rst_n          (rst_n          ),
    /*input     [7:0]     */.ascii_din      (rx_byte        ),
    /*input               */.ascii_din_vld  (rx_byte_vld    ),
    /*input               */.dec_temp_sign  (temp_sign      ),
    /*input     [23:0]    */.dec_tmp_din    (dec_temp       ),
    /*input               */.dec_tmp_din_vld(dec_temp_vld   ),
    /*input               */.uart_tx_busy   (tx_busy        ),

    /*output              */.sensor_enable  (sensor_enable  ),//输出给ds18b20驱动模块
    /*output              */.disp_enable    (disp_enable    ),
    /*output    [23:0]    */.disp_data      (disp_data      ),//输出给数码管驱动模块显示
    /*output              */.disp_data_vld  (disp_data_vld  ),   
    /*output    [7:0]     */.ascii_dout     (ascii_dout     ),//输出给串口发送模块发送
    /*output              */.ascii_dout_vld (ascii_dout_vld )

    );

    uart_tx u_uart_tx(
    /*input               */.clk         (clk           ),
    /*input               */.rst_n       (rst_n         ),
    /*input               */.tx_req      (ascii_dout_vld),
    /*input       [7:0]   */.tx_din      (ascii_dout    ),
    /*output              */.tx_busy     (tx_busy       ),//1:表示忙 发送数据 0:表示非忙
    /*output              */.tx_dout     (uart_txd      )
    );

    seg_driver u_seg_driver(
    /*input               */.clk        (clk           ),
    /*input               */.rst_n      (rst_n         ),
    /*input               */.seg_enable (disp_enable   ),
    /*input     [23:0]    */.din        (disp_data     ),
    /*input               */.din_vld    (disp_data_vld ),
    /*output    [5:0]     */.sel        (sel           ),//片选信号
    /*output    [7:0]     */.dig        (dig           ) //段选信号
);

五、参考资料

DS18B20温度采集报警系统,原理及汇编、C语言实现
DS18B20内部结构及功能
DS18B20百度百科
1-Wire总线数字温度传感器DS18B20原理及应用.pdf
三态门介绍

你可能感兴趣的:(FPGA,verilog,ds18b20,传感器)