微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 硬件电路设计 > TI模拟硬件电路设计 > LM95172温度芯片读取问题

LM95172温度芯片读取问题

时间:10-02 整理:3721RD 点击:

开发TI的LM95172芯片的驱动时,DATASHEET上的时序是:每次片选CS拉低,第一个读取的16位数据就是温度寄存器里的值。但是,我在实现的过程中发现,好像事实并非如此。在实现的过程中,我的驱动对于有地址的寄存器的读/写是没有问题的。

===============================================================================

    对此,我有两个疑问:

问题1:由于温度寄存器并没有地址,是否是在每次拉低CS时读取?除了在上电时需要复位,在读取温度寄存器之前是否还需要其他的操作?如设置控制/状态寄存器里的值?

问题2:温度是如何转换的?如何判断温度转换完成了?我除了在上电后,第一次拉低CS后读取的16位数据为0x7FFE外,其他的情况下,拉低CS,读取的16位数据都是0.

===============================================================================

以下简要说明操作LM95172的顺序:

(备注:SCK频率为38K; 黄色CS;绿色SCK;蓝色SIO)

  1. 上电时复位。

   (1)拉低CS;读取温度寄存器(所有寄存器没有配置,读取的值为0x7FFE);发送8位读取控制/状态寄存器命令(0x81);读取控制/状态寄存器(读取得到的值为0x0800);拉高CS;

(2)拉低CS;读取温度寄存器(此时读取的值为0x0000);发送8位写入控制/状态寄存器命令(0x01);将(1)中读取的状态值最高位置1,写入控制/状态寄存器(SHUTDOWN状态控制位);延时100ms;拉高CS;

   (3)拉低CS;读取温度寄存器(此时读取的值为0x0000);发送8位写入控制/状态寄存器命令(0x01);将(1)中读取的状态值最高位置0,写入控制/状态寄存器;延时100ms;拉高CS;

 

2. 读取温度:拉低CS;发送16位的串行时钟移入16位数据(移入的是温度寄存器中的数据吗?读取的数据一直是0x0000);拉高CS;

===============================================================================

 

    这里还有一个现象,如果上电复位后,在读取温度是执行以下操作:

    拉低片选 => 读入16位数据(是温度寄存器的值吗?)=> 写入一条8位的命令(如写入0x81,表示读取控制/状态寄存器) => 读取控制/状态寄存器。

则每次读取的值都不一样,读取的数值三次或是四次一个循环周期,还经常出现如下时序,

这个时序图的异常时由什么引起的?

===============================================================================

 

以下为驱动代码:

 

#ifndef LM95172_H
#define LM95172_H

#include <Arduino.h>


class LM95172 {
public:
  static const int READ = 1;
  static const int WRITE = 0;
  static const int CELSIUS = 1;
  static const int FAHRENHEIT = 0;

  static const byte REG_CTL = 0x1;
  static const byte REG_TH = 0x2;
  static const byte REG_TL = 0x3;
  static const byte REG_ID = 0x7;

  static const byte CTRL_SHUT_DOWN = 15;
  static const byte CTRL_ONE_SHOT = 14;
  static const byte CTRL_OVERTEMP_RST = 13;
  static const byte CTRL_CONV_TOGGLE = 12;
  static const byte CTRL_OVERTEMP_STAT = 11;
  static const byte CTRL_T_HIGH = 10;
  static const byte CTRL_T_LOW = 9;
  static const byte CTRL_DATA_AVAIL = 8;
  static const byte CTRL_OVERTEMP_DIS = 7;
  static const byte CTRL_OVERTEMP_POL = 6;
  static const byte CTRL_RES_1 = 5;
  static const byte CTRL_RES_0 = 4;

  static const byte RES_13 = 0x0;
  static const byte RES_14 = 0x1 << 4;
  static const byte RES_15 = 0x2 << 4;
  static const byte RES_16 = 0x3 << 4;

  int currentResolution; 
  int currentUnit; //Celsius or Farenheit
  int PIN_CS;
  int PIN_CLK;
  int PIN_SIO;

  LM95172(int pinCS, int pinClk, int pinSIO) {
    PIN_CS = pinCS;
    PIN_CLK = pinClk;
    PIN_SIO = pinSIO;

    //default resolution
    currentResolution = 13;
  }

  /**
   * Initialize the sensor and reset
   * the default unit is Farenheit
   */
  void init();

  void init(int theUnit) 
  {
    init();
    currentUnit = theUnit;
  }

 /**
  * Device reset according to datasheet
  * needs to be performed on power up.
  */
  void resetSensor();
  
 /**
  * Change temperature reading resolution
  * res: 13 - 16 bits
  */
  void changeResolution(byte res);

 /**
  * Returns current temperature in Celsius
  */
  double getTempC();

 /**
  *Returns current temperature in Fahrenheit
  */
  double getTempF() {
    return 1.8 * getTempC() + 32.0;
  }

 /**
  *Returns the current temperature depending
  *on the unit setting. The default unit is
  *Fahrenheit.
  */
  double getTempReading();

 /**
  * Set over temperature trip point
  * tHigh: trip temperature
  * tLow: hysteresis
  */
  void setTripTemperatureC(double tLow, double tHigh);

 /**
  * Get the current trip temperature threshold
  */
  void getTripTemperatureC(double& tLow, double& tHigh);

 /**
  * Enable or disable OneShot temperature measurement
  * In OneShot mode, the device goes to shutdown mode
  * once a measurement is made
  */
  void enableOneShot(boolean enabled);

 /**
  * Send Command (either read or write) to the sen
  * reg: register
  * rw: READ or WRITE
  * val: 16bit value (if READ, the value is return
  */
  void sendCmd(byte reg, int rw, unsigned int &val);
};

#endif
#include "LM95172.h"

void LM95172::resetSensor()
{
    unsigned int v = 0;
        
    digitalWrite(PIN_CS, LOW);
    getTempC();
    sendCmd(REG_CTL, READ, v);
    digitalWrite(PIN_CS, HIGH);
    
    v = v | (1 << CTRL_SHUT_DOWN); //set shutdown bit;
    digitalWrite(PIN_CS, LOW);
    getTempC();
    sendCmd(REG_CTL, WRITE, v);
    delay(100);
    digitalWrite(PIN_CS, HIGH);
    
    v = ~(1 << CTRL_SHUT_DOWN) & v; //clear shutdown bit;
    digitalWrite(PIN_CS, LOW);
    getTempC();
    sendCmd(REG_CTL, WRITE, v);
    delay(100);
    digitalWrite(PIN_CS, HIGH);
}

void LM95172::init() {
    pinMode(PIN_CS, OUTPUT);
    pinMode(PIN_CLK, OUTPUT);
    pinMode(PIN_SIO, INPUT);
    
    digitalWrite(PIN_CS, HIGH);
    digitalWrite(PIN_CLK, LOW);
    digitalWrite(PIN_SIO, HIGH);
    
    currentUnit = FAHRENHEIT;

    resetSensor();
  }
void LM95172::changeResolution(byte res)
{
    unsigned int v = 0;
     
    digitalWrite(PIN_CS, LOW);
    getTempC();
    sendCmd(REG_CTL, READ, v);
    digitalWrite(PIN_CS, HIGH);
    
    v = v & 0xFFC0; //clear the lower 5 bits;
    
    currentResolution = res;
    
    if (res == 13) v = v | RES_13;
    else if (res == 14) v = v | RES_14;
    else if (res == 15) v = v | RES_15;
    else v = v | RES_16;
    
    digitalWrite(PIN_CS, LOW);
    getTempC();
    sendCmd(REG_CTL, WRITE, v);
    digitalWrite(PIN_CS, HIGH);
}

double LM95172::getTempC()
{
    double result = 0.0;
    
    pinMode(PIN_SIO, INPUT);
    byte h = shiftIn(PIN_SIO, PIN_CLK, MSBFIRST);
    byte l = shiftIn(PIN_SIO, PIN_CLK, MSBFIRST);
        
    unsigned int v = (h << 8) | l;
    
    if (currentResolution == 13) {
        if (v >= 4096) {
            result = (4096.0 - (v >> 3)) * 0.0625;
        } else {
            result = (v >> 3) * 0.0625;
        }
    } else if (currentResolution == 14) {
        if (v >= 8192) {
            result = (8192.0 - (v >> 2)) * 0.03125;
        } else {
            result = (v >> 2) * 0.03125;
        }            
    } else if (currentResolution == 15) {
        if (v >= 16384) {
            result = (16384.0 - (v >> 1)) * 0.015625;
        } else {
            result = (v >> 1) * 0.015625;
        }
    } else {
        if (v >= 32768l) {
            result = (32768.0 - v) * 0.0078125;
        } else {
            result = v * 0.0078125;
        }
    }
    
    return result;
}

double LM95172::getTempReading()
{
  double t = 0.0;

  digitalWrite(PIN_CS, LOW);

  if (currentUnit == CELSIUS) t = getTempC();
  else t = getTempF();

  digitalWrite(PIN_CS, HIGH);
  
  return t;
}

void LM95172::setTripTemperatureC(double tLow, double tHigh)
{
    unsigned int tl, th, v;
    
    th = (unsigned int) (tHigh * 32 * 4) & 0xFFE0;
    tl = (unsigned int) (tLow * 32 * 4) & 0xFFE0;

    digitalWrite(PIN_CS, LOW);
    getTempC();
    sendCmd(REG_CTL, READ, v);    
    sendCmd(REG_TH, WRITE, th);
    sendCmd(REG_TL, WRITE, tl);    
    digitalWrite(PIN_CS, HIGH);   
}

void LM95172::getTripTemperatureC(double& tLow, double& tHigh)
{
    unsigned int tl, th, v;
    

    digitalWrite(PIN_CS, LOW);
    getTempC();
    sendCmd(REG_CTL, READ, v);    
    sendCmd(REG_TH, READ, th);
    sendCmd(REG_TL, READ, tl);    
    digitalWrite(PIN_CS, HIGH);    
   
    tHigh = (double) th / 32.0 * 0.25;
    tLow = (double) tl / 32.0 * 0.25;
}
void LM95172::enableOneShot(boolean enabled)
{
    unsigned int v = 0;
     
    digitalWrite(PIN_CS, LOW);
    getTempC();
    sendCmd(REG_CTL, READ, v);
    digitalWrite(PIN_CS, HIGH);
    
    if (enabled) {
        v = v | (1 << CTRL_SHUT_DOWN) | ( 1 << CTRL_ONE_SHOT);     
    } else {
        v = v & ~(1 << CTRL_SHUT_DOWN) & ~( 1 << CTRL_ONE_SHOT);
    }
    
    digitalWrite(PIN_CS, LOW);
    getTempC();
    sendCmd(REG_CTL, WRITE, v);
    digitalWrite(PIN_CS, HIGH);  
}

void LM95172::sendCmd(byte reg, int rw, unsigned int &val)
{
    byte cmdByte = 0;
    
    if (rw == READ) cmdByte = 0x80 | reg;
    else cmdByte =  reg;
    
    pinMode(PIN_SIO, OUTPUT);    
    shiftOut(PIN_SIO, PIN_CLK, MSBFIRST, cmdByte);
    
    if (rw == READ) {
        pinMode(PIN_SIO, INPUT);
        byte h = shiftIn(PIN_SIO, PIN_CLK, MSBFIRST);
        byte l = shiftIn(PIN_SIO, PIN_CLK, MSBFIRST);
        
        val = (h << 8) | l;
    } else {
        byte h = (val & 0xff00) >> 8;
        byte l = val & 0xff;
        
        shiftOut(PIN_SIO, PIN_CLK, MSBFIRST, h);
        shiftOut(PIN_SIO, PIN_CLK, MSBFIRST, l);
    }  
}

附件是本问题的WORD版本描述。

数据手册的图 11,12,13 详细描述了读温度寄存器的时序

上来是先读16位温度, 仔细研究一下吧.

你好,

1.  我已经很仔细的研究了数据手册中的时序,并且都做过实验,用示波器抓取过读取的时序;

2.   时序上表示的是:CS拉低读取16位的温度,但是事实好像并非如此。

3.  我的驱动是按照数据手册开发的,但是读取不到温度。

PS: 不知是不是LM95172使用的人比较少,在网络和各大论坛上,其相关资料比较少,可供

参考资料除了数据手册,也很少有其他资料;我已请我们技术小组的硬件工程师、技术主管和

我们公司的首席科学家研究过这个问题,但是问题一直没有解决。

如果你使用过lm95172,还请不吝赐教。若有时间,帮忙看看我的驱动程序是否存在问题也是

万分感谢的!~

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top