Background
The project actually uses SHT3x for temperature and humidity measurement, the main control chip uses STM8S003F3P6, and uses the hardware connection of the analog IIC interface.
Schematic
As shown in the figure below, use STM8S003F3P6 pins PB4/PB5 for SHT3x data interface
SHT3x-DIS is Sensirion’s new generation temperature and humidity sensor with accuracy of ±2%RH and ±0.3℃, input voltage range from 2.4V to 5.5V, IIC bus interface, speed up to 1MHz. The measurement temperature and humidity ranges are -40°C ~ 125°C and 0 ~ 100%.
From the figure below, we can see that the humidity sensor and temperature sensor are integrated inside the SHT3x, which are sampled and input to the data processing and linearization unit through the ADC, and have a correction memory to deal with the influence of the environment on the device measurement. Read data via digital interface IIC. With an alarm pin, the threshold can be set by modifying the value of the register, and it will be set when the measured temperature and humidity exceed the threshold.
Software design
The basic configuration of STM8S003F3P6 is as follows
Clock configuration, the clock configuration must be mentioned here, if the clock configuration is not mentioned, the timing delay of the SHT3x analog IIC interface
it’s hard to judge
/************************************************ Function name: CLK_Configuration Function: clock configuration Parameters: none Return value: None Author: strongerHuang *****************************************************/ void CLK_Configuration(void) { /* ErrorStatus clk_return_status; CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV8); //HSI = 16M (8 frequency division)=2MHZ //Switch the internal low-speed clock 128khz clk_return_status = CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_LSI, DISABLE, CLK_CURRENTCLOCKSTATE_DISABLE); if (clk_return_status == SUCCESS) //SUCCESS or ERROR { CLK_ClockSwitchCmd(ENABLE); CLK_LSICmd(ENABLE); CLK_ClockSwitchCmd(DISABLE); }*/ // CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1); //HSI = 16M (1 frequency division) //ErrorStatus clk_return_status; CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1); //HSI = 16M (8 frequency division)=2MHZ /* //Switch the internal low-speed clock 8M clk_return_status = CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSE, DISABLE, CLK_CURRENTCLOCKSTATE_DISABLE); if (clk_return_status == SUCCESS) //SUCCESS or ERROR { CLK_ClockSwitchCmd(ENABLE); CLK_HSECmd(ENABLE); CLK_ClockSwitchCmd(DISABLE); }*/ CLK_DeInit();//Set as default value CLK_HSICmd(ENABLE);//Enable HSI CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);//HSI frequency division CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1);//CPU frequency division }
The pin operation macro definition using IIC pin PB4/PB5 is as follows
#define SHT30_SCL (0x01<<4) #define SHT30_SDA (0x01<<5) #define SHT30_SCL0_O GPIOB->DDR |= SHT30_SCL; GPIOB->CR1 |= SHT30_SCL //GPIOB4 push output #define SHT30_SCL0_H GPIOB->ODR |= SHT30_SCL #define SHT30_SCL0_L GPIOB->ODR &= ~SHT30_SCL #define SHT30_SCL0_I GPIOB->DDR & amp;= ~SHT30_SCL; GPIOB->CR1 & amp;= ~SHT30_SCL //GPIOB4 floating input #define SHT30_SCL0_DAT ( (GPIOB->IDR>>4) & 0x01) #define SHT30_SDA0_O GPIOB->DDR |= SHT30_SDA; GPIOB->CR1 |= SHT30_SDA //GPIOB5 push-pull output #define SHT30_SDA0_H GPIOB->ODR |= SHT30_SDA #define SHT30_SDA0_L GPIOB->ODR &= ~SHT30_SDA #define SHT30_SDA0_I GPIOB->DDR & amp;= ~SHT30_SDA; GPIOB->CR1 & amp;= ~SHT30_SDA //GPIOB5 floating input #define SHT30_SDA0_DAT ( (GPIOB->IDR>>5) & 0x01) #define SHT30_SlaveAddress (0x44<<1) //7-bit address 0x44 left shifted 1 bit 0x45 -- 0x8A #define noACK 0 //Used to determine whether to end the communication #define ACK 1 //End data transmission
Before the main function starts, the pins used need to be initialized and configured as follows
Configure PB4/PB5 to initialize as output
uint8 SHT30_Init(vid) { uint8 vRval = 0x00; SHT30_SCL0_O; //Set SCLK as output SHT30_SDA0_O; //Set SDA as output \t SHT30_SCL0_H; SHT30_SCL0_L; \t SHT30_SDA0_H; SHT30_SDA0_L; \t vRval += SHT30_Soft_Reset(); \t \t \t \t SHT30_DelayMs(1); \t vRval += SHT30_ClearStaus(); \t SHT30_DelayMs(1); \t //SHT30_Periodic_Measure(SHT30_PERIODOC_H_MEASURE_1S); return vRval; }
Single fetch data command
The detailed data format of the Measurement Commands for Single Shot Data Acquisition Mode is shown in the figure below. First, start from the top of the table. Repeatability refers to repeatability (the higher the repeatability, the higher the accuracy, please refer to the Sensor Performance section of the manual), and Clock Stretching refers to clock stretching. Their functions will be described below. The data flow process is as follows.
Send the start signal and a one-byte address composed of the upper 7-bit device address and the lowest-bit write signal (WR=0), and wait for the response signal. (Note that the address is located in the upper 7 bits, so when addressing, you need to shift the address to the left by one bit and add a read 1/write 0 signal, ADDR<<1 | WR);
Send the high byte (Most Significant Byte, MSB) of the command and wait for the response signal;
Send the low byte (Least Significant Byte, LSB) of the command and wait for the response signal, then send the stop signal;
wait for some time (the measurement is in progress);
Send the start signal and a one-byte address consisting of the upper 7-bit device address and the lowest-bit read signal (RD=1), and then select from two directions according to the selected Clock Stretching. If the clock extension function is disabled, wait for a non-response signal, send a stop signal, delay for a period of time (this step is very important!! The delay time is about 50ms) and wait for the end of the conversion, then send an eight-bit response signal and wait for the response signal , and then read the high byte, low byte and CRC check byte of the temperature and humidity byte by byte, and send a response signal after each byte is received, and finally send a stop signal. And if the clock extension function is enabled, the SCL of the bus is controlled by SHT3x, we only need to block the program through while (SCL==0), wait for it to release the bus and then the MCU can read the data;
Some timing functions for SHT3x are as follows
/*--------------------------------------------- ------------------------ Function description: SHT30 measurement result calculation Parameter description: vTemSymbol [out] - returns the temperature symbol vTem [out] - temperature vHum [out] - Humidity Function returns: None -------------------------------------------------- -------------------*/ uint8 SHT30_Get_TH(uint8 *vTemSymbol, uint16 *vTem, uint16 *vHum) { uint8 vDat[8]; uint8 vRval = 0; \t vRval = SHT30_Single_Measure(vDat); if (!vRval) SHT30_calc(vDat, vTemSymbol, vTem, vHum); \t return vRval; } /*------------------------------------------------ --------------------- Function description: SHT30 single measurement Parameter description: vBuf [out] - measurement reading result Function returns: 0 - success greater than 1 error -------------------------------------------------- -------------------*/ uint8 SHT30_Single_Measure(uint8 *vBuf) { uint8 vRval = 0; uint8 i = 0; \t SHT30_Start(); \t vRval |= SHT30_SendByte(SHT30_SlaveAddress + 0); //Address write if (!vRval) vRval |= SHT30_SendByte( (SHT30_SINGLE_H_MEASURE_EN>>8) & amp;0xFF ); //Enable high-precision acquisition if (!vRval) vRval |= SHT30_SendByte( (SHT30_SINGLE_H_MEASURE_EN) &0xFF ); SHT30_Stop(); \t if (vRval) return vRval; \t SHT30_SCL0_H; SHT30_DelayMs(15); //15Ms \t \t SHT30_Start(); if (!vRval) vRval |= SHT30_SendByte(SHT30_SlaveAddress + 1); //Address read \t if (vRval) return vRval; \t for(i=0; i<6; i ++ ) { vBuf[i] = SHT30_RecvByte(); //store data if (i == 0x06) { SHT30_SendACK(1); //The last data needs to return NOACK } else { SHT30_SendACK(0); //Response ACK } } \t SHT30_Stop(); \t return vRval; } /*------------------------------------------------ --------------------- Function description: SHT30 measurement result calculation Parameter description: vBuf [in] - measurement read result vTemSymbol [out] - return temperature symbol vTem [out] - temperature vHum [out] - Humidity Function returns: None -------------------------------------------------- -------------------*/ void SHT30_calc(uint8 *vBuf, uint8 *vTemSymbol, uint16 *vTem, uint16 *vHum) { uint16 vVal = 0x00; uint8 vCrc = 0x00; float vTemp = 0.00; \t \t//temperature vCrc = SHT30_CheckCrc8(vBuf, 2); if (vCrc == vBuf[2]) { vVal = vBuf[0]; vVal<<=8; vVal |= vBuf[1]; \t\t vTemp = 175.0*vVal/(65536.0-1.0); \t\t if (vTemp >= 45) { *vTemSymbol = 1; *vTem = (uint16)((vTemp - 45.0)*10.0); } else { *vTemSymbol = 0; *vTem = (uint16)((45.0 - vTemp)*10.0); } \t\t } \t vBuf += 3; vVal = 0x00; vCrc = SHT30_CheckCrc8(vBuf, 2); if (vCrc == vBuf[2]) { vVal = vBuf[0]; vVal<<=8; vVal |= vBuf[1]; \t\t vTemp = 100.0*vVal/(65536.0-1.0); *vHum = (uint16)(vTemp*10); } }