📄 sht1x.c
字号:
/**************************************************
温度湿度测量
采用: Sensirion SHT1x 温湿度传感器
通讯: IIC总线
***************************************************/
#include <msp430x14x.h>
#include <math.h>
#include "Global.h"
#include "ModbusSlaver.h"
/* ---- 引脚端口定义 ---- */
#define IIC_OUT (P2OUT)
#define IIC_IN (P2IN)
#define IIC_DIR (P2DIR)
#define IIC_DAT (BIT0)
#define IIC_SCK (BIT1)
// DAT脚采用电阻上拉, 所以初始化让DAT输出0
// DAT线为1: 则把DAT切换为输入状态, DAT线被拉为1
// DAT线为0: 则把DAT切换为输出状态, DAT输出0
#define IIC_DAT_1 IIC_DIR &= ~IIC_DAT
#define IIC_DAT_0 IIC_DIR |= IIC_DAT
// SCK先为单片机直接输出
#define IIC_SCK_1 IIC_OUT |= IIC_SCK
#define IIC_SCK_0 IIC_OUT &= ~IIC_SCK
// 读取DAT线的高低(是否为0)
#define IIC_DAT_R (IIC_IN & IIC_DAT)
/* ---- 命令定义 ---- */
#define NOACK 0
#define ACK 1
//adr command r/w
#define STATUS_REG_W (0x06) //000 0011 0
#define STATUS_REG_R (0x07) //000 0011 1
#define MEASURE_TEMP (0x03) //000 0001 1
#define MEASURE_HUMI (0x05) //000 0010 1
#define RESET (0x1e) //000 1111 0
#define NO_ERROR 0
#define ERROR_NOACK 1
#define STATUS_OK (0)
#define STATUS_SENSORFAIL (1)
unsigned char Flg_MeasureTcRH = FALSE;// 测量允许标志
unsigned char Status; // 状态
unsigned char Flg_BatteryLow; // 电压低标志
#define ACK_TIME_OUT (30000)
#define DELAY_VALUE (20)
void SHT_Delay(unsigned int time)
{
for(; time>0; time--){}
}
unsigned char SHT_WriteByte(unsigned char Value)
// writes a byte on the Sensibus and checks the acknowledge
{
unsigned char i;
unsigned char Error = 0;
// Send 8bit Data
for (i=0x80; i>0; i/=2) //shift bit for masking
{
if (i & Value) IIC_DAT_1; //masking value with i , write to SENSI-BUS
else IIC_DAT_0;
SHT_Delay(DELAY_VALUE);
IIC_SCK_1; //clk for SENSI-BUS
_NOP();_NOP();_NOP();_NOP(); //pulswith approx. 5 us
SHT_Delay(DELAY_VALUE);
IIC_SCK_0;
SHT_Delay(DELAY_VALUE);
}
// Release Bus and wait for ACK signal
IIC_DAT_1; //release DATA-line
SHT_Delay(DELAY_VALUE);
IIC_SCK_1; //clk #9 for ack
SHT_Delay(DELAY_VALUE);
if (IIC_DAT_R) Error = ERROR_NOACK;
else Error = NO_ERROR; //check ack (DATA will be pulled down by SHT11)
IIC_SCK_0;
// retuen Error
return Error; //error=1 in case of no acknowledge
}
unsigned char SHT_ReadByte(unsigned char Ack)
// reads a byte form the Sensibus and gives an acknowledge in case of "ack=1"
{
unsigned char i;
unsigned char Value=0;
// Read 8bit from Data-line
IIC_DAT_1; //release DATA-line
for (i=0x80; i>0; i/=2) //shift bit for masking
{
IIC_SCK_1; //clk for SENSI-BUS
SHT_Delay(DELAY_VALUE);
if (IIC_DAT_R) Value |= i; //read bit
_NOP();_NOP();_NOP();_NOP(); // Edit By Bull
SHT_Delay(DELAY_VALUE);
IIC_SCK_0;
SHT_Delay(DELAY_VALUE);
}
// Answer for Ack
if (Ack) IIC_DAT_0; //in case of "ack==1" pull down DATA-Line
IIC_SCK_1; //clk #9 for ack
SHT_Delay(DELAY_VALUE);
_NOP();_NOP();_NOP();_NOP(); //pulswith approx. 5 us
IIC_SCK_0;
SHT_Delay(DELAY_VALUE);
IIC_DAT_1; //release DATA-line
//retuen Byte
return Value;
}
void SHT_TransStart(void)
// generates a transmission start
// _____ ________
// DATA: |_______|
// ___ ___
// SCK : ___| |___| |______
{
IIC_DAT_1; IIC_SCK_0; //Initial state
SHT_Delay(DELAY_VALUE);
IIC_SCK_1;
SHT_Delay(DELAY_VALUE);
IIC_DAT_0;
SHT_Delay(DELAY_VALUE);
IIC_SCK_0;
SHT_Delay(DELAY_VALUE);
IIC_SCK_1;
SHT_Delay(DELAY_VALUE);
IIC_DAT_1;
SHT_Delay(DELAY_VALUE);
IIC_SCK_0;
}
void SHT_ConnectionReset(void)
// communication reset: DATA-line=1 and at least 9 SCK cycles followed by transstart
// _____________________________________________________ ________
// DATA: |_______|
// _ _ _ _ _ _ _ _ _ ___ ___
// SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______| |___| |______
{
unsigned char i;
IIC_DAT_1; IIC_SCK_0; //Initial state
for(i=0;i<9;i++) //9 SCK cycles
{ IIC_SCK_1;
SHT_Delay(DELAY_VALUE);
IIC_SCK_0;
}
SHT_TransStart(); //transmission start
}
unsigned char SHT_SoftReset(void)
// resets the sensor by a softreset
{
unsigned char Error=0;
SHT_ConnectionReset(); //reset communication
Error += SHT_WriteByte(RESET); //send RESET-command to sensor
return Error; //error=1 in case of no response form the sensor
}
unsigned char SHT_ReadStatusReg(unsigned char *p_Value, unsigned char *p_CheckSum)
// reads the status register with checksum (8-bit)
{
unsigned char Error = 0;
SHT_TransStart(); //transmission start
Error = SHT_WriteByte(STATUS_REG_R); //send command to sensor
*p_Value = SHT_ReadByte(ACK); //read status register (8-bit)
*p_CheckSum = SHT_ReadByte(NOACK); //read checksum (8-bit)
return Error; //error=1 in case of no response form the sensor
}
unsigned char SHT_WriteStatusReg(unsigned char *p_Value)
// writes the status register with checksum (8-bit)
{
unsigned char Error=0;
SHT_TransStart(); //transmission start
Error += SHT_WriteByte(STATUS_REG_W); //send command to sensor
Error += SHT_WriteByte(*p_Value); //send value of status register
return Error; //error>=1 in case of no response form the sensor
}
/* ---- 温度湿度测量函数 Temperature & Humidity Measure function---- */
unsigned char SHT_Measure_Temperature(signed int *p_Value, unsigned char *p_CheckSum)
// makes a measurement (humidity/temperature) with checksum
{
unsigned Error = 0;
unsigned int i, j;
unsigned char TempH;
unsigned char TempL;
SHT_TransStart(); //transmission start
Error += SHT_WriteByte(MEASURE_TEMP); //send command to sensor
for (i=0;i<ACK_TIME_OUT;i++)
{
for (j=0;j<10;j++){_NOP(); _NOP(); _NOP(); _NOP();}
if(IIC_DAT_R==0) break; //wait until sensor has finished the measurement
//Modbus_Deal();
}
if(IIC_DAT_R) Error+=1; // or timeout (~2 sec.) is reached
//*(p_Value) = SHT_ReadByte(ACK); //read the first byte (MSB)
//*(p_Value+1) = SHT_ReadByte(ACK); //read the second byte (LSB)
TempH = SHT_ReadByte(ACK);
TempL = SHT_ReadByte(ACK);
*p_Value = TempH * 256 + TempL;
*p_CheckSum = SHT_ReadByte(NOACK); //read checksum
return Error;
}
unsigned char SHT_Measure_Humidity(signed int *p_Value, unsigned char *p_CheckSum)
// makes a measurement (humidity/temperature) with checksum
{
unsigned Error = 0;
unsigned int i;
unsigned char TempH;
unsigned char TempL;
SHT_TransStart(); //transmission start
Error += SHT_WriteByte(MEASURE_HUMI); //send command to sensor
for (i=0;i<ACK_TIME_OUT;i++)
{
if(IIC_DAT_R==0) break; //wait until sensor has finished the measurement
//Modbus_Deal();
}
if(IIC_DAT_R) Error+=1; // or timeout (~2 sec.) is reached
//*(p_Value) = SHT_ReadByte(ACK); //read the first byte (MSB)
//*(p_Value+1) = SHT_ReadByte(ACK); //read the second byte (LSB)
TempH = SHT_ReadByte(ACK);
TempL = SHT_ReadByte(ACK);
*p_Value = TempH * 256 + TempL;
*p_CheckSum = SHT_ReadByte(NOACK); //read checksum
return Error;
}
/* ---- SHT传感器初始化 ---- */
void SHT_Init(void)
{
IIC_OUT &= ~IIC_DAT;
IIC_DIR |= IIC_SCK;
}
/* ---- 数据转换函数 ---- */
//----------------------------------------------------------------------------------------
void SHT_Calc_STH1x(float *p_humidity ,float *p_temperature)
//----------------------------------------------------------------------------------------
// calculates temperature [癈] and humidity [%RH]
// input : humi [Ticks] (12 bit)
// temp [Ticks] (14 bit)
// output: humi [%RH]
// temp [癈]
{ const float C1=-4.0; // for 12 Bit
const float C2=+0.0405; // for 12 Bit
const float C3=-0.0000028; // for 12 Bit
const float T1=+0.01; // for 14 Bit @ 5V
const float T2=+0.00008; // for 14 Bit @ 5V
float rh=*p_humidity; // rh: Humidity [Ticks] 12 Bit
float t=*p_temperature; // t: Temperature [Ticks] 14 Bit
float rh_lin; // rh_lin: Humidity linear
float rh_true; // rh_true: Temperature compensated humidity
float t_C; // t_C : Temperature [癈]
t_C=t*0.01 - 40; //calc. temperature from ticks to [癈]
rh_lin=C3*rh*rh + C2*rh + C1; //calc. humidity from ticks to [%RH]
rh_true=(t_C-25)*(T1+T2*rh)+rh_lin; //calc. temperature compensated humidity [%RH]
if(rh_true>100)rh_true=100; //cut if the value is outside of
if(rh_true<0.1)rh_true=0.1; //the physical possible range
*p_temperature=t_C; //return temperature [癈]
*p_humidity=rh_true; //return humidity[%RH]
}
//--------------------------------------------------------------------
float SHT_Calc_Dewpoint(float h, float t)
//--------------------------------------------------------------------
// calculates dew point
// input: humidity [%RH], temperature [癈]
// output: dew point [癈]
{ float logEx,dew_point;
logEx=0.66077+7.5*t/(237.3+t)+(log10(h)-2);
dew_point = (logEx - 0.66077)*237.3/(0.66077+7.5-logEx);
return dew_point;
}
void SHT_MeasureTRHD(signed int *pTc, signed int *pRH, signed int *pDp)
{
unsigned char Error = 0;
unsigned char CheckSum;
signed int Sample_T;
signed int Sample_H;
float f_Tc;
float f_RH;
float f_Dp;
unsigned char StatusReg;
if (Flg_MeasureTcRH == FALSE) return;
// Sampling
Error += SHT_Measure_Temperature(&Sample_T, &CheckSum);
Error += SHT_Measure_Humidity(&Sample_H, &CheckSum);
Error += SHT_ReadStatusReg(&StatusReg, &CheckSum);
// Calc
f_RH = (float) Sample_H;
f_Tc = (float) Sample_T;
SHT_Calc_STH1x(&f_RH, &f_Tc);
f_Dp = SHT_Calc_Dewpoint(f_RH, f_Tc);
// Save
_DINT();
*pTc = (signed int)(f_Tc * 10);
*pRH = (signed int)(f_RH * 10);
*pDp = (signed int)(f_Dp * 10);
Status = STATUS_OK;
if (Error != 0){Status = STATUS_SENSORFAIL;}
else
{
if (StatusReg & BIT6)
{
Flg_BatteryLow = 1;
Status = STATUS_SENSORFAIL;
}
}
_EINT();
// Sensor Status
Flg_MeasureTcRH = FALSE;
}
void SHT_MeasureTRH(signed int *pTc, signed int *pRH)
{
unsigned char Error = 0;
unsigned char CheckSum;
signed int Sample_T;
signed int Sample_H;
float f_Tc;
float f_RH;
unsigned char StatusReg;
if (Flg_MeasureTcRH == FALSE) return;
Flg_MeasureTcRH = FALSE;
// Sampling
Error += SHT_Measure_Temperature(&Sample_T, &CheckSum);
Error += SHT_Measure_Humidity(&Sample_H, &CheckSum);
Error += SHT_ReadStatusReg(&StatusReg, &CheckSum);
// Calc
f_RH = (float) Sample_H;
f_Tc = (float) Sample_T;
SHT_Calc_STH1x(&f_RH, &f_Tc);
// Save
_DINT();
*pTc = (signed int)(f_Tc * 10);
*pRH = (signed int)(f_RH * 10);
// Sensor Status
Status = STATUS_OK;
if (Error != 0){Status = STATUS_SENSORFAIL;}
else
{
if (StatusReg & BIT6)
{
Flg_BatteryLow = 1;
Status = STATUS_SENSORFAIL;
}
}
_EINT();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -