基于DS18B20的温度检测

打印 上一主题 下一主题

主题 1862|帖子 1862|积分 5586

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
媒介

        DS18B20是DALLAS半导体公司生产的单总线数字温度传感器,其输出的是数字信号,具有体积小,功耗低,抗干扰能力强,精度高的特点。

        温度范围-55摄氏度至+125摄氏度,在-10摄氏度至+85摄氏度可以到达不超过 0.5摄氏度的误差。单端口节省FPGA接口资源。传感器内部含EEPROM内部存储温度阈值,测量分辨率,体系掉电保护数据。

正文

一、基于DS18B20的温度检测

        1.项目需求

实行目标:基于ds18b20数据温度传感器,完成基于FPGA的温度计设计。(数码管显示)
        2.技能介绍

        每个DS18B20的片内ROM都存有一个独一无二的64位编码。在该ROM编码的低8位生存有DS18B20的分类编码:28h;中间的48位是独一无二的序列号;最高8位是前面56位的CRC循环冗余校验码 (CRC=X8+X5+X4+1)。
由于每个DS18B20的序列号都不一样,以是一条总线上可以控制多个DS18B20。

        温度测量方法:DS18B20中的温度传感器可完成对温度的测量,他的温度转换精度用户可自定义为9、10、11、12位,精度分别为0.5℃、0.25℃、0.125℃、0.0625℃分辨率。
符号标记位(S)(5位)表示温度的正负极性:若S=0,则为正数;若S=1,则为负数。
温度数据正数源码输出,负数补码输出(计算温度时求补码)输出二进制数*温度精度=当前温度


        高速缓冲器中第5个字节即为配置寄存器,通过修改R1,R2的值来配置DS18B20的分辨率。TM(0,工作模式,1测试模式),默认12位宽。


        DS18B20实现温度转换
主机控制DS18B20完成温度转换必须经过三个步骤:每一次读写之前都要对DS18B20进行 初始化操作,初始化乐成后发送一条ROM下令,末了发送RAM下令,这样才能对DS18B20进行预定的操作。
1.初始化:单总线上的全部操作都必须以初始化为开始。初始化序列由总线上的主装备发出的复位脉冲以及紧跟着从装备回应的存在脉冲构成。该存在脉冲是让总线主装备知道DS18B20在总线上并准备好运行。
2.ROM下令:搜索ROM[F0h](识别从机)、读ROM[33h](数据总线存在一个从机)、匹配ROM[55h](多从机选定从机工作)、跳过ROM[CCh]、警报搜索ROM[ECh]。
3.RAM下令:温度转换[44h](单次温度转换)、写入暂存器[4Eh](向传感器写入温度阈值与分辨率)、读取高速缓存器[BEh]、复制高速缓存器[48H1]、召回EEPROM[B8h]、读取供电模式[B4h]。(0寄存电容,1外部供电)


        数据传输过程:与DS18B20全部的通信都是由初始化开始的,初始化由主装备发出的复位脉冲及从装备响应的存在脉冲构成。主装备发出480-960us的低电平脉冲,之后释放总线,紧接着主装备进行480us的总线检测。总线有低电平出现表示总线上的器件应答。从装备进行480-960us的应答检测,检测到后进行数据输出到数据总线。

写时序:主装备通过写时序将下令写入DS18B20中,写时序模式有1,0两种模式。数据总线由高电平拉至低电平常进入写时序。 

读时序:发送读取供电模式[B4h]或读高速缓存区[BEh]下令时,实时生成读时序在读时隙从装备才可以向主装备传输数据。

这里利用状态机,简便实行代码。
        3.顶层架构


        4.端口描述

clk时钟(50Mhz)
rst_n复位信号(低电平有效)
dp数据总线
[2:0]sel位选信号
[7:0]seg段选信号
二、代码验证

数据处理模块
  1. module ds18b20_data(
  2.         input                                 clk                        ,
  3.         input                                 rst_n                        ,
  4.         inout                                        dp                                ,//数据总线
  5.        
  6.         output wire[19:0]        data_out                ,//读取到的数据
  7.         output reg                        data_flag                 //符号位
  8. );
  9. //0011_0011;跳过ROM命令        CCh
  10. //0010_0010;温度转换命令        44h
  11. //1111_0010;写入暂存器命令        4Eh
  12. //0111_1101;读温度命令                BEh
  13. parameter         date = 3'd1,//初始化
  14.                                 wier = 3'd2,//写命令
  15.                                 dend = 3'd3,//等待转换
  16.                                 datt = 3'd4,//再次初始化
  17.                                 romx = 3'd5,//Rom功能命令
  18.                                 duqu = 3'd6;//数据读取
  19. parameter         cch = 16'h44cc,
  20.                                 beh = 16'hbecc;
  21.                                
  22.                                
  23. reg [4:0]cnt_1ns;//1ns计数器
  24. reg clk_1ns;//1ns时钟
  25. reg [19:0]cnt_us;//us计数器
  26. reg flag_us;//存在脉冲有效信号
  27. reg[2:0]stater;//状态机状态
  28. reg[3:0]bit_cnt;//bit计数器
  29. reg[15:0]data_temp;//存储接收的温度数据
  30. reg[19:0]data_temp_t;//温度数据进行正负判断,小数点位统一,((数据*625(精度)/10000)=摄氏度)*1000=数码管数据,反码源码转换
  31. reg dp_en;//输出为1,输入为0
  32. reg dp_out;//输入0,输出为操作命令
  33. assign dp = (dp_en ==1'b1)? dp_out:1'bz;
  34. always@(posedge clk_1ns,negedge rst_n) //符号位
  35. begin
  36.         if(rst_n == 0)
  37.                 data_flag <= 1'b0;
  38.         else
  39.                 if((stater == duqu)&&(bit_cnt == 4'd15)&&(cnt_us == 20'd60)&&(data_temp[15]== 1'b0))
  40.                         data_flag <= 1'b0;
  41.                 else       
  42.                         if((stater == duqu)&&(bit_cnt == 4'd15)&&(cnt_us == 20'd60)&&(data_temp[15]== 1'b1))
  43.                                 data_flag <= 1'b1;
  44.                         else
  45.                                 data_flag <= data_flag;
  46. end
  47. always@(posedge clk,negedge rst_n)//1ns计数器使能模块
  48. begin
  49.         if(rst_n == 0)
  50.                 cnt_1ns <= 5'd0;
  51.         else
  52.                 if(cnt_1ns == 5'd24)
  53.                         cnt_1ns <= 5'd0;
  54.                 else
  55.                         cnt_1ns <= cnt_1ns + 5'd1;
  56. end
  57. always@(posedge clk,negedge rst_n)//1ns时钟
  58. begin
  59.         if(rst_n == 0)
  60.                 clk_1ns <= 1'b0;
  61.         else
  62.                 if(cnt_1ns == 5'd24)
  63.                         clk_1ns <= ~clk_1ns;
  64.                 else
  65.                         clk_1ns <= clk_1ns;
  66. end
  67. always@(posedge clk_1ns,negedge rst_n)//us计数器使能
  68. begin
  69.         if(rst_n == 0)
  70.                 cnt_us <= 20'd0;
  71.         else
  72.                 if((((stater == date)||(stater == datt))&&(cnt_us == 20'd999))||(((stater == wier)||(stater == romx)||(stater == duqu))&&(cnt_us == 20'd64))||((stater == dend)&&(cnt_us == 20'd750_000)))
  73.                         cnt_us <= 20'd0;
  74.                 else
  75.                         cnt_us <= cnt_us + 20'd1;
  76. end               
  77.        
  78. always@(posedge clk_1ns,negedge rst_n)//存在脉冲有效
  79. begin
  80.         if(rst_n == 0)
  81.                 flag_us <= 1'b0;
  82.         else
  83.                 if((((stater == date)||(stater == datt))&&(cnt_us == 20'd570)&&(dp == 1'b0)))
  84.                         flag_us <= 1'b1;
  85.                 else
  86.                         if(((stater == date)||(stater == datt))&&(cnt_us == 20'd999))
  87.                                 flag_us <= 1'b0;
  88.                         else
  89.                                 flag_us <= flag_us;
  90. end
  91. always@(posedge clk_1ns,negedge rst_n)//bit计数器使能
  92. begin
  93.         if(rst_n == 0)
  94.                 bit_cnt <= 4'd0;
  95.         else
  96.                 if(((stater == wier)||(stater == romx)||(stater == duqu))&&(bit_cnt == 4'd15)&&(cnt_us == 20'd64))
  97.                         bit_cnt <= 4'd0;
  98.                 else
  99.                         if(((stater == wier)||(stater == romx)||(stater == duqu))&&(cnt_us == 20'd64))
  100.                                 bit_cnt <= bit_cnt + 4'd1;
  101.                         else
  102.                                 bit_cnt <= bit_cnt;
  103. end
  104. always@(posedge clk_1ns,negedge rst_n)//存储接收的温度数据
  105. begin
  106.         if(rst_n == 0)
  107.                 data_temp <= 16'd0;
  108.         else
  109.                 if((stater == duqu)&&(cnt_us == 20'd13))
  110.                         data_temp <= {dp,data_temp[15:1]};
  111.                 else
  112.                         data_temp <= data_temp;
  113. end
  114. always@(posedge clk_1ns,negedge rst_n)//温度数据进行正负判断,小数点位统一,((数据*625(精度)/10000)=摄氏度)*1000=数码管数据,反码源码转换
  115. begin
  116.         if(rst_n == 0)
  117.                 data_temp_t <= 20'd0;
  118.         else
  119.                 if((stater == duqu)&&(bit_cnt == 4'd15)&&(cnt_us == 20'd60)&&(data_temp[15]== 1'b0))
  120.                         data_temp_t <= data_temp[11:0];
  121.                 else
  122.                         if(((stater == duqu)&&(bit_cnt == 4'd15)&&(cnt_us == 20'd60)&&(data_temp[15]== 1'b0)))
  123.                                 data_temp_t <= ~data_temp[11:0] + 1'b1;
  124.                         else
  125.                                 data_temp_t <= data_temp_t;
  126. end
  127.        
  128. assign data_out = (data_temp_t * 625)        /10;
  129.        
  130. always@(posedge clk_1ns,negedge rst_n)//状态机状态跳转条件
  131. begin
  132.         if(rst_n == 0)
  133.                 stater <= date;
  134.         else       
  135.                 case(stater)
  136.                         date        :        if((cnt_us == 20'd999) && (flag_us == 1'b1))
  137.                                                         stater <= wier;
  138.                                                 else
  139.                                                         stater <= date;
  140.                    wier        :        if((bit_cnt == 4'd15) &&(cnt_us == 20'd64))
  141.                                                         stater <= dend;
  142.                                                 else
  143.                                                         stater <= wier;
  144.                    dend        :        if(cnt_us == 20'd750_000)
  145.                                                         stater <= datt;
  146.                                                 else
  147.                                                         stater <= dend;
  148.                    datt        :        if((cnt_us == 20'd999) && (flag_us == 1'b1))
  149.                                                         stater <= romx;
  150.                                                 else
  151.                                                         stater <= datt;
  152.                    romx        :        if((bit_cnt == 4'd15) &&(cnt_us == 20'd64))
  153.                                                         stater <= duqu;
  154.                                                 else
  155.                                                         stater <= romx;
  156.                    duqu        :        if((bit_cnt == 4'd15) &&(cnt_us == 20'd64))
  157.                                                         stater <= date;
  158.                                                 else
  159.                                                         stater <= duqu;
  160.                         default :stater <= date;
  161.                 endcase
  162. end
  163.                
  164. always@(posedge clk_1ns,negedge rst_n)//输出为1,输入为0
  165. begin                             //输入0,输出为操作命令
  166.         if(rst_n == 0)
  167.                 begin
  168.                         dp_en <= 1'b0;
  169.                         dp_out <= 1'b0;
  170.                 end
  171.         else
  172.                 case(stater)
  173.                         date        :        if(cnt_us <499)
  174.                                                         begin
  175.                                                                 dp_en  <= 1'b1;
  176.                                                                 dp_out <= 1'b0;
  177.                                                         end
  178.                                                 else
  179.                                                         begin
  180.                                                                 dp_en  <= 1'b0;
  181.                                                                 dp_out <= 1'b0;
  182.                                                         end
  183.                    wier        :        if(cnt_us >62)
  184.                                                         begin
  185.                                                                 dp_en  <= 1'b0;
  186.                                                                 dp_out <= 1'b0;
  187.                                                         end
  188.                                                 else
  189.                                                         if(cnt_us <= 1)
  190.                                                                 begin
  191.                                                                         dp_en  <= 1'b1;
  192.                                                                         dp_out <= 1'b0;
  193.                                                                 end
  194.                                                         else
  195.                                                                 if(beh[bit_cnt] == 1'b0)
  196.                                                                         begin
  197.                                                                                 dp_en  <= 1'b1;
  198.                                                                                 dp_out <= 1'b0;
  199.                                                                         end
  200.                                                                 else
  201.                                                                         if(beh[bit_cnt] == 1'b1)
  202.                                                                                 begin
  203.                                                                                         dp_en  <= 1'b0;
  204.                                                                                         dp_out <= 1'b0;
  205.                                                                                 end
  206.                    dend        :                begin
  207.                                                                 dp_en  <= 1'b1;
  208.                                                                 dp_out <= 1'b1;
  209.                                                         end       
  210.                    datt        :        if(cnt_us <499)
  211.                                                         begin
  212.                                                                 dp_en  <= 1'b1;
  213.                                                                 dp_out <= 1'b0;
  214.                                                         end
  215.                                                 else
  216.                                                         begin
  217.                                                                 dp_en  <= 1'b0;
  218.                                                                 dp_out <= 1'b0;
  219.                                                         end       
  220.                    romx        :        if(cnt_us >62)
  221.                                                         begin
  222.                                                                 dp_en  <= 1'b0;
  223.                                                                 dp_out <= 1'b0;
  224.                                                         end
  225.                                                 else
  226.                                                         if(cnt_us <= 1)
  227.                                                                 begin
  228.                                                                         dp_en  <= 1'b1;
  229.                                                                         dp_out <= 1'b0;
  230.                                                                 end
  231.                                                         else
  232.                                                                 if(cch[bit_cnt] == 1'b0)
  233.                                                                         begin
  234.                                                                                 dp_en  <= 1'b1;
  235.                                                                                 dp_out <= 1'b0;
  236.                                                                         end
  237.                                                                 else
  238.                                                                         if(cch[bit_cnt] == 1'b1)
  239.                                                                                 begin
  240.                                                                                         dp_en  <= 1'b0;
  241.                                                                                         dp_out <= 1'b0;
  242.                                                                                 end
  243.                         duqu        :        if(cnt_us <= 1)
  244.                                                         begin
  245.                                                                 dp_en  <= 1'b1;
  246.                                                                 dp_out <= 1'b0;
  247.                                                         end
  248.                                                 else
  249.                                                         begin
  250.                                                                 dp_en  <= 1'b0;
  251.                                                                 dp_out <= 1'b0;
  252.                                                         end       
  253.                 default :        begin
  254.                                                         dp_en  <= 1'b0;
  255.                                                         dp_out <= 1'b0;
  256.                                                 end
  257.                 endcase
  258. end       
  259.                        
  260. endmodule
复制代码
数码管显示模块
  1. module shu_ma_g_MAX(
  2.         input                                 clk                ,
  3.         input                                        rst_n                ,
  4.         input        [19:0]                data                ,//数据10进制
  5.         input [ 5:0]                point                ,//小数点位
  6.         input                                        signe                ,//正负号位
  7.         input                                        seg_en        ,//数码管使能
  8.        
  9.         output reg[2:0]        sel                ,
  10.         output reg[7:0]        seg                
  11. );
  12. parameter cnt_1ms_max = 16'd49999;
  13. wire[3:0] data1                                ;//数码管数据
  14. wire[3:0] data2                                ;//数码管数据
  15. wire[3:0] data3                                ;//数码管数据
  16. wire[3:0] data4                                ;//数码管数据
  17. wire[3:0] data5                                ;//数码管数据
  18. wire[3:0] data6                                ;//数码管数据
  19. reg[23:0]data_reg                        ;//寄存显示数据
  20. reg[15:0]cnt_1ms                        ;//1ms计数器
  21. reg                cnt_1ms_flag        ;
  22. reg[2:0]        cnt_sel                        ;//扫描周期计数器
  23. reg[3:0] data_zhan                ;//数码管显示暂存数据
  24. reg                 point_flag                ;//小数点使能信号
  25. reg[2:0] sel_reg                        ;//暂存输出
  26. always@(posedge clk,negedge rst_n)//判断符号位
  27. begin
  28.         if(rst_n == 0)
  29.                 data_reg <= 24'b0;
  30.         else
  31.                 if((data6)||(point[5]))
  32.                         data_reg <= {data6,data5,data4,data3,data2,data1};
  33.                 else
  34.                         if(((data5)||(point[4]))&&(signe == 1'b1))//最高位为符号位011-111
  35.                                 data_reg <= {4'd10,data5,data4,data3,data2,data1};
  36.                         else
  37.                                 if(((data5)||(point[4]))&&(signe == 1'b0))
  38.                                         data_reg <= {4'd11,data5,data4,data3,data2,data1};
  39.                                 else
  40.                                        
  41.                         if(((data4)||(point[3]))&&(signe == 1'b1))//次高位为符号位001-111
  42.                                 data_reg <= {4'd11,4'd10,data4,data3,data2,data1};
  43.                         else
  44.                                 if(((data4)||(point[3]))&&(signe == 1'b0))
  45.                                         data_reg <= {4'd11,4'd11,data4,data3,data2,data1};
  46.                                 else
  47.                                
  48.                         if(((data3)||(point[2]))&&(signe == 1'b1))//次次高位为符号位000-111
  49.                                 data_reg <= {4'd11,4'd11,4'd10,data3,data2,data1};
  50.                         else
  51.                                 if(((data3)||(point[2]))&&(signe == 1'b0))
  52.                                         data_reg <= {4'd11,4'd11,4'd11,data3,data2,data1};
  53.                                 else
  54.                                
  55.                         if(((data2)||(point[1]))&&(signe == 1'b1))//次次次高位为符号位000-011
  56.                                 data_reg <= {4'd11,4'd11,4'd11,4'd10,data2,data1};
  57.                         else
  58.                                 if(((data2)||(point[1]))&&(signe == 1'b0))
  59.                                         data_reg <= {4'd11,4'd11,4'd11,4'd11,data2,data1};
  60.                                 else
  61.                                                                                                
  62.                         if(((data1)||(point[0]))&&(signe == 1'b1))//次次次次高位为符号位000-001
  63.                                 data_reg <= {4'd11,4'd11,4'd11,4'd11,4'd10,data1};
  64.                         else
  65.                                 data_reg <= {4'd11,4'd11,4'd11,4'd11,4'd11,data1};
  66.                                                
  67. end
  68. always@(posedge clk,negedge rst_n)        //计数器驱动模块
  69. begin
  70.         if(rst_n == 0)
  71.                 cnt_1ms <= 16'd0;
  72.         else
  73.                 if(cnt_1ms == cnt_1ms_max)
  74.                         cnt_1ms <= 16'd0;
  75.                 else
  76.                         cnt_1ms <= cnt_1ms + 16'd1;
  77.                
  78. end
  79. always@(posedge clk,negedge rst_n)//1ms标志信号
  80. begin
  81.         if(rst_n == 0)
  82.                 cnt_1ms_flag <= 1'b0;
  83.         else
  84.                 if(cnt_1ms == cnt_1ms_max)
  85.                         cnt_1ms_flag <= 1'b1;
  86.                 else
  87.                         cnt_1ms_flag <= 1'b0;
  88. end
  89. always@(posedge clk,negedge rst_n)//扫描周期计数器使能
  90. begin
  91.         if(rst_n == 0)
  92.                 cnt_sel <= 3'd0;
  93.         else
  94.                 if((cnt_sel == 3'd5)&&(cnt_1ms_flag <= 1'b1))
  95.                         cnt_sel <= 3'd0;
  96.                 else
  97.                         if(cnt_1ms_flag <= 1'b1)
  98.                                 cnt_sel <= cnt_sel + 3'd1;
  99.                         else
  100.                                 cnt_sel <= cnt_sel;
  101. end
  102.                
  103. always@(posedge clk,negedge rst_n)//暂存输出
  104. begin
  105.         if(rst_n == 0)
  106.                 sel_reg <= 3'd0;
  107.         else
  108.                 if((cnt_sel == 3'd0)&&(cnt_1ms_flag <= 1'b1))
  109.                         sel_reg <= 3'd0;
  110.                 else
  111.                         if(cnt_1ms_flag <= 1'b1)
  112.                                 sel_reg <= sel_reg + 1'd1;
  113.                         else
  114.                                 sel_reg <= sel_reg;
  115. end
  116. always@(posedge clk,negedge rst_n)//段码数据传递
  117. begin
  118.         if(rst_n == 0)
  119.                 data_zhan <= 4'd0;
  120.         else
  121.                 if((seg_en == 1'b1)&&(cnt_1ms_flag <= 1'b1))
  122.                         case(cnt_sel)
  123.                                 3'd0 : data_zhan <= data_reg[3:0];
  124.                                 3'd1 : data_zhan <= data_reg[7:4];
  125.                                 3'd2 : data_zhan <= data_reg[11:8];
  126.                                 3'd3 : data_zhan <= data_reg[15:12];
  127.                                 3'd4 : data_zhan <= data_reg[19:16];
  128.                                 3'd5 : data_zhan <= data_reg[23:20];
  129.                         default : data_zhan <= 4'd0;
  130.                         endcase
  131.                 else
  132.                         data_zhan <= data_zhan;
  133. end
  134. always@(posedge clk,negedge rst_n)//小数点点亮
  135. begin
  136.         if(rst_n == 0)
  137.                 point_flag <= 1'b0;
  138.         else
  139.                 if(cnt_1ms_flag <= 1'b1)
  140.                         point_flag <= ~point[cnt_sel];
  141.                 else
  142.                         point_flag <= point_flag;
  143. end
  144.                                                        
  145. always@(posedge clk,negedge rst_n)//段码数值判断并输出
  146. begin
  147.         if(rst_n == 0)               
  148.                 seg <= 8'b1111_1111;//0
  149.         else
  150.                 case(data_zhan)
  151.                         4'd0 : seg <= {point_flag,7'd100_0000};//0
  152.                         4'd1 : seg <= {point_flag,7'd100_0000};//1
  153.                         4'd2 : seg <= {point_flag,7'd100_0000};//2
  154.                         4'd3 : seg <= {point_flag,7'd100_0000};//3
  155.                         4'd4 : seg <= {point_flag,7'd100_0000};//4
  156.                         4'd5 : seg <= {point_flag,7'd100_0000};//5
  157.                         4'd6 : seg <= {point_flag,7'd100_0000};//6
  158.                         4'd7 : seg <= {point_flag,7'd100_0000};//7
  159.                         4'd8 : seg <= {point_flag,7'd100_0000};//8
  160.                         4'd9 : seg <= {point_flag,7'd100_0000};//9
  161.                        
  162.                         4'd10: seg <= 8'b1011_1111;//-
  163.                         4'd11: seg <= 8'b1111_1111;//熄灭
  164. /*                       
  165.                         4'd10: seg <= {point_flag,7'd100_0000};//A
  166.                         4'd11: seg <= {point_flag,7'd100_0000};//b
  167.                         4'd12 : seg <= {point_flag,7'd100_0000};//C
  168.                         4'd13 : seg <= {point_flag,7'd100_0000};//d
  169.                         4'd14 : seg <= {point_flag,7'd100_0000};//E
  170.                         4'd15 : seg <= {point_flag,7'd100_0000};//F
  171. */
  172.                         default : seg <= 8'd1100_0000;
  173.                 endcase
  174. end
  175. always@(posedge clk,negedge rst_n)
  176. begin
  177.         if(rst_n == 0)               
  178.                 sel <= 3'd0;//0                       
  179.         else
  180.                 sel <= sel_reg;
  181. end
  182. er_bcd er_bcd_inst(
  183.         .clk        (clk        ),
  184.         .rst_n(rst_n),
  185.         .data        (data        ),//数据10进制
  186.        
  187.         .data1(data1),
  188.         .data2(data2),
  189.         .data3(data3),
  190.         .data4(data4),
  191.         .data5(data5),
  192.         .data6(data6)                         
  193. );       
  194.                
  195. endmodule
复制代码
数码管辅助模块
  1. module er_bcd(
  2.         input                                 clk                ,
  3.         input                                        rst_n                ,
  4.         input        [19:0]                data                ,//数据10进制
  5.        
  6.         output reg[3:0]        data1                ,//bcd码
  7.         output reg[3:0]        data2                ,//bcd码
  8.         output reg[3:0]        data3                ,//bcd码
  9.         output reg[3:0]        data4                ,//bcd码
  10.         output reg[3:0]        data5                ,//bcd码
  11.         output reg[3:0]        data6                 //bcd码       
  12. );
  13. reg [4 :0]cnt_shift        ;
  14. reg [43:0]data_shift        ;//暂存转换后的BCD码
  15. reg                  shift_flag        ;
  16. always@(posedge clk, negedge rst_n)//记时钟21次后清零,大约20ns*20=400ns进行一次数据转码并输出
  17. begin
  18.         if(rst_n == 0)
  19.                 cnt_shift <= 5'd0;
  20.         else
  21.                 if((cnt_shift == 5'd21)&&(shift_flag == 1'b1))//计数清零
  22.                         cnt_shift <= 5'd0;
  23.                 else
  24.                         if(shift_flag == 1'b1)
  25.                                 cnt_shift <= cnt_shift + 5'd1;
  26.                         else
  27.                                 cnt_shift <= cnt_shift;
  28. end
  29. always@(posedge clk, negedge rst_n)
  30. begin
  31.         if(rst_n == 0)
  32.                 data_shift <= 43'd0;
  33.         else
  34.                 if(cnt_shift == 5'd0)
  35.                         data_shift <= {24'd0,data};
  36.                 else
  37.                         if((cnt_shift <= 20)&&(shift_flag ==  1'b0))
  38.                                 begin
  39.                                 data_shift[23:20] <= (data_shift[23:20] > 4)?(data_shift[23:20] + 2'd3):(data_shift[23:20]);//大四加三
  40.                                 data_shift[27:24] <= (data_shift[27:24] > 4)?(data_shift[27:24] + 2'd3):(data_shift[27:24]);//大四加三
  41.                                 data_shift[31:28] <= (data_shift[31:28] > 4)?(data_shift[31:28] + 2'd3):(data_shift[31:28]);//大四加三
  42.                                 data_shift[35:32] <= (data_shift[35:32] > 4)?(data_shift[35:32] + 2'd3):(data_shift[35:32]);//大四加三
  43.                                 data_shift[39:36] <= (data_shift[39:36] > 4)?(data_shift[39:36] + 2'd3):(data_shift[39:36]);//大四加三
  44.                                 data_shift[43:40] <= (data_shift[43:40] > 4)?(data_shift[43:40] + 2'd3):(data_shift[43:40]);//大四加三
  45.                                 end
  46.                         else
  47.                                 if((cnt_shift <= 20)&&(shift_flag ==  1'b1))
  48.                                         data_shift <= data_shift << 1;
  49.                                 else
  50.                                         data_shift <= data_shift;
  51. end
  52. always@(posedge clk, negedge rst_n)//相对于时钟信号,0时数据计算,1时进行数据移位
  53. begin
  54.         if(rst_n == 0)
  55.                 shift_flag <= 1'b0;
  56.         else
  57.                 shift_flag = ~shift_flag;
  58. end
  59. always@(posedge clk, negedge rst_n)
  60. begin
  61.         if(rst_n == 0)
  62.                 begin
  63.                         data1   <=  4'b0;
  64.                    data2   <=  4'b0;
  65.                    data3   <=  4'b0;
  66.                    data4   <=  4'b0;
  67.                    data5   <=  4'b0;
  68.                    data6   <=  4'b0;
  69.                 end
  70.         else        if(cnt_shift == 5'd21)
  71.                 begin
  72.                         data1   <=  data_shift[23:20];//分段传递
  73.                    data2   <=  data_shift[27:24];//分段传递
  74.                    data3   <=  data_shift[31:28];//分段传递
  75.                    data4   <=  data_shift[35:32];//分段传递
  76.                    data5   <=  data_shift[39:36];//分段传递
  77.                    data6   <=  data_shift[43:40];//分段传递
  78.                 end
  79. end
  80. endmodule
复制代码
顶层连线
  1. module ds18b20_ctrl(
  2.         input                                 clk                        ,
  3.         input                                 rst_n                        ,
  4.         inout                                        dp                                ,
  5.        
  6.         output [2:0]                sel                        ,
  7.         output [7:0]                seg                                
  8. );
  9. wire data_flag;
  10. wire [19:0]data;
  11. ds18b20_data ds18b20_data(
  12.         .clk                        (clk                        ),
  13.         .rst_n                (rst_n                ),
  14.         .dp                        (dp                        ),   
  15.          
  16.         .data_out        (data                        ),
  17.         .data_flag        (data_flag        )
  18. );
  19. shu_ma_g_MAX shu_ma_g_MAX(
  20.         .clk                (clk                        )        ,
  21.         .rst_n        (rst_n                )        ,
  22.         .data                (data                        )        ,//数据10进制
  23.         .point        (6'b001000        )        ,//小数点位
  24.         .signe        (data_flag        )        ,//正负号位
  25.         .seg_en        (1'b1                        )        ,//数码管使能
  26.    
  27.         .sel                (sel                        )        ,
  28.         .seg                 (seg                         )       
  29. );
  30. endmodule
复制代码
三、仿真验证


这里进行初始化,写下令跳过ROM下令,状态跳转到等待状态

经过480us后存在脉冲有效信号拉高,证实识别到传感器

数据开始从总线上读入

这里可以看到,有数据输出,实行乐成

参考资料

DS18B20

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

麻花痒

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表