반응형
2021/10/30 처음 시작
소나무 기운 , 전자제품 개발/생산
TMP117 온도센서 사용하기
TMP117 온도센서입니다.
- I2C통신
- 0.1도 정확도
- -20도 ~ +50도 측정, 최대 -55도 ~ 150도 측정 가능
- 16비트 0.0078도 분해능
보이는 예제 모두가 C++ 로 되어 있어서 C에서 쓰기위해 수정을 좀 했어요.
사용법
1mS마다 한번씩
TMP117Process()함수를 호출해 주면 됩니다.
그러면 500mS마다 한번씩 온도를 읽어
g_tStsDev.nBdTemp 변수에 넣습니다.
포함하셔서 컴파일하시면 없는 변수 몇개는 에러가 날겁니다.
조금 수정해서 사용하세요.
tmp117.h 파일
#ifndef __TMP117_H__
#define __TMP117_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "common.h"
/*!
* @file Adafruit_TMP117.h
*
* I2C Driver for the Adafruit Arduino library for the TMP117
*high-accuracy temperature sensor This is a library is written to work with the
*Adafruit TMP117 breakout: https://www.adafruit.com/products/4821
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing products from
* Adafruit!
*
*
* BSD license (see license.txt)
*/
// #define TMP117_I2CADDR_DEFAULT 0x48 ///< TMP117 default i2c address
#define TMP117_DEV_ADDR 0x90
#define TMP117_CHIP_ID 0x0117 ///< TMP117 default device id from WHOAMI
#define TMP117_WHOAMI 0x0F ///< Chip ID register
#define _CONFIGURATION 0x01 ///< Configuration register
#define TMP117_TEMP_DATA 0x00 ///< Temperature data register
#define TMP117_CONFIGURATION 0x01 ///< Configuration register
#define TMP117_T_HIGH_LIMIT 0x02 ///< High limit set point register
#define TMP117_T_LOW_LIMIT 0x03 ///< Low limit set point register
#define TMP117_TEMP_OFFSET 0x07 ///< Temp offset register
#define TMP117_DEVICE_ID 0x0F ///< Device ID register
#define WHOAMI_ANSWER 0x0117 ///< Correct 2-byte ID register value response
#define HIGH_ALRT_FLAG 0b100 ///< mask to check high threshold alert
#define LOW_ALRT_FLAG 0b010 ///< mask to check low threshold alert
#define DRDY_ALRT_FLAG 0b001 ///< mask to check data ready flag
#define TMP117_RESOLUTION \
0.0078125f ///< Scalar to convert from LSB value to degrees C
// #define TMP117_EEPROM_UL 0x04
// #define TMP117_EEPROM1 0x05
// #define TMP117_EEPROM2 0x06
// #define TMP117_EEPROM3 0x08
///////////////////////////////////////////////////////////////
/**
* @brief
*
* Allowed values for `setDataRate`.
*/
typedef enum
{
TMP117_RATE_ONE_SHOT,
} tmp117_rate_t;
/**
* @brief A struct to hold alert state information.
*
* The alert state register is auto-clearing and so must be read together
*
*/
typedef struct
{
bool high; ///< Status of the high temperature alert
bool low; ///< Status of the low temperature alert
bool data_ready; ///< Status of the data_ready alert
} tmp117_alerts_t;
/**
* @brief Options for setAveragedSampleCount
*
*/
typedef enum
{
TMP117_AVERAGE_1X,
TMP117_AVERAGE_8X,
TMP117_AVERAGE_32X,
TMP117_AVERAGE_64X,
} tmp117_average_count_t;
/**
* @brief Options to specify the minimum delay between new measurements.
*
*/
typedef enum
{
TMP117_DELAY_0_MS,
TMP117_DELAY_125_MS,
TMP117_DELAY_250_MS,
TMP117_DELAY_500_MS,
TMP117_DELAY_1000_MS,
TMP117_DELAY_4000_MS,
TMP117_DELAY_8000_MS,
TMP117_DELAY_16000_MS,
} tmp117_delay_t;
typedef enum
{
TMP117_MODE_CONTINUOUS,
TMP117_MODE_SHUTDOWN,
TMP117_MODE_ONE_SHOT = 3, // skipping 0x2 which is a duplicate CONTINUOUS
} tmp117_mode_t;
void TMP117Process(void);
void TMP117_reset(void);
void TMP117_SetinterruptsActiveLow(bool active_low);
bool TMP117_GetinterruptsActiveLow(void);
bool TMP117_getEvent(int16_t *temp);
bool TMP117_getAlerts(tmp117_alerts_t *alerts);
bool TMP117_setThermAlertModeEnabled(bool therm_enabled);
bool TMP117_getThermAlertModeEnabled(void);
tmp117_average_count_t TMP117_getAveragedSampleCount(void);
bool TMP117_setAveragedSampleCount(tmp117_average_count_t count);
float TMP117_getOffset(void);
bool TMP117_setOffset(float offset);
float TMP117_getLowThreshold(void);
bool TMP117_setLowThreshold(float low_threshold);
float TMP117_getHighThreshold(void);
bool TMP117_setHighThreshold(float high_threshold);
tmp117_delay_t TMP117_getReadDelay(void);
bool TMP117_setReadDelay(tmp117_delay_t delay);
tmp117_mode_t TMP117_getMeasurementMode(void);
bool TMP117_setMeasurementMode(tmp117_mode_t mode);
bool TMP117_read(uint8_t byRegAddr, uint8_t *pBuf, uint8_t byLen);
// void _read(void);
bool TMP117_init(void);
uint16_t TMP117_sensorid_temp; ///< ID number for temperature
tmp117_alerts_t TMP117_alert_drdy_flags; ///< Storage for self-cleared bits in config reg.
// float TMP117_unscaled_temp; ///< Last reading's temperature (C) before scaling
// Adafruit_I2CDevice *i2c_dev = NULL; ///< Pointer to I2C bus interface
// Adafruit_BusIO_Register *config_reg = NULL; ///< Pointer to config register object
// Adafruit_BusIO_Register *temp_reg = NULL; ///< Temperature register, used regularly
void TMP117_readAlertsDRDY(void);
bool TMP117_getDataReady(void);
void TMP117_waitForData(void);
#ifdef __cplusplus
}
#endif
#endif
TMP117.c 파일
//------------------------------------------------------------------------------
#include "tmp117.h"
#include "stm32f1xx_hal.h"
#include <ctype.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
extern I2C_HandleTypeDef hi2c2;
extern TStatusDev g_tStsDev;
extern void FormMeasRslt_UpdateCurAdj(void);
//------------------------------------------------------------------------------
void TMP117Process(void)
{ // every 1ms
static uint16_t MCP117Cnt = 0;
int16_t nT = 0;
MCP117Cnt++;
if (MCP117Cnt > 500) // 500ms
{
MCP117Cnt = 0;
if (TMP117_getEvent(&nT) == true)
{
g_tStsDev.nBdTemp = nT;
}
FormMeasRslt_UpdateCurAdj(); // 현재 온도값에 따른 조절값 가져오기
}
}
//------------------------------------------------------------------------------
bool TMP117_read(uint8_t byRegAddr, uint8_t *pBuf, uint8_t byLen)
{
if (HAL_I2C_Master_Transmit(&hi2c2, (uint16_t)TMP117_DEV_ADDR, &byRegAddr, 1, 1000) != HAL_OK)
return false;
return HAL_I2C_Master_Receive(&hi2c2, (uint16_t)TMP117_DEV_ADDR, pBuf, byLen, 1000);
}
//------------------------------------------------------------------------------
bool TMP117_write(uint8_t byRegAddr, uint8_t *pBuf, uint8_t byLen)
{
if (HAL_I2C_Master_Transmit(&hi2c2, (uint16_t)TMP117_DEV_ADDR, &byRegAddr, 1, 1000) != HAL_OK)
return false;
return HAL_I2C_Master_Receive(&hi2c2, (uint16_t)TMP117_DEV_ADDR, pBuf, byLen, 1000);
}
//------------------------------------------------------------------------------
bool TMP117_write_bit(uint8_t byRegAddr, uint8_t byBit, uint8_t byShift)
{
uint16_t buffer;
TMP117_read(byRegAddr, (uint8_t *)&buffer, 2);
byBit = byBit << byShift;
buffer &= (~byBit); // clear
buffer |= byBit; // set
return TMP117_write(byRegAddr, (uint8_t *)&buffer, 2);
}
//------------------------------------------------------------------------------
uint16_t TMP117_read_bit(uint8_t byRegAddr, uint8_t byMask, uint8_t byShift)
{
uint16_t buffer;
// uint16_t nTmp;
TMP117_read(byRegAddr, (uint8_t *)&buffer, 2);
buffer >>= byShift;
buffer = buffer & (uint16_t)byMask;
return buffer;
}
//------------------------------------------------------------------------------
/*! @brief Initializer for post bus-init setup
* @param sensor_id Optional unique ID for the sensor set
* @returns True if chip identified and initialized
*/
bool TMP117_init(void)
{
// Adafruit_BusIO_Register chip_id =
// Adafruit_BusIO_Register(i2c_dev, TMP117_WHOAMI, 2, MSBFIRST);
// make sure we're talking to the right chip
uint8_t buffer[2];
// chip_id.read(buffer, 2);
TMP117_read(TMP117_WHOAMI, buffer, 2);
if ((buffer[0] << 8 | buffer[1]) != WHOAMI_ANSWER)
{
return false;
}
// _sensorid_temp = sensor_id;
// do any software reset or other initial setup
// config_reg =
// new Adafruit_BusIO_Register(i2c_dev, TMP117_CONFIGURATION, 2, MSBFIRST);
// temp_reg =
// new Adafruit_BusIO_Register(i2c_dev, TMP117_TEMP_DATA, 2, MSBFIRST);
TMP117_reset();
return true;
}
//------------------------------------------------------------------------------
/**
* @brief Performs a software reset initializing registers to their power on
* state
*
*/
void TMP117_reset(void)
{
// Adafruit_BusIO_RegisterBits sw_reset =
// Adafruit_BusIO_RegisterBits(config_reg, 1, 1);
// sw_reset.write(1);
TMP117_write_bit(TMP117_CONFIGURATION, 1, 1);
HAL_Delay(2); // datasheet specifies 2ms for reset
TMP117_waitForData();
}
//------------------------------------------------------------------------------
bool TMP117_getEvent(int16_t *temp)
{
// uint32_t t = millis();
uint16_t buffer;
TMP117_readAlertsDRDY();
if (TMP117_getDataReady() == false)
return false;
// Temp reg will report old value until new value is ready; "clears" on new
// data ready
// unscaled_temp = (int16_t)temp_reg->read();
// use helpers to fill in the events
// memset(temp, 0, sizeof(sensors_event_t));
// temp->version = sizeof(sensors_event_t);
// temp->sensor_id = _sensorid_temp;
// temp->type = SENSOR_TYPE_AMBIENT_TEMPERATURE;
// temp->timestamp = t;
// temp->temperature = (unscaled_temp * TMP117_RESOLUTION);
TMP117_read(TMP117_TEMP_DATA, (uint8_t *)&buffer, 2);
buffer = ((buffer >> 8) | (buffer << 8));
*temp = (int16_t)(buffer * TMP117_RESOLUTION);
return true;
}
//------------------------------------------------------------------------------
/**
* @brief Get the current state of the alert flags
*
* **NOTE:** Because the high/low temperature status is based on temperature
* data, their status returned by this method is only updated when new
* temperature data is available. This ensures that the reported value is based
* on temperature data and not a cleared but not updated alert status.
*
* @param alerts Pointer to an alerts struct to be filled with the trigger
* status of the alerts
* @return true:success false: failure
*/
bool TMP117_getAlerts(tmp117_alerts_t *alerts)
{
TMP117_readAlertsDRDY();
memset(alerts, 0, sizeof(tmp117_alerts_t));
alerts->high = TMP117_alert_drdy_flags.high;
alerts->low = TMP117_alert_drdy_flags.low;
alerts->data_ready = TMP117_alert_drdy_flags.data_ready;
return true;
}
//------------------------------------------------------------------------------
/**
* @brief Read the current low temperature threshold
*
* @return float The current low temperature threshold in degrees C
*/
float TMP117_getLowThreshold(void)
{
// Adafruit_BusIO_Register low_threshold_reg =
// Adafruit_BusIO_Register(i2c_dev, TMP117_T_LOW_LIMIT, 2, MSBFIRST);
// return (int16_t)low_threshold_reg.read() * TMP117_RESOLUTION;
int16_t nTmp;
TMP117_read(TMP117_TEMP_DATA, (uint8_t *)&nTmp, 2);
return nTmp * TMP117_RESOLUTION;
}
//------------------------------------------------------------------------------
/**
* @brief Set a new low temperature threshold
*
* @param low_threshold The new threshold to be set, in degrees C. An alert will
* trigger when the current temperature measurement is lower than the given
* threshold.
* @return true:success false: failure
*/
bool TMP117_setLowThreshold(float low_threshold)
{
// Adafruit_BusIO_Register low_threshold_reg =
// Adafruit_BusIO_Register(i2c_dev, TMP117_T_LOW_LIMIT, 2, MSBFIRST);
// return low_threshold_reg.write(low_threshold / TMP117_RESOLUTION);
int16_t nTmp;
nTmp = (low_threshold / TMP117_RESOLUTION);
return TMP117_write(TMP117_T_LOW_LIMIT, (uint8_t *)&nTmp, 2);
}
//------------------------------------------------------------------------------
/**
* @brief Read the current high temperature threshold
*
* @return float The current high temperature threshold in degrees C
*/
float TMP117_getHighThreshold(void)
{
// Adafruit_BusIO_Register high_threshold_reg =
// Adafruit_BusIO_Register(i2c_dev, TMP117_T_HIGH_LIMIT, 2, MSBFIRST);
// return (int16_t)high_threshold_reg.read() * TMP117_RESOLUTION;
int16_t nTmp;
TMP117_read(TMP117_T_HIGH_LIMIT, (uint8_t *)&nTmp, 2);
return nTmp * TMP117_RESOLUTION;
}
//------------------------------------------------------------------------------
/**
* @brief Set a new high temperature threshold
*
* @param high_threshold The new threshold to be set, in degrees C. An alert
* will trigger when the current temperature measurement is higher than the
* given threshold.
* @return true:success false: failure
*/
bool TMP117_setHighThreshold(float high_threshold)
{
// Adafruit_BusIO_Register high_threshold_reg =
// Adafruit_BusIO_Register(i2c_dev, TMP117_T_HIGH_LIMIT, 2, MSBFIRST);
// return high_threshold_reg.write(high_threshold / TMP117_RESOLUTION);
int16_t nTmp;
nTmp = (high_threshold / TMP117_RESOLUTION);
return TMP117_write(TMP117_T_HIGH_LIMIT, (uint8_t *)&nTmp, 2);
}
//------------------------------------------------------------------------------
/**
* @brief Sets the polarity of the INT pin.
*
* @param active_low Set to true to make the pin active low
*/
void TMP117_SetinterruptsActiveLow(bool active_low)
{
// Adafruit_BusIO_RegisterBits active_low_bit =
// Adafruit_BusIO_RegisterBits(config_reg, 1, 3);
// active_low_bit.write(active_low);
TMP117_write_bit(TMP117_CONFIGURATION, active_low, 3);
}
//------------------------------------------------------------------------------
/**
* @brief Get the polarity of the INT pin.
*
* @return active_low
*
* true: INT pin is active when low
* false: INT pin is active when high
*/
bool TMP117_GetinterruptsActiveLow(void)
{
// Adafruit_BusIO_RegisterBits active_low_bit =
// Adafruit_BusIO_RegisterBits(config_reg, 1, 3);
// return active_low_bit.read();
return TMP117_read_bit(TMP117_CONFIGURATION, 1, 3);
}
//------------------------------------------------------------------------------
/**
* @brief Read the current temperature offset
*
* @return float The currently set temperature offset.
*/
float TMP117_getOffset(void)
{
// Adafruit_BusIO_Register temp_offset_reg =
// Adafruit_BusIO_Register(i2c_dev, TMP117_TEMP_OFFSET, 2, MSBFIRST);
// return temp_offset_reg.read() * TMP117_RESOLUTION;
int16_t nTmp;
if (TMP117_read(TMP117_TEMP_OFFSET, (uint8_t *)&nTmp, 2))
return 0;
return nTmp * TMP117_RESOLUTION;
}
//------------------------------------------------------------------------------
/**
* @brief Write a new temperature offset.
*
* @param offset The new temperature offset in degrees C. When set, the given
* offset will be added to all future temperature reads reported by `getEvent`
* @return true: success false: failure
*/
bool TMP117_setOffset(float offset)
{
if ((offset > 256.0) || (offset < -256.0))
{
return false;
}
// Adafruit_BusIO_Register temp_offset_reg =
// Adafruit_BusIO_Register(i2c_dev, TMP117_TEMP_OFFSET, 2, MSBFIRST);
int16_t offset_lsb = (int16_t)round(offset / TMP117_RESOLUTION);
// bool success = temp_offset_reg.write(offset_lsb);
bool success = TMP117_write(TMP117_TEMP_OFFSET, (uint8_t *)&offset_lsb, 2);
if (success)
TMP117_waitForData();
return success;
}
//------------------------------------------------------------------------------
/**
* @brief Enable or disable "THERM" alert mode
*
*
* WHen enabled, the 'low' alert will never trigger and acts in combination with
* the high threshold to determine the behavior of the high temperature alert.
*
* In "Therm" mode, the "high" temperature alert statys triggered until the
* measured temperature goes below the 'low' temperature threshold, allowing it
* to act like a hysteresis value to prevent thrashing around the threshold
* temperature.
*
* @param therm_enabled
* @return true:success false:failure
*/
bool TMP117_setThermAlertModeEnabled(bool therm_enabled)
{
// Adafruit_BusIO_RegisterBits therm_enable_bit =
// Adafruit_BusIO_RegisterBits(config_reg, 1, 4);
// return therm_enable_bit.write(therm_enabled);
return TMP117_write_bit(TMP117_CONFIGURATION, 1, 4);
}
//------------------------------------------------------------------------------
/**
* @brief Get the current enable status of the "THERM" alert mode
*
* @return true: Therm mode enabled
* @return false Normal high/low alert mode enabled
*/
bool TMP117_getThermAlertModeEnabled(void)
{
// Adafruit_BusIO_RegisterBits therm_enable_bit =
// Adafruit_BusIO_RegisterBits(config_reg, 1, 4);
// return therm_enable_bit.read();
return TMP117_read_bit(TMP117_CONFIGURATION, 1, 4);
}
//------------------------------------------------------------------------------
/**
* @brief Read the current number of samples that are averaged to calculate the
* reported temperature
*
* @return tmp117_average_count_t The current average setting enum value
*/
tmp117_average_count_t TMP117_getAveragedSampleCount(void)
{
// Adafruit_BusIO_RegisterBits average_count_bits =
// Adafruit_BusIO_RegisterBits(config_reg, 2, 5);
// return (tmp117_average_count_t)average_count_bits.read();
return (tmp117_average_count_t)TMP117_read_bit(TMP117_CONFIGURATION, 3, 5);
}
//------------------------------------------------------------------------------
/**
* @brief Set the number of raw measurements that are averaged into the reported
* temperature.
*
* Each sample read takes 15.5ms so the higher the number of averaged samples,
* the longer the amount of time between new measurements. For larger average
* counts the amount of time required for a new measurement will exceed the
* interval specified by `setReadDelay`
*
* @param count The `tmp117_average_count_t` that specifies the desired sample
* count
* @return true:success false:failure
*/
bool TMP117_setAveragedSampleCount(tmp117_average_count_t count)
{
// Adafruit_BusIO_RegisterBits average_count_bits =
// Adafruit_BusIO_RegisterBits(config_reg, 2, 5);
// return average_count_bits.write(count);
return TMP117_read_bit(TMP117_CONFIGURATION, count, 5);
}
//------------------------------------------------------------------------------
/**
* @brief Get current setting for the minimum delay between calculated
* temperature reads.
*
* @return tmp117_delay_t The minimum time between new temperature measurements.
* This amount of time will be exceeded if the time required for the configured
* number of averaged reads is more than the delay setting.
*/
tmp117_delay_t TMP117_getReadDelay(void)
{
// Adafruit_BusIO_RegisterBits read_delay_bits =
// Adafruit_BusIO_RegisterBits(config_reg, 3, 7);
// return (tmp117_delay_t)read_delay_bits.read();
return (tmp117_delay_t)TMP117_read_bit(TMP117_CONFIGURATION, 3, 7);
}
//------------------------------------------------------------------------------
/**
* @brief Set a new minimum delay between calculated reads
*
* @param delay The minimum time between new temperature `measurements as a
* tmp117_delay_t`. This amount of time will be exceeded if the time required
* for the configured number of averaged reads is more than the delay setting.
* @return true:success false:failure
*/
bool TMP117_setReadDelay(tmp117_delay_t delay)
{
// Adafruit_BusIO_RegisterBits read_delay_bits =
// Adafruit_BusIO_RegisterBits(config_reg, 3, 7);
// return read_delay_bits.write(delay);
return TMP117_write_bit(TMP117_CONFIGURATION, 3, 7);
}
//------------------------------------------------------------------------------
/**
* @brief Read the active measurement mode
*
* @return tmp117_mode_t The current measurement mode.
*/
tmp117_mode_t TMP117_getMeasurementMode(void)
{
// Adafruit_BusIO_RegisterBits mode_bits =
// Adafruit_BusIO_RegisterBits(config_reg, 2, 10);
// return (tmp117_mode_t)mode_bits.read();
return (tmp117_mode_t)TMP117_read_bit(TMP117_CONFIGURATION, 2, 10);
}
//------------------------------------------------------------------------------
/**
* @brief Set a new measurement mode
*
* @param mode the new mode to set, a `tmp117_mode_t`. If `mode` is
* `TMP117_MODE_ONE_SHOT`, initiate a new reading before switching to
* `TMP117_MODE_SHUTDOWN`.
* @return true:success false:failure
*/
bool TMP117_setMeasurementMode(tmp117_mode_t mode)
{
// Adafruit_BusIO_RegisterBits mode_bits =
// Adafruit_BusIO_RegisterBits(config_reg, 2, 10);
// return mode_bits.write(mode);
return TMP117_write_bit(TMP117_CONFIGURATION, 2, 10);
}
/////////////////// Misc private methods //////////////////////////////
//------------------------------------------------------------------------------
void TMP117_waitForData(void)
{
while (!TMP117_getDataReady())
{
HAL_Delay(1);
}
}
bool TMP117_getDataReady(void)
{
TMP117_readAlertsDRDY();
return TMP117_alert_drdy_flags.data_ready;
}
//------------------------------------------------------------------------------
void TMP117_readAlertsDRDY(void)
{
// Adafruit_BusIO_RegisterBits alert_drdy_bits =
// Adafruit_BusIO_RegisterBits(config_reg, 3, 13);
// uint8_t alert_bits = alert_drdy_bits.read();
uint8_t alert_bits = TMP117_read_bit(TMP117_CONFIGURATION, 3, 13);
TMP117_alert_drdy_flags.data_ready = (alert_bits & DRDY_ALRT_FLAG) > 0;
// drdy means a new read finished, verifies that the alert values
// match the currently reported temperature
if (TMP117_alert_drdy_flags.data_ready)
{
TMP117_alert_drdy_flags.high = (alert_bits & HIGH_ALRT_FLAG) > 0;
TMP117_alert_drdy_flags.low = (alert_bits & LOW_ALRT_FLAG) > 0;
}
}
//------------------------------------------------------------------------------
마무리
ㅁ 어드레스 값 확인 후 사용하세요.
ㅁ 외부 참조 변수 선언부 에러가 있을테니 수정하셔야 합니다.
ㅁ 500mS마다 한번씩 읽고 있어요.
참고문헌
틀린 부분이나 질문은 댓글 달아주세요.
즐거운 하루 보내세요. 감사합니다.
반응형
'STMicro STM32' 카테고리의 다른 글
LTC2943 - Multicell Battery Gas Gauge (0) | 2021.12.12 |
---|---|
Two ways to Flash loader with UART(RS232) (0) | 2021.12.01 |
STM32F103 내부 온도센서를 읽어보자. (2) | 2021.08.12 |
[STM32] CubeIDE , post-build steps 기능 활용. 컴파일 완료 후 특정 작업 진행. (0) | 2021.06.24 |
STM32CubeIDE 두개의 프로젝트에서 파일 공유하기 (0) | 2021.06.13 |
댓글