完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
功能介绍:读取传感器SHT85数据,转换成温度、湿度 、饱和水蒸气含量。
注意事项: SDA脚设置为开漏输出,外部上拉电阻10k。或者设置成推挽,软件切换SDA输入输出。 调试时可适当加长延时时间。 在while(1)循环之前调用 TH_Class_SHT85.init(),每隔1S调用一次TH_Class_SHT85.loop()。 代码 SHT85驱动.7z SHT85.h #ifndef __SHT85_H__ #define __SHT85_H__ #include "main.h" #define CRC_POLYNOMIAL 0x131 // P(x) = x^8 + x^5 + x^4 + 1 = 100110001 #define I2C_ADDR 0x44 //SHT85地址 /****************************错误码***************************/ #define NO_ERROR 0x00 #define ACK_ERROR 0x01 #define CHECKSUM_ERROR 0x02 #define TIMEOUT_ERROR 0x04 /****************************IIC错误码***************************/ typedef enum{ ACK = 0, NO_ACK = 1, }etI2cAck; /****************************CMD定义***************************/ typedef enum { CMD_READ_SERIALNBR = 0x3780, // read serial number CMD_READ_STATUS = 0xF32D, // read status register CMD_CLEAR_STATUS = 0x3041, // clear status register CMD_HEATER_ENABLE = 0x306D, // enabled heater CMD_HEATER_DISABLE = 0x3066, // disable heater CMD_SOFT_RESET = 0x30A2, // soft reset CMD_MEAS_SINGLE_H = 0x2400, // single meas., high repeatability CMD_MEAS_SINGLE_M = 0x240B, // single meas., medium repeatability CMD_MEAS_SINGLE_L = 0x2416, // single meas., low repeatability CMD_MEAS_PERI_05_H = 0x2032, // periodic meas. 0.5 mps, high repeatability CMD_MEAS_PERI_05_M = 0x2024, // periodic meas. 0.5 mps, medium repeatability CMD_MEAS_PERI_05_L = 0x202F, // periodic meas. 0.5 mps, low repeatability CMD_MEAS_PERI_1_H = 0x2130, // periodic meas. 1 mps, high repeatability CMD_MEAS_PERI_1_M = 0x2126, // periodic meas. 1 mps, medium repeatability CMD_MEAS_PERI_1_L = 0x212D, // periodic meas. 1 mps, low repeatability CMD_MEAS_PERI_2_H = 0x2236, // periodic meas. 2 mps, high repeatability CMD_MEAS_PERI_2_M = 0x2220, // periodic meas. 2 mps, medium repeatability CMD_MEAS_PERI_2_L = 0x222B, // periodic meas. 2 mps, low repeatability CMD_MEAS_PERI_4_H = 0x2334, // periodic meas. 4 mps, high repeatability CMD_MEAS_PERI_4_M = 0x2322, // periodic meas. 4 mps, medium repeatability CMD_MEAS_PERI_4_L = 0x2329, // periodic meas. 4 mps, low repeatability CMD_MEAS_PERI_10_H = 0x2737, // periodic meas. 10 mps, high repeatability CMD_MEAS_PERI_10_M = 0x2721, // periodic meas. 10 mps, medium repeatability CMD_MEAS_PERI_10_L = 0x272A, // periodic meas. 10 mps, low repeatability CMD_FETCH_DATA = 0xE000, // readout measurements for periodic mode CMD_BREAK = 0x3093, // stop periodic measurement }etCommands; // Single Shot Measurement Repeatability typedef enum { SINGLE_MEAS_LOW = CMD_MEAS_SINGLE_L, // low repeatability SINGLE_MEAS_MEDIUM = CMD_MEAS_SINGLE_M, // medium repeatability SINGLE_MEAS_HIGH = CMD_MEAS_SINGLE_H // high repeatability }etSingleMeasureModes; // Periodic Measurement Configurations typedef enum { PERI_MEAS_LOW_05_HZ = CMD_MEAS_PERI_05_L, PERI_MEAS_LOW_1_HZ = CMD_MEAS_PERI_1_L, PERI_MEAS_LOW_2_HZ = CMD_MEAS_PERI_2_L, PERI_MEAS_LOW_4_HZ = CMD_MEAS_PERI_4_L, PERI_MEAS_LOW_10_HZ = CMD_MEAS_PERI_10_L, PERI_MEAS_MEDIUM_05_HZ = CMD_MEAS_PERI_05_M, PERI_MEAS_MEDIUM_1_HZ = CMD_MEAS_PERI_1_M, PERI_MEAS_MEDIUM_2_HZ = CMD_MEAS_PERI_2_M, PERI_MEAS_MEDIUM_4_HZ = CMD_MEAS_PERI_4_M, PERI_MEAS_MEDIUM_10_HZ = CMD_MEAS_PERI_10_M, PERI_MEAS_HIGH_05_HZ = CMD_MEAS_PERI_05_H, PERI_MEAS_HIGH_1_HZ = CMD_MEAS_PERI_1_H, PERI_MEAS_HIGH_2_HZ = CMD_MEAS_PERI_2_H, PERI_MEAS_HIGH_4_HZ = CMD_MEAS_PERI_4_H, PERI_MEAS_HIGH_10_HZ = CMD_MEAS_PERI_10_H, }etPeriodicMeasureModes; /****************************温湿度传感器结构体定义**************************/ typedef struct _TH_Class{ u32 SerialNumber;//传感器SN号 float Temperature;//温度 float Humidity;//相对湿度 float H2O;//绝对湿度 void (*init)(void);//初始化函数指针 void (*loop)(void);//loop函数指针,循环读取温湿度,周期:1S }TH_Class_t; extern TH_Class_t TH_Class_SHT85; #endif SHT85.c /******************************************** *Filename: SHT85.c *Revised: Date: 06-22 14:42 *Author: SYMBEL *Description: SHT85驱动 *********************************************/ #include "SHT85.h" #include /****************************IIC引脚定义**************************/ #define SHT85_SCL(x) HAL_GPIO_WritePin(SHT85_SCK_GPIO_Port, SHT85_SCK_Pin, x?GPIO_PIN_SET:GPIO_PIN_RESET) #define SHT85_SDA(x) HAL_GPIO_WritePin(SHT85_SDA_GPIO_Port, SHT85_SDA_Pin, x?GPIO_PIN_SET:GPIO_PIN_RESET) #define IS_SHT85_SDA() HAL_GPIO_ReadPin(SHT85_SDA_GPIO_Port, SHT85_SDA_Pin) //读取SDA脚电平 /****************************IIC引脚定义**************************/ /*****************************函数声明***************************/ static u8 StartWriteAccess(void); static u8 StartReadAccess(void); static void StopAccess(void); static u8 WriteCommand(etCommands command); static u8 Read2BytesAndCrc(uint16_t* data, bool finAck, uint8_t timeout); static uint8_t CalcCrc(uint8_t data[], uint8_t nbrOfBytes); static u8 CheckCrc(uint8_t data[], uint8_t nbrOfBytes, uint8_t checksum); static float CalcTemperature(uint16_t rawValue); static float CalcHumidity(uint16_t rawValue); void SHT85_Init(void); void SHT85_FSM(void); /****************************结构体初始化**************************/ TH_Class_t TH_Class_SHT85 = { .SerialNumber = 0, .Temperature = 0.0f, .Humidity = 0.0f, .H2O = 0.0f, .init = SHT85_Init, .loop = SHT85_FSM, }; /********************************************************** *函数:DelayUs *功能:延时1us *参数:us:延时时间 单位:us *返回:无 *描述:无 **********************************************************/ static void DelayUs(u32 us) { for(int i=0; i __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP(); __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP(); __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP(); __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP(); __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP(); __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP(); __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP(); __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP(); } } static void I2c_StartCondition(void) { SHT85_SDA(1); SHT85_SCL(1); DelayUs(3); SHT85_SDA(0); DelayUs(3); SHT85_SCL(0); DelayUs(3); } static void I2c_StopCondition(void) { SHT85_SDA(0); SHT85_SCL(0); DelayUs(2); SHT85_SCL(1); DelayUs(3); SHT85_SDA(1); DelayUs(3); } static u8 I2c_WriteByte(uint8_t txByte) { uint8_t mask,error=0,i; // SHT85_SDA(0); for(i=1;i<20;i++); for(mask=0x80; mask>0; mask>>=1)//shift bit for masking (8 times) { if ((mask & txByte) == 0) SHT85_SDA(0); //masking txByte, write bit to SDA-Line else SHT85_SDA(1); DelayUs(1); //data hold time(t_HD;DAT) SHT85_SCL(1); //generate clock pulse on SCL DelayUs(1); //data set-up time (t_SU;DAT) SHT85_SCL(0); DelayUs(1); //SCL high time (t_HIGH) } error = IS_SHT85_SDA(); //release SDA-line SHT85_SCL(1); //clk #9 for ack DelayUs(1); //data set-up time (t_SU;DAT) error = IS_SHT85_SDA(); SHT85_SCL(0); DelayUs(3); //wait time to see byte package on scope return error; //return error code } static uint8_t I2c_ReadByte(etI2cAck ack) { uint8_t mask,rxByte=0,i,rxb; SHT85_SDA(1); rxb = IS_SHT85_SDA(); //release SDA-line for(i=1;i<20;i++); for(mask=0x80; mask>0; mask>>=1)//shift bit for masking (8 times) { SHT85_SCL(1); //start clock on SCL-line DelayUs(2); //data set-up time (t_SU;DAT) rxb = IS_SHT85_SDA(); if(rxb) rxByte=(rxByte | mask); //read bit SHT85_SCL(0); DelayUs(2); //data hold time(t_HD;DAT) } if(ack == ACK) SHT85_SDA(0); else SHT85_SDA(1); DelayUs(2); //data set-up time (t_SU;DAT) SHT85_SCL(1); //clk #9 for ack DelayUs(5); //SCL high time (t_HIGH) SHT85_SCL(0); //SHT85_SDA(1); //release SDA-line DelayUs(2); //wait time to see byte package on scope return rxByte; //return error code } u8 I2c_GeneralCallReset(void) { u8 error; I2c_StartCondition(); error = I2c_WriteByte(0x00); if(error == NO_ERROR) { error = I2c_WriteByte(0x06); } return error; } u8 SHT85_ReadSerialNumber(uint32_t* serialNumber) { u8 error; // error code uint16_t serialNumWords[2]; error = StartWriteAccess(); // write "read serial number" command if(error == NO_ERROR) { error = WriteCommand(CMD_READ_SERIALNBR); } // if no error, start read access if(error == NO_ERROR) { error = StartReadAccess(); } // if no error, read first serial number word if(error == NO_ERROR) { error = Read2BytesAndCrc(&serialNumWords[0], true, 100); } // if no error, read second serial number word if(error == NO_ERROR) { error = Read2BytesAndCrc(&serialNumWords[1], false, 0); } StopAccess(); // if no error, calc serial number as 32-bit integer if(error == NO_ERROR) { *serialNumber = (serialNumWords[0] << 16) | serialNumWords[1]; } return error; } u8 SHT85_ReadStatus(uint16_t* status) { u8 error; // error code error = StartWriteAccess(); // if no error, write "read status" command if(error == NO_ERROR) { error = WriteCommand(CMD_READ_STATUS); } // if no error, start read access if(error == NO_ERROR) { error = StartReadAccess(); } // if no error, read status if(error == NO_ERROR) { error = Read2BytesAndCrc(status, false, 0); } StopAccess(); return error; } u8 SHT85_ClearAllAlertFlags(void) { u8 error; // error code error = StartWriteAccess(); // if no error, write clear status register command if(error == NO_ERROR) { error = WriteCommand(CMD_CLEAR_STATUS); } StopAccess(); return error; } u8 SHT85_SingleMeasurment(float* temperature, float* humidity, etSingleMeasureModes measureMode, uint8_t timeout) { u8 error; // error code uint16_t rawValueTemp; // temperature raw value from sensor uint16_t rawValueHumi; // humidity raw value from sensor error = StartWriteAccess(); // if no error if(error == NO_ERROR) { // start measurement error = WriteCommand((etCommands)measureMode); } // if no error, wait until measurement ready if(error == NO_ERROR) { // poll every 1ms for measurement ready until timeout while(timeout--) { // check if the measurement has finished error = StartReadAccess(); // if measurement has finished -> exit loop if(error == NO_ERROR) break; // delay 1ms DelayUs(1000); } // check for timeout error if(timeout == 0) { error = TIMEOUT_ERROR; } } // if no error, read temperature and humidity raw values if(error == NO_ERROR) { error |= Read2BytesAndCrc(&rawValueTemp, true, 0); error |= Read2BytesAndCrc(&rawValueHumi, false, 0); } StopAccess(); // if no error, calculate temperature in °C and humidity in %RH if(error == NO_ERROR) { *temperature = CalcTemperature(rawValueTemp); *humidity = CalcHumidity(rawValueHumi); } return error; } u8 SHT85_StartPeriodicMeasurment(etPeriodicMeasureModes measureMode) { u8 error; // error code error = StartWriteAccess(); // if no error, start periodic measurement if(error == NO_ERROR) { error = WriteCommand((etCommands)measureMode); } StopAccess(); return error; } u8 SHT85_StopPeriodicMeasurment(void) { u8 error; // error code error = StartWriteAccess(); // if no error, write breake command if(error == NO_ERROR) { error = WriteCommand(CMD_BREAK); } StopAccess(); return error; } u8 SHT85_ReadMeasurementBuffer(float* temperature, float* humidity) { u8 error; // error code uint16_t rawValueTemp; // raw temperature from sensor uint16_t rawValueHumi; // raw humidity from sensor error = StartWriteAccess(); // if no error, read measurements if(error == NO_ERROR) { error = WriteCommand(CMD_FETCH_DATA); } if(error == NO_ERROR) { error = StartReadAccess(); } if(error == NO_ERROR) { error = Read2BytesAndCrc(&rawValueTemp, true, 0); } if(error == NO_ERROR) { error = Read2BytesAndCrc(&rawValueHumi, false, 0); } // if no error, calculate temperature in °C and humidity in %RH if(error == NO_ERROR) { *temperature = CalcTemperature(rawValueTemp); *humidity = CalcHumidity(rawValueHumi); } StopAccess(); return error; } u8 SHT85_EnableHeater(void) { u8 error; // error code error = StartWriteAccess(); // if no error, write heater enable command if(error == NO_ERROR) { error = WriteCommand(CMD_HEATER_ENABLE); } StopAccess(); return error; } u8 SHT85_DisableHeater(void) { u8 error; // error code error = StartWriteAccess(); // if no error, write heater disable command if(error == NO_ERROR) { error = WriteCommand(CMD_HEATER_DISABLE); } StopAccess(); return error; } u8 SHT85_SoftReset(void) { u8 error; // error code error = StartWriteAccess(); // write reset command if(error == NO_ERROR) { error = WriteCommand(CMD_SOFT_RESET); } StopAccess(); // if no error, wait 50 ms after reset if(error == NO_ERROR) { DelayUs(50000); } return error; } static u8 StartWriteAccess(void) { u8 error; // error code // write a start condition I2c_StartCondition(); // write the sensor I2C address with the write flag error = I2c_WriteByte(I2C_ADDR << 1); return error; } static u8 StartReadAccess(void) { u8 error; // error code // write a start condition I2c_StartCondition(); // write the sensor I2C address with the read flag error = I2c_WriteByte(I2C_ADDR << 1|0x01); return error; } static void StopAccess(void) { // write a stop condition I2c_StopCondition(); } static u8 WriteCommand(etCommands command) { u8 error; // error code // write the upper 8 bits of the command to the sensor error = I2c_WriteByte(command >> 8); // write the lower 8 bits of the command to the sensor error |= I2c_WriteByte(command & 0xFF); return error; } static u8 Read2BytesAndCrc(uint16_t* data, bool finAck, uint8_t timeout) { u8 error; // error code uint8_t bytes[2]; // read data array uint8_t checksum; // checksum byte // read two data bytes and one checksum byte bytes[0] = I2c_ReadByte(ACK); bytes[1] = I2c_ReadByte(ACK); checksum = I2c_ReadByte(finAck ? ACK : NO_ACK); // verify checksum error = CheckCrc(bytes, 2, checksum); // combine the two bytes to a 16-bit value *data = (bytes[0] << 8) | bytes[1]; return error; } static uint8_t CalcCrc(uint8_t data[], uint8_t nbrOfBytes) { uint8_t bit; // bit mask uint8_t crc = 0xFF; // calculated checksum uint8_t byteCtr; // byte counter // calculates 8-Bit checksum with given polynomial for(byteCtr = 0; byteCtr < nbrOfBytes; byteCtr++) { crc ^= (data[byteCtr]); for(bit = 8; bit > 0; --bit) { if(crc & 0x80) { crc = (crc << 1) ^ CRC_POLYNOMIAL; } else { crc = (crc << 1); } } } return crc; } static u8 CheckCrc(uint8_t data[], uint8_t nbrOfBytes, uint8_t checksum) { // calculates 8-Bit checksum uint8_t crc = CalcCrc(data, nbrOfBytes); // verify checksum return (crc != checksum) ? CHECKSUM_ERROR : NO_ERROR; } /********************************************************** *函数:CalcTemperature *功能:温度转换 *参数:rawValue:温度采样值 *返回:温度,单位℃ *描述: **********************************************************/ static float CalcTemperature(uint16_t rawValue) { // calculate temperature [°C] // T = -45 + 175 * rawValue / (2^16-1) return 175.0f * (float)rawValue / 65535.0f - 45.0f; } /********************************************************** *函数:CalcHumidity *功能:相对湿度转换 *参数:rawValue:相对湿度采样值 *返回:相对湿度,单位% *描述: **********************************************************/ static float CalcHumidity(uint16_t rawValue) { // calculate relative humidity [%RH] // RH = rawValue / (2^16-1) * 100 return 100.0f * (float)rawValue / 65535.0f; } /********************************************************** *函数:FnTandRHToH2O *功能:饱和水蒸气含量计算 *参数:nInTemp:温度,单位℃ * nInRH: 相对湿度,单位% *返回:饱和水蒸气含量,单位℃ *描述: **********************************************************/ static float FnTandRHToH2O(float nInTemp, float nInRH) { float fCnH2O; //H2O含量 float fCnH2OMax; float fTemp; fTemp = nInTemp; fCnH2OMax = 0.0000008734* fTemp* fTemp* fTemp - 0.0000013617* fTemp* fTemp + 0.0004784740* fTemp + 0.0068091716; fCnH2O = nInRH*fCnH2OMax; return(fCnH2O); } /********************************************************** *函数:SHT85_Init *功能:SHT85初始化 *参数:无 *返回:无 *描述:IIC引脚初始化,读取SN,配置测量频率。 **********************************************************/ void SHT85_Init(void) { /*IIC引脚初始化。此程序使用STM32 HAL库,已在main()初始化*/ /*读取SN*/ SHT85_ReadSerialNumber(&TH_Class_SHT85.SerialNumber); /*设置测量频率*/ SHT85_StartPeriodicMeasurment(PERI_MEAS_MEDIUM_10_HZ); } /********************************************************** *函数:SHT85_FSM *功能:SHT85 loop函数 *参数:无 *返回:无 *描述:读取温度、相对湿度、计算饱和水蒸气含量。建议执行频率1Hz。 **********************************************************/ void SHT85_FSM(void) { /*读取温度、相对湿度*/ SHT85_ReadMeasurementBuffer(&TH_Class_SHT85.Temperature, &TH_Class_SHT85.Humidity); /*计算饱和水蒸气含量*/ TH_Class_SHT85.H2O = FnTandRHToH2O(TH_Class_SHT85.Temperature, TH_Class_SHT85.Humidity); } |
|
|
|
只有小组成员才能发言,加入小组>>
3308 浏览 9 评论
2988 浏览 16 评论
3490 浏览 1 评论
9049 浏览 16 评论
4083 浏览 18 评论
1167浏览 3评论
601浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
592浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2329浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1892浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-18 09:52 , Processed in 1.178555 second(s), Total 51, Slave 41 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号