STM8 analog iic interface debugging temperature and humidity sensor SHT3x driver

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);
}
}