102|3

22

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

温度传感器只有第一次采集的是准的是怎么回事? [复制链接]

    使用verilog写了一个P3T1750DP温度传感器的驱动代码,但是测量出来的温度只有上电后第一次采集的是准的,后面采集回来的都是不准了。工程代码如下:

top.v

module top(
    input               pl_ref_clk_100m_p   ,            
    input               pl_ref_clk_100m_n   , 
    
    output              ex_i2c_scl          ,
    inout               ex_i2c_sda
    );
    wire                p3t1750dp_en;
    wire                clk_100m;
    wire                rst_n;
    wire                p3t1750dp_done;
    wire [15:0]         temp_out;
    wire [7:0]          p3t1750dp_addr,p3t1750dp_pointer;

vio_0 vio_0 (
  .clk(clk_100m),                // input wire clk
  .probe_out0(p3t1750dp_en),  // output wire [0 : 0] probe_out0
  .probe_out1(p3t1750dp_addr),  // output wire [7 : 0] probe_out1
  .probe_out2(p3t1750dp_pointer),  // output wire [7 : 0] probe_out2
  .probe_out3(rst_n)  // output wire [0 : 0] probe_out2
);
p3t1750dp p3t1750dp(
    .clk_100m       (clk_100m       ),
    .rst_n          (rst_n          ),
    
    .p3t1750dp_en   (p3t1750dp_en   ),
    .p3t1750dp_addr (p3t1750dp_addr ),
    .p3t1750dp_pointer(p3t1750dp_pointer),
    .scl            (ex_i2c_scl            ),
    .sda            (ex_i2c_sda            ),
    .p3t1750dp_done (p3t1750dp_done ),
    .temp_out       (temp_out       )
);
IBUFDS clk_100m_ibufds(
    .O	(clk_100m            ),
    .I	(pl_ref_clk_100m_p   ),
    .IB	(pl_ref_clk_100m_n   )
);
endmodule

p3t1750dp.v模块参照官方的时序Figure 19. Read register including pointer byte (2-byte data)写的。

 

module p3t1750dp(
    input               clk_100m        ,
    input               rst_n           ,
    
    input               p3t1750dp_en    ,
    input  [7:0]        p3t1750dp_addr  ,
    input  [7:0]        p3t1750dp_pointer,
    (* MARK_DEBUG="true" *)output              scl             ,
    inout               sda             ,
    (* MARK_DEBUG="true" *)output              p3t1750dp_done  ,
    (* MARK_DEBUG="true" *)output reg [15:0]   temp_out
);
    localparam      SCL_NUM   = 64;
    
    (* MARK_DEBUG="true" *)reg  [$clog2(SCL_NUM) -1:0] cnt_scl         ;    // 100MHz/64=1.5625MHz
    reg                         p3t1750dp_en_d  ;
    (* MARK_DEBUG="true" *)wire                        scl_high        ;
    (* MARK_DEBUG="true" *)wire                        neg_scl         ;
    (* MARK_DEBUG="true" *)wire                        scl_low         ;
    (* MARK_DEBUG="true" *)wire                        scl_done        ;

    assign scl_high = (cnt_scl == ((SCL_NUM >>2) -1));
    assign neg_scl  = (cnt_scl == ((SCL_NUM >>1) -1));
    assign scl_low  = (cnt_scl == (SCL_NUM -(SCL_NUM >>2) -1));
    assign scl      = (!cnt_scl[$clog2(SCL_NUM) -1]);
    assign scl_done = (&cnt_scl);

    always @(posedge clk_100m or negedge rst_n) begin
        if(!rst_n)begin
            p3t1750dp_en_d <= 1'b0;
            cnt_scl <= 'd0;
        end 
        else begin
            p3t1750dp_en_d <= p3t1750dp_en;
            cnt_scl <= p3t1750dp_en_d ? (cnt_scl + 'd1) : 'd0;
        end 
    end

    (* MARK_DEBUG="true" *)reg  [5:0]                  bit_cnt         ;
    (* MARK_DEBUG="true" *)reg  [15:0]                 read_data       ;
    reg                         sda_o           ;
    reg                         sda_en_d,master_ack_d,slave_ack_d      ;
    wire                        sda_i           ;
    wire                        sda_en          ;

    wire                        start           ;  //1 20
    wire                        addr_w          ;  //2-9        
    wire                        pointer         ;  //11-18 
    wire                        slave_ack       ;  //10 19 29
    wire                        addr_r          ;  //21-28
    wire                        read_byte1      ;  //30-37        
    wire                        master_ack      ;  //38 47
    wire                        read_byte2      ;  //39-46
    wire                        stop            ;  //48
    wire                        idle            ;  //49


    wire [7:0]                  address_w,address_r;  

    assign sda_i    = sda;
    assign sda_en   = (start | addr_w | pointer | addr_r | master_ack | stop | idle);
    assign sda      = sda_en_d ? sda_o : 1'bz;
    assign address_w= {p3t1750dp_addr[6:0],1'b0};   // write
    assign address_r= {p3t1750dp_addr[6:0],1'b1};   // read
    assign p3t1750dp_pointer = 8'h00;
    assign p3t1750dp_done = (stop & scl_high);

    assign start      = ((bit_cnt == 'd0)|(bit_cnt == 'd19));  //1 20   
    assign addr_w     = ((bit_cnt >= 'd1)&(bit_cnt <= 'd8));  //2-9
    assign pointer    = ((bit_cnt >= 'd10)&(bit_cnt <= 'd17)); //11-18
    assign slave_ack  = ((bit_cnt == 'd9)|(bit_cnt == 'd18)|(bit_cnt == 'd28));  //10 19 29
    assign addr_r     = ((bit_cnt >= 'd20)&(bit_cnt <= 'd27));  //21-28
    assign read_byte1 = ((bit_cnt >= 'd29)&(bit_cnt <= 'd36));  //30-37
    assign master_ack = ((bit_cnt == 'd37)|(bit_cnt == 'd46));  //38 47
    assign read_byte2 = ((bit_cnt >= 'd38)&(bit_cnt <= 'd45));  //39-46
    assign stop       = (bit_cnt == 'd47);  //48
    assign idle       = (bit_cnt == 'd48);  //49
    
    always @(posedge clk_100m or negedge rst_n) begin
        if(!rst_n)
            bit_cnt <= 'd0;
        else if(neg_scl)
            if(idle)
                bit_cnt <= 'd0;
            else
                bit_cnt <= (bit_cnt + 'd1);
        else
            bit_cnt <= bit_cnt;
    end 
    always @(posedge clk_100m or negedge rst_n) begin
        if(!rst_n)begin
            master_ack_d <= 1'b0;
            slave_ack_d <= 1'b0;
            sda_en_d <= 1'b0;
            temp_out <= 'd0;
        end
        else begin
            master_ack_d <= master_ack;
            slave_ack_d <= slave_ack;
            sda_en_d <= sda_en;
            temp_out <= p3t1750dp_done ? read_data : temp_out;
        end
    end
    always@(posedge clk_100m or negedge rst_n)begin
        if(!rst_n)
            sda_o <= 1'd1;
        else if(start)// 1 20
            sda_o <= scl_high ? 1'b0 : sda_o;
        else if(addr_w)// 2-9  
            sda_o <= scl_low ? address_w[8 - bit_cnt] : sda_o;
        else if(slave_ack)
            sda_o <= 1'b1;
        else if(pointer)// 11-18
            sda_o <= scl_low ? p3t1750dp_pointer[17 - bit_cnt] : sda_o;
        else if(addr_r)// 21-28
            sda_o <= scl_low ? address_r[27 - bit_cnt] : sda_o;
        else if(master_ack)
            if(scl_low)// 38 47
                sda_o <= (bit_cnt == 'd37) ? 1'b0 : 1'b1;
            else
                sda_o <= ((bit_cnt == 'd46)& neg_scl) ? 1'b0 : sda_o;
        else if(stop)// 48
            sda_o <= scl_high ? 1'b1 : sda_o;
        else if(idle)// 49
            sda_o <= 1'b1;
        else
            sda_o <= sda_o;
    end 
    always@(posedge clk_100m or negedge rst_n)begin
        if(!rst_n)
            read_data <= 'd0;
        else
            read_data <= ((read_byte1 | read_byte2)& scl_high) ? {read_data[14:0],sda_i} : read_data;
    end 
endmodule

 

    测试时ila设置抓取p3t1750dp_done 的上升沿。

      vio依次配置p3t1750dp_addr(硬件上设置器件地址为0x00),p3t1750dp_pointer(指向温度传感器寄存测量结果的寄存器),拉高rst_n信号,最后打开p3t1750dp_en(iic开始和器件通讯)。

 

    第一次触发抓到的结果,温度数据为高12bit,7520右移4位后为470,器件测量精度为0.0625,所以第一次测量结果为:470*0.0625=29.375℃。

      第二次触发的测量结果:结果直接变负数了

 

最新回复

那你到底解决问题没有了啊?????   详情 回复 发表于 昨天 22:28
点赞 关注
 

回复
举报

3080

帖子

0

TA的资源

五彩晶圆(中级)

沙发
 

temperature conversion time One-shot mode    -----有2个地方需要注意,一个是温度的转换时间,一个是工作模式,单一模式或连续模式 。。

点评

数据手册好像没写上电默认是单一模式还是连续模式,我直接当成上电默认连续模式了  详情 回复 发表于 昨天 21:30
 
 

回复

22

帖子

0

TA的资源

一粒金砂(中级)

板凳
 
tagetage 发表于 2024-12-28 20:14 temperature conversion time One-shot mode    -----有2个地方需要注意,一个是温度的转换时间 ...

数据手册好像没写上电默认是单一模式还是连续模式,我直接当成上电默认连续模式了

点评

那你到底解决问题没有了啊?????  详情 回复 发表于 昨天 22:28
 
 
 

回复

3080

帖子

0

TA的资源

五彩晶圆(中级)

4
 
1nnocet- 发表于 2024-12-28 21:30 数据手册好像没写上电默认是单一模式还是连续模式,我直接当成上电默认连续模式了

那你到底解决问题没有了啊?????

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/3 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表