100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > STM32 使用 SHT2x 温湿度传感器

STM32 使用 SHT2x 温湿度传感器

时间:2018-12-30 17:57:12

相关推荐

STM32 使用 SHT2x 温湿度传感器

简介

这TM的是个超级坑的通讯过程,虽然符合IIC通讯流程,但要是你直接用IIC通讯会发现完全不是这么回事。这个是在STM32F0系列单片机上使用的范例,可以正常读取温度和湿度,主机模式和轮询模式和寄存器配置都有实现。database.h 里面没啥东西,可以直接用#include "stm32f0xx.h"代替数据手册:点击查看

代码

SHT2x.h

#ifndef SHT2x_H#define SHT2x_H//---------- Includes ----------------------------------------------------------#include "I2C_HAL.h"#include "database.h"//---------- Defines -----------------------------------------------------------#define LITTLE_ENDIAN //一定要设置大小端,当设置错误会出现比较大的数据跳动typedef union {uint16_t u16;// element specifier for accessing whole u16int16_t i16;// element specifier for accessing whole i16struct {#ifdef LITTLE_ENDIAN // Byte-order is little endianuint8_t u8L; // element specifier for accessing low u8uint8_t u8H; // element specifier for accessing high u8#else // Byte-order is big endianuint8_t u8H; // element specifier for accessing low u8uint8_t u8L; // element specifier for accessing high u8#endif} s16; // element spec. for acc. struct with low or high u8} nt16;// Error codestypedef enum{ACK_ERROR= 0x01,TIME_OUT_ERROR = 0x02,CHECKSUM_ERROR = 0x04,UNIT_ERROR= 0x08}etError;// CRC#define SHT2xPOLYNOMIAL 0x131 //P(x)=x^8+x^5+x^4+1 = 100110001// sensor commandtypedef enum{TRIG_T_MEASUREMENT_HM = 0xE3, // command trig. temp meas. hold masterTRIG_RH_MEASUREMENT_HM = 0xE5, // command trig. humidity meas. hold masterTRIG_T_MEASUREMENT_POLL = 0xF3, // command trig. temp meas. no hold masterTRIG_RH_MEASUREMENT_POLL = 0xF5, // command trig. humidity meas. no hold masterUSER_REG_W= 0xE6, // command writing user registerUSER_REG_R= 0xE7, // command reading user registerSOFT_RESET= 0xFE // command soft reset}etSHT2xCommand;typedef enum {SHT2x_RES_12_14BIT = 0x00, // RH=12bit, T=14bitSHT2x_RES_8_12BIT = 0x01, // RH= 8bit, T=12bitSHT2x_RES_10_13BIT = 0x80, // RH=10bit, T=13bitSHT2x_RES_11_11BIT = 0x81, // RH=11bit, T=11bitSHT2x_RES_MASK = 0x81 // Mask for res. bits (7,0) in user reg.} etSHT2xResolution;typedef enum {SHT2x_EOB_ON = 0x40, // end of batterySHT2x_EOB_MASK = 0x40, // Mask for EOB bit(6) in user reg.} etSHT2xEob;typedef enum {SHT2x_HEATER_ON= 0x04, // heater onSHT2x_HEATER_OFF = 0x00, // heater offSHT2x_HEATER_MASK = 0x04, // Mask for Heater bit(2) in user reg.} etSHT2xHeater;// measurement signal selectiontypedef enum{HUMIDITY,TEMP}etSHT2xMeasureType;typedef enum{I2C_ADR_W= 128, // sensor I2C address + write bitI2C_ADR_R= 129 // sensor I2C address + read bit}etI2cHeader;uint8_t SHT2x_ReadUserRegister(uint8_t *pRegisterValue);uint8_t SHT2x_WriteUserRegister(uint8_t *pRegisterValue);void SHT2x_InitUserRegister(void);uint8_t SHT2x_MeasureHM(etSHT2xMeasureType eSHT2xMeasureType, nt16 *pMeasurand);float SHT2x_CalcRH(uint16_t u16sRH);float SHT2x_CalcTemperatureC(uint16_t u16sT);void SHT2x_Process();#endif

SHT2x.c

//==============================================================================// SH2x 温湿度采集程序//==============================================================================// File: SHT2x.c// Author : MC// Compiler : Keil 5//==============================================================================//---------- Includes ----------------------------------------------------------#include "SHT2x.h"#include <assert.h>// assert functions/*校验data 校验的数据nbrOfBytes 数据长度checksum 校验对比数返回 0 成功 CHECKSUM_ERROR 4 失败*///==============================================================================uint8_t SHT2x_CheckCrc(uint8_t data[], uint8_t nbrOfBytes, uint8_t checksum)//=============================================================================={uint8_t crc = 0;uint8_t byteCtr;//calculates 8-Bit checksum with given polynomialfor (byteCtr = 0; byteCtr < nbrOfBytes; ++byteCtr){crc ^= (data[byteCtr]);for (uint8_t bit = 8; bit > 0; --bit){if (crc & 0x80) crc = (crc << 1) ^ SHT2xPOLYNOMIAL;else crc = (crc << 1);}}if (crc != checksum) return CHECKSUM_ERROR;else return 0;}/*轮询模式采集温湿度eSHT2xMeasureType 需要采集的项, HUMIDITY湿度 TEMP温度pMeasurand 采集回来的原始值*///===========================================================================uint8_t SHT2x_MeasurePoll(etSHT2xMeasureType eSHT2xMeasureType, nt16 *pMeasurand)//==========================================================================={uint8_t checksum; //checksumuint8_t data[2]; //data array for checksum verificationuint8_t error=0; //error variableuint16_t i=0; //counting variable//-- write I2C sensor address and command --I2c_StartCondition();I2c_WriteByte (I2C_ADR_W); // I2C AdrIIC_Wait_Ack();switch(eSHT2xMeasureType){case HUMIDITY: I2c_WriteByte (TRIG_RH_MEASUREMENT_POLL); break;case TEMP : I2c_WriteByte (TRIG_T_MEASUREMENT_POLL); break;}IIC_Wait_Ack();//-- poll every 10ms for measurement ready. Timeout after 20 retries (200ms)--do{delay_us(10000); //delay 10msI2c_StartCondition();I2c_WriteByte(I2C_ADR_R);if(i++ >= 20) break;} while(IIC_Wait_Ack());if (i>=20) error |= TIME_OUT_ERROR;//-- read two data bytes and one checksum byte --pMeasurand->s16.u8H = data[0] = I2c_ReadByte(ACK);pMeasurand->s16.u8L = data[1] = I2c_ReadByte(ACK);checksum=I2c_ReadByte(NO_ACK);I2c_StopCondition();//-- verify checksum --error |= SHT2x_CheckCrc (data,2,checksum);return error;}/*主机模式采集温度或适度eSHT2xMeasureType 需要采集的项, HUMIDITY湿度 TEMP温度pMeasurand 采集回来的原始值*///===========================================================================uint8_t SHT2x_MeasureHM(etSHT2xMeasureType eSHT2xMeasureType, nt16 *pMeasurand)//==========================================================================={uint8_t checksum; //checksumuint8_t data[2]; //data array for checksum verificationuint8_t error=0; //error variableuint16_t i;//counting variable//-- write I2C sensor address and command --I2c_StartCondition();error |= I2c_WriteByte (I2C_ADR_W); // I2C AdrIIC_Wait_Ack();switch(eSHT2xMeasureType){case HUMIDITY: I2c_WriteByte(TRIG_RH_MEASUREMENT_HM); break;case TEMP : I2c_WriteByte(TRIG_T_MEASUREMENT_HM); break;default: assert(0);}IIC_Wait_Ack();I2c_StartCondition();I2c_WriteByte (I2C_ADR_R);IIC_Wait_Ack();//-- read two data bytes and one checksum byte --pMeasurand->s16.u8H = data[0] = I2c_SHT21WithSCLReadByte(ACK);pMeasurand->s16.u8L = data[1] = I2c_ReadByte(ACK);checksum=I2c_ReadByte(NO_ACK);I2c_StopCondition();// //-- verify checksum --error |= SHT2x_CheckCrc (data,2,checksum);return error;}/*原始值转换为湿度u16sRH 原始值返回 湿度*///==============================================================================float SHT2x_CalcRH(uint16_t u16sRH)//=============================================================================={float humidityRH; // variable for resultu16sRH &= ~0x0003;// clear bits [1..0] (status bits)//-- calculate relative humidity [%RH] --humidityRH = -6.0 + (125.0*(float)u16sRH)/65536; // RH= -6 + 125 * SRH/2^16return humidityRH;}/*原始值转换为温度u16sRH 原始值返回 温度*///==============================================================================float SHT2x_CalcTemperatureC(uint16_t u16sT)//=============================================================================={float temperatureC; // variable for resultu16sT &= ~0x0003; // clear bits [1..0] (status bits)//-- calculate temperature --temperatureC= -46.85 + (175.72*(float)u16sT)/65536; //T= -46.85 + 175.72 * ST/2^16return temperatureC;}/*读取用户寄存器pRegisterValue 存放数据的指针返回 0 成功 CHECKSUM_ERROR 4 失败*///===========================================================================uint8_t SHT2x_ReadUserRegister(uint8_t *pRegisterValue)//==========================================================================={uint8_t checksum; //variable for checksum byteuint8_t error=0; //variable for error codeI2c_StartCondition();error |= I2c_WriteByte (I2C_ADR_W);IIC_Wait_Ack();error |= I2c_WriteByte (USER_REG_R);IIC_Wait_Ack();I2c_StartCondition();error |= I2c_WriteByte (I2C_ADR_R);IIC_Wait_Ack();*pRegisterValue = I2c_ReadByte(NO_ACK);I2c_StopCondition();return error;}/*写入用户寄存器pRegisterValue 待写入的数返回 0 成功 CHECKSUM_ERROR 4 失败*///===========================================================================uint8_t SHT2x_WriteUserRegister(uint8_t *pRegisterValue)//==========================================================================={uint8_t error=0; //variable for error codeI2c_StartCondition();error |= I2c_WriteByte (I2C_ADR_W);IIC_Wait_Ack();error |= I2c_WriteByte (USER_REG_W);IIC_Wait_Ack();error |= I2c_WriteByte (*pRegisterValue);IIC_Wait_Ack();I2c_StopCondition();return error;}/*初始化用户寄存器*///===========================================================================void SHT2x_InitUserRegister(void)//==========================================================================={uint8_t userRegister=0;userRegister = 0x00;//(userRegister & ~SHT2x_RES_MASK) | SHT2x_RES_10_13BIT;SHT2x_WriteUserRegister(&userRegister); //write changed user reg}/*用户线程*/nt16 sRH={0};//variable for raw humidity ticksnt16 sT={0}; //variable for raw temperature ticksvoid SHT2x_Process(){int ret;SHT2x_ReadUserRegister(&WorkUnion.input.userRegister); //get actual user regret=SHT2x_MeasureHM(TEMP, &sT);WorkUnion.input.Tempreture=SHT2x_CalcTemperatureC(sT.u16);delay_ms(100);ret=SHT2x_MeasureHM(HUMIDITY, &sRH);WorkUnion.input.Humidity=SHT2x_CalcRH(sRH.u16);//if(ret==0)}

I2C_HAL.h

#ifndef I2C_HAL_H#define I2C_HAL_H#ifndef I2C_HAL_H#define I2C_HAL_H//---------- Includes ----------------------------------------------------------#include "database.h"//---------- Defines -----------------------------------------------------------//IO口操作宏定义#define GPIOSCL GPIOA#define PinSCL GPIO_Pin_2#define GPIOSDA GPIOA#define PinSDA GPIO_Pin_3//IO方向设置#define SDA_IN() {GPIOA->MODER&=0XFFFFFF3F;}#define SDA_OUT() {uint32_t Temp=GPIOA->MODER;\Temp&=0XFFFFFF3F;\Temp|=0x00000040;\GPIOA->MODER=Temp;}#define SCL_IN() {GPIOA->MODER&=0XFFFFFFCF;}#define SCL_OUT() {uint32_t Temp=GPIOA->MODER;\Temp&=0XFFFFFFCF;\Temp|=0x00000010;\GPIOA->MODER=Temp;}//IO操作函数 #define IIC_SCL1 GPIO_SetBits(GPIOSCL,PinSCL)#define IIC_SCL0 GPIO_ResetBits(GPIOSCL,PinSCL) //SCL#define IIC_SDAx(x) GPIO_WriteBit(GPIOSDA,PinSDA,x)#define IIC_SDA1 GPIO_SetBits(GPIOSDA,PinSDA) //SDA #define IIC_SDA0 GPIO_ResetBits(GPIOSDA,PinSDA) //SDA#define READ_SDA GPIO_ReadInputDataBit(GPIOSDA,PinSDA) //输入SDA #define READ_SCL GPIO_ReadInputDataBit(GPIOSDA,PinSCL) //输入SCL //---------- Enumerations ------------------------------------------------------// I2C leveltypedef enum{LOW = 0,HIGH = 1,}etI2cLevel;// I2C acknowledgetypedef enum{ACK = 0,NO_ACK = 1,}etI2cAck;//==============================================================================void I2c_Init ();//==============================================================================//Initializes the ports for I2C interface//==============================================================================void I2c_StartCondition ();//==============================================================================// writes a start condition on I2C-bus// input : -// output: -// return: -// note : timing (delay) may have to be changed for different microcontroller// _____// SDA: |_____// _______// SCL : |___//==============================================================================void I2c_StopCondition ();//==============================================================================// writes a stop condition on I2C-bus// input : -// output: -// return: -// note : timing (delay) may have to be changed for different microcontroller// _____// SDA: _____|// _______// SCL : ___|//===========================================================================uint8_t I2c_WriteByte (uint8_t txByte);//===========================================================================// writes a byte to I2C-bus and checks acknowledge// input: txByte transmit byte// output: -// return: error// note: timing (delay) may have to be changed for different microcontroller//===========================================================================uint8_t I2c_ReadByte (etI2cAck ack);//===========================================================================// reads a byte on I2C-bus// input: rxByte receive byte// output: rxByte// note: timing (delay) may have to be changed for different microcontrolleru8 IIC_Wait_Ack(void);uint8_t I2c_SHT21WithSCLReadByte(etI2cAck ack);#endif

I2C_HAL.c

//---------- Includes ----------------------------------------------------------#include "I2C_HAL.h"//==============================================================================void I2c_Init ()//=============================================================================={GPIO_InitTypeDef GPIO_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA , ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;GPIO_Init(GPIOA, &GPIO_InitStructure);IIC_SDA0;// Set port as output for configurationIIC_SCL0;// Set port as output for configurationSDA_OUT(); // Set SDA level as low for output modeSCL_OUT();IIC_SDA1;// I2C-bus idle mode SDA released (input)IIC_SCL1;// I2C-bus idle mode SCL released (input)}//==============================================================================void I2c_StartCondition ()//=============================================================================={SDA_OUT();SCL_OUT();IIC_SDA1;IIC_SCL1;delay_us(20); // hold time start condition (t_HD;STA)IIC_SDA0;delay_us(20); // hold time start condition (t_HD;STA)IIC_SCL0;delay_us(20);}//==============================================================================void I2c_StopCondition ()//=============================================================================={SDA_OUT();SCL_OUT();IIC_SDA0;IIC_SCL0;delay_us(20); // set-up time stop condition (t_SU;STO)IIC_SCL1;delay_us(20); // set-up time stop condition (t_SU;STO)IIC_SDA1;delay_us(20);}//不产生ACK应答 void IIC_NAck(void){SCL_OUT();SDA_OUT();IIC_SCL0;IIC_SDA1;delay_us(10);IIC_SCL1;delay_us(10);IIC_SCL0;}//产生ACK应答void IIC_Ack(void){SCL_OUT();SDA_OUT();IIC_SCL0;IIC_SDA0;delay_us(10);IIC_SCL1;delay_us(10);IIC_SCL0;} //等待应答信号到来//返回值:1,接收应答失败// 0,接收应答成功u8 IIC_Wait_Ack(void){u8 ucErrTime=0;SDA_IN();//SDA设置为输入 IIC_SCL1;delay_us(5); while(READ_SDA){ucErrTime++;if(ucErrTime>250){//I2c_StopCondition();return 1;}delay_us(100);}IIC_SCL0;//时钟输出0 return 0; } //==============================================================================uint8_t I2c_WriteByte (uint8_t txByte)//=============================================================================={uint8_t mask,error=0;u8 t;SCL_OUT();SDA_OUT();IIC_SCL0;//拉低时钟开始数据传输for(t=0;t<8;t++){IIC_SDAx((txByte&0x80)>>7);txByte<<=1; delay_us(10); //对TEA5767这三个延时都是必须的IIC_SCL1;delay_us(10); IIC_SCL0;delay_us(10);}return error; //return error code}//==============================================================================uint8_t I2c_ReadByte (etI2cAck ack)//=============================================================================={unsigned char i,receive=0;SCL_OUT();SDA_IN();//SDA设置为输入for(i=0;i<8;i++ ){IIC_SCL0; delay_us(5);IIC_SCL1;receive<<=1;if(READ_SDA)receive++; delay_us(5); } if (ack==ACK)IIC_Ack(); //发送ACK elseIIC_NAck();//发送nACKreturn receive;}//==============================================================================uint8_t I2c_SHT21WithSCLReadByte(etI2cAck ack)//=============================================================================={uint16_t i;unsigned char receive=0;SCL_IN(); // set SCL I/O port as inputSDA_IN();for(i=0; i<10000; i++) // wait until master hold is released or{delay_us(10); // a timeout (~1s) is reachedif (READ_SCL==1){if(READ_SDA)receive++; break;}}SCL_OUT();SDA_IN();//SDA设置为输入for(i=0;i<7;i++ ){IIC_SCL0; delay_us(5);IIC_SCL1;receive<<=1;if(READ_SDA)receive++; delay_us(5); } if (ack==ACK)IIC_Ack(); //发送ACK elseIIC_NAck();//发送nACKreturn receive;}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。