Browse Source

Added support for sensor SHT21/HTU21/Si7021.

Vladimir N. Shilov 3 years ago
parent
commit
f962289104
2 changed files with 215 additions and 1 deletions
  1. 34 0
      Inc/main.h
  2. 181 1
      Src/main.c

+ 34 - 0
Inc/main.h

@@ -78,6 +78,34 @@ volatile struct {
   uint32_t _reserv:    25;
 } Flag;
 
+typedef union {
+  uint16_t u16;           // element specifier for accessing whole u16
+  int16_t  i16;           // element specifier for accessing whole i16
+  struct {
+    #ifdef LITTLE_ENDIAN  // Byte-order is little endian
+    uint8_t u8L;          // element specifier for accessing low u8
+    uint8_t u8H;          // element specifier for accessing high u8
+    #else                 // Byte-order is big endian
+    uint8_t u8H;          // element specifier for accessing low u8
+    uint8_t u8L;          // element specifier for accessing high u8
+    #endif
+  } s16;                  // element spec. for acc. struct with low or high u8
+} nt16;
+
+typedef union {
+  uint32_t u32;           // element specifier for accessing whole u32
+  int32_t i32;            // element specifier for accessing whole i32
+ struct {
+    #ifdef LITTLE_ENDIAN  // Byte-order is little endian
+    uint16_t u16L;        // element specifier for accessing low u16
+    uint16_t u16H;        // element specifier for accessing high u16
+    #else                 // Byte-order is big endian
+    uint16_t u16H;        // element specifier for accessing low u16
+    uint16_t u16L;        // element specifier for accessing high u16
+    #endif
+  } s32;                  // element spec. for acc. struct with low or high u16
+} nt32;
+
 /* USER CODE END ET */
 
 /* Exported constants --------------------------------------------------------*/
@@ -86,6 +114,12 @@ volatile struct {
 #define I2C_RET_NACK  (int8_t)-1
 #define I2C_RET_TOUT  (int8_t)-2
 
+#define I2C_SHT_ADDR  0x80
+#define SHT_SOFT_RST  0xFE
+#define SHT_STRT_HUMD 0xF5
+#define SHT_STRT_TEMP 0xF3
+#define SHT_DATA_LEN  3
+
 /* USER CODE END EC */
 
 /* Exported macro ------------------------------------------------------------*/

+ 181 - 1
Src/main.c

@@ -75,7 +75,7 @@ static rtc_t Clock;
 static struct bme280_dev SensorDev;
 static struct bme280_data SensorData;
 static int8_t rsltSensor = 33; //BME280_OK;
-
+static int16_t Humidity, Temperature;
 /* USER CODE END PV */
 
 /* Private function prototypes -----------------------------------------------*/
@@ -93,6 +93,12 @@ static void showDigit(tube_pos_t pos, uint8_t dig);
 static void SPI_StartTX(void);
 int8_t user_i2c_read(uint8_t id, uint8_t reg_addr, uint8_t *data, uint16_t len);
 int8_t user_i2c_write(uint8_t id, uint8_t reg_addr, uint8_t *data, uint16_t len);
+int8_t user_i2c_write_byte(uint8_t id, uint8_t data);
+static int8_t SHT_Init(void);
+static int8_t SHT_StartH(void);
+static int8_t SHT_StartT(void);
+static int16_t SHT_GetH(void);
+static int16_t SHT_GetT(void);
 /* USER CODE END PFP */
 
 /* Private user code ---------------------------------------------------------*/
@@ -193,6 +199,8 @@ int main(void)
   if (rsltSensor == BME280_OK) {
     Flag.BME280 = 1;
   }
+
+//  SHT_Init();
   /* USER CODE END 2 */
 
   /* USER CODE BEGIN WHILE */
@@ -225,6 +233,8 @@ int main(void)
     IN15_OFF;
     COLOR_RGB(0, 0, 0);
     RTC_ReadAll(&Clock);
+    //SHT_StartH();
+    //SHT_StartT();
     tdelay_ms(500);
 
     if (Flag.RTC_IRQ != 0) {
@@ -243,6 +253,9 @@ int main(void)
     showDigit(Tube_D, Clock.Sec >> 4);
     showDigit(Tube_E, Clock.Sec & 0xf);
 */
+    //Humidity = SHT_GetH();
+    //Temperature = SHT_GetT();
+
     if (rsltSensor == BME280_OK) {
       temp_h = (uint8_t)SensorData.temperature / 100;
       temp_l = (uint8_t)SensorData.temperature % 100;
@@ -276,10 +289,18 @@ int main(void)
 }
 
 
+/**
+ * @brief Launch SPI transaction.
+ * @retval None
+ */
 static void SPI_StartTX(void) {
   LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1);
 }
 
+/**
+ * @brief Read len bytes from I2C bus to data by reg_addr.
+ * @retval I2C return code
+ */
 int8_t user_i2c_read(const uint8_t id, const uint8_t reg_addr, uint8_t *data, const uint16_t len) {
   Flag.I2C_RX_End = 0;
   Flag.I2C_RX_Err = 0;
@@ -330,6 +351,10 @@ int8_t user_i2c_read(const uint8_t id, const uint8_t reg_addr, uint8_t *data, co
   return I2C_RET_OK;
 }
 
+/**
+ * @brief Write len bytes to I2C bus from data by reg_addr.
+ * @retval I2C return code
+ */
 int8_t user_i2c_write(const uint8_t id, const uint8_t reg_addr, uint8_t *data, const uint16_t len) {
   Flag.I2C_TX_End = 0;
   Flag.I2C_TX_Err = 0;
@@ -360,6 +385,161 @@ int8_t user_i2c_write(const uint8_t id, const uint8_t reg_addr, uint8_t *data, c
   return I2C_RET_OK;
 }
 
+/**
+ * @brief Write one byte to I2C bus.
+ * @retval I2C return code
+ */
+int8_t user_i2c_write_byte(const uint8_t id, const uint8_t data) {
+  /* wait for i2c */
+  while ( I2C1->ISR & I2C_ISR_BUSY ) {};
+
+  /* prepare i2c for sending data byte */
+  I2C1->CR2 &= ~( I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN);
+  I2C1->CR2 |= ( id | 1 << I2C_CR2_NBYTES_Pos );
+  I2C1->CR1 |= I2C_CR1_NOSTRETCH;
+
+  /* gen START */
+  I2C1->CR2 |= ( I2C_CR2_START );
+
+  /* wait for start end */
+  while ( !( I2C1->CR2 & I2C_CR2_START ) ) {};
+
+  /* check if devce is present */
+  if ((I2C1->ISR & I2C_ISR_NACKF) != 0) {
+    /* no device present, reset i2c */
+    I2C1->CR1 &= ~I2C_CR1_PE;
+    while ((I2C1->CR1 & I2C_CR1_PE) != 0) {};
+    I2C1->CR1 |= I2C_CR1_PE;
+    /* exit with NACK */
+    return I2C_RET_NACK;
+  }
+
+  /* device ok, data */
+  I2C1->TXDR = data;
+
+  return I2C_RET_OK;
+}
+
+/**
+ * @brief Init DHT21/SHT21/Si7021 sensor, need wait for 15 ms
+ * @retval I2C return code
+ */
+static int8_t SHT_Init(void) {
+  int8_t res;
+
+  res = user_i2c_write_byte (I2C_SHT_ADDR, SHT_SOFT_RST);
+  if (res == I2C_RET_OK) {
+      tdelay_ms(15);
+  }
+
+  return res;
+}
+
+/**
+ * @brief Launch Humidity measure for DHT21/SHT21/Si7021 sensor, need wait for 16 ms
+ * @retval I2C return code
+ */
+static int8_t SHT_StartH(void) {
+  int8_t res;
+
+  res = user_i2c_write_byte (I2C_SHT_ADDR, SHT_STRT_HUMD);
+  if (res == I2C_RET_OK) {
+      tdelay_ms(16);
+  }
+
+  return res;
+}
+
+/**
+ * @brief Launch Temperature measure for DHT21/SHT21/Si7021 sensor, need wait for 50 ms
+ */
+static int8_t SHT_StartT(void) {
+  int8_t res;
+
+  res = user_i2c_write_byte (I2C_SHT_ADDR, SHT_STRT_TEMP);
+  if (res == I2C_RET_OK) {
+      tdelay_ms(50);
+  }
+
+  return res;
+}
+
+/**
+ * @brief Read and convert Humidity data from DHT21/SHT21/Si7021 sensor.
+ * @retval Return value in 0.01 % [0..10000]
+ */
+static int16_t SHT_GetH(void) {
+  uint8_t buf[4];
+  uint32_t rh;
+
+  /* wait for i2c */
+  while ( I2C1->ISR & I2C_ISR_BUSY ) {
+  }
+
+  /* prepare dma channel for receiving data */
+  DMA1_Channel2->CMAR = (uint32_t)buf;
+  DMA1_Channel2->CPAR = (uint32_t)&(I2C1->RXDR);
+  DMA1_Channel2->CNDTR = SHT_DATA_LEN;
+  DMA1_Channel2->CCR |= DMA_CCR_EN;
+
+  /* prepare i2c for receiving data */
+  I2C1->CR2 &= ~( I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN);
+  I2C1->CR2 |= ( I2C_SHT_ADDR | SHT_DATA_LEN << I2C_CR2_NBYTES_Pos | I2C_CR2_RD_WRN);
+  /* launch receiving */
+  I2C1->CR1 |= ( I2C_CR1_RXDMAEN );
+  I2C1->CR2 |= ( I2C_CR2_START );
+
+  while (Flag.I2C_RX_End == 0) {
+    __WFI();
+  }
+
+  rh = (buf[0] << 8) | buf[1];
+  rh *= 12500;
+  rh += 32768;
+  rh >>= 16;
+  rh -= 600;
+
+  return (int16_t)rh;
+}
+
+/**
+ * @brief Read and convert Temperature data from DHT21/SHT21/Si7021 sensor.
+ * @retval Return value in 0.01 oC [-4000..+8500]
+ */
+static int16_t SHT_GetT(void) {
+  uint8_t buf[4];
+  uint32_t temp;
+
+  /* wait for i2c */
+  while ( I2C1->ISR & I2C_ISR_BUSY ) {
+  }
+
+  /* prepare dma channel for receiving data */
+  DMA1_Channel2->CMAR = (uint32_t)buf;
+  DMA1_Channel2->CPAR = (uint32_t)&(I2C1->RXDR);
+  DMA1_Channel2->CNDTR = SHT_DATA_LEN;
+  DMA1_Channel2->CCR |= DMA_CCR_EN;
+
+  /* prepare i2c for receiving data */
+  I2C1->CR2 &= ~( I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN);
+  I2C1->CR2 |= ( I2C_SHT_ADDR | SHT_DATA_LEN << I2C_CR2_NBYTES_Pos | I2C_CR2_RD_WRN);
+  /* launch receiving */
+  I2C1->CR1 |= ( I2C_CR1_RXDMAEN );
+  I2C1->CR2 |= ( I2C_CR2_START );
+
+  while (Flag.I2C_RX_End == 0) {
+    __WFI();
+  }
+
+  temp = (buf[0] << 8) | buf[1];
+  temp *= 17572;
+  temp += 32768;
+  temp >>= 16;
+  temp -= 4685;
+
+  return (int16_t)temp;
+}
+
 /**
   * @brief System Clock Configuration
   * @retval None