📄 sht75.c
字号:
//-----------------------------------------------------------------
// 名称: SHT75传感器程序(参照SENSIRION公司提供的8051版代码改编)
//-----------------------------------------------------------------
#define _XTAL_FREQ 4000000UL
#define INT8U unsigned char
#define INT16U unsigned int
#include <pic.h>
#include <stdio.h>
#include <math.h>
//传感器引脚相关定义
#define SCL RB0
#define SDA RB1
#define SDA_IN() TRISB1 = 1 //设SDA数据方向为输入
#define SDA_OUT() TRISB1 = 0 //设SDA数据方向为输出
//SHT75传感器命令集 //地址 命令 读/写
#define MEASURE_TEMP 0x03 //000 0001 1
#define MEASURE_HUMI 0x05 //000 0010 1
#define STATUS_REG_W 0x06 //000 0011 0
#define STATUS_REG_R 0x07 //000 0011 1
#define RESET 0x1E //000 1111 0
//是否应答
#define NACK 0
#define ACK 1
//温湿度信息显示缓冲
char HT_Display_Buffer[20];
//定义温度与湿度符号
enum {TEMP,HUMI};
extern void PutStr(char *s);
//-----------------------------------------------------------------
// 写一节到SHT75并检查应答
//-----------------------------------------------------------------
INT8U s_Write_Byte(INT8U dat)
{
}
//-----------------------------------------------------------------
// 从传感器读一字节,在ack=1时发送应答
//-----------------------------------------------------------------
INT8U s_Read_Byte(INT8U ack)
{
}
//-----------------------------------------------------------------
// 传输开始
//-----------------------------------------------------------------
void s_TransStart()
{
//以下语句序列模拟传输开始的操作时序
SDA = 1;
SCL = 0; __delay_us(1); SCL = 1; __delay_us(1); SDA = 0; __delay_us(1);
SCL = 0; __delay_us(3); SCL = 1; __delay_us(1); SDA = 1; __delay_us(1);
SCL = 0;
}
//-----------------------------------------------------------------
// 传感器连接复位
//-----------------------------------------------------------------
void s_ConnectionReset()
{
INT8U i;
SDA = 1; SCL = 0; //初始状态
for(i = 0; i < 9; i++) {SCL = 1; SCL = 0;} //模拟9个时钟周期
s_TransStart(); //传输开始
}
//-----------------------------------------------------------------
// 传感器软复位
//-----------------------------------------------------------------
INT8U s_SoftReset()
{
INT8U error = 0;
s_ConnectionReset(); //连接通讯复位
error += s_Write_Byte(RESET); //向传感器发送复位命令
return error; //传感器无响应时返回1
}
//-----------------------------------------------------------------
// 读状态寄存器
//-----------------------------------------------------------------
INT8U s_Read_StatusReg(INT8U *p_value, INT8U *p_checksum)
{
INT8U error = 0;
s_TransStart(); //传输开始
error = s_Write_Byte(STATUS_REG_R); //向传感器发送命令STATUS_REG_R
*p_value = s_Read_Byte(ACK); //读状态寄存器(8位)
*p_checksum = s_Read_Byte(NACK); //读取校验和(8位)
return error; //传感器无响应时返回1
}
//-----------------------------------------------------------------
// 写状态寄存器
//-----------------------------------------------------------------
INT8U s_Write_StatusReg(INT8U *p_value)
{
INT8U error = 0;
s_TransStart(); //传输开始
error += s_Write_Byte(STATUS_REG_W); //向传感器发送命令STATUS_REG_W
error += s_Write_Byte(*p_value); //发送状态寄存器的值
return error; //传感器无响应时返回1
}
//-----------------------------------------------------------------
// 带校验码的温度与湿度测量
//-----------------------------------------------------------------
INT8U s_Measure(INT8U *p_value, INT8U *p_checksum, INT8U mode)
{
INT8U i = 0, error = 0;
s_TransStart(); //传输开始
switch(mode) //向传感器发送命令
{ case TEMP : error += s_Write_Byte(MEASURE_TEMP); break;
case HUMI : error += s_Write_Byte(MEASURE_HUMI); break;
default : break;
}
SDA_IN();
while (SDA && ++i < 40) __delay_ms(100);
if(SDA) error+=1; //超时
*(p_value) = s_Read_Byte(ACK); //读第一字节(MSB)
*(p_value + 1) = s_Read_Byte(ACK); //读第二字节(LSB)
*p_checksum = s_Read_Byte(NACK); //读校验和
return error;
}
//-----------------------------------------------------------------
// 计算温湿度
//-----------------------------------------------------------------
void Calc_STH75(float *p_humidity ,float *p_temperature)
{
const float C1 = -4.0; //12位,系数C1
const float C2 = +0.0405; //12位,系数C2
const float C3 = -0.0000028; //12位,系数C3
const float T1 = +0.01; //14位 @ 5V ,系数T1
const float T2 = +0.00008; //14位 @ 5V ,系数T2
float rh = *p_humidity; // rh: 湿度 12 Bit
float t = *p_temperature; // t: 温度 14 Bit
float rh_lin; // rh_lin: 线性湿度
float rh_true; // rh_true: 温度补偿湿度
float t_C; // t_C : 温度(℃)
t_C = t * 0.01 - 40; //计算温度
rh_lin = C3 * rh * rh + C2 * rh + C1; //计算湿度
rh_true=(t_C - 25) * (T1 + T2 * rh) + rh_lin; //计算:温度补偿湿度
if(rh_true > 100) rh_true = 100; //将湿度数据限制在可能的范围之内
if(rh_true < 0.1) rh_true = 0.1; //即0.1% ~ 100%
*p_temperature = t_C; //返回温度[℃]
*p_humidity = rh_true; //返回湿度[%RH]
}
//--------------------------------------------------------------------
// 根据输入的湿度与温度计算露点
//--------------------------------------------------------------------
float Calc_Dew_point(float h,float t)
{
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;
}
//--------------------------------------------------------------------
// 延时函数(n x 100ms)
//--------------------------------------------------------------------
void delayX100ms(INT8U n)
{
while (n--) __delay_ms(100);
}
//--------------------------------------------------------------------
// 传感器测试(读取湿度与温度数据并进行转换计算,送虚拟终端显示)
//--------------------------------------------------------------------
void Temp_and_Humi_Sensors_Test()
{
INT8U a[2],b[2]; //读传感器湿度与温度,各两字节
float x,y,d; //计算转换后的湿度,温度,露点
INT8U error,checksum; //错误及校验和
s_ConnectionReset(); //连接复位
while(1)
{ error = 0;
error += s_Measure((INT8U*)a, &checksum, HUMI); //测量湿度
error += s_Measure((INT8U*)b, &checksum, TEMP); //测量温度
if(error !=0 ) s_ConnectionReset(); //出错时传感器连接复位
else
{ x = (float)(a[0] * 256.0 + a[1]); //将两字节温度转换为float类型
y = (float)(b[0] * 256.0 + b[1]); //将两字节湿度转换为float类型
Calc_STH75(&x,&y); //计算湿度与温度
d = Calc_Dew_point(x,y); //计算露点
//生成指定格式的待输出字符串(GCC中sprintf不支持%f输出,因此需要转换)
sprintf(HT_Display_Buffer,"HUMI:%5d.%1d%% TEMP:%5d.%1d DEW:%5d.%1d\r",
(int)x, (int)(fabs(x-(int)x)*10),
(int)y, (int)(fabs(y-(int)y)*10),
(int)d, (int)(fabs(d-(int)d)*10));
PutStr(HT_Display_Buffer); //向虚拟终端输出结果
}
//延时近0.8s,以免传感器过热
delayX100ms(8);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -