Browse Source

Added HTU21 module.

Vladimir N. Shilov 1 year ago
parent
commit
7b67aa245a
7 changed files with 138 additions and 54 deletions
  1. 6 0
      inc/delay.h
  2. 83 0
      lib/htu21.c
  3. 17 0
      lib/htu21.h
  4. 14 47
      lib/i2c.c
  5. 4 4
      lib/i2c.h
  6. 8 3
      src/main.c
  7. 6 0
      src/stm8s_it.c

+ 6 - 0
inc/delay.h

@@ -0,0 +1,6 @@
+#ifndef __BOARD_H
+#define __BOARD_H
+
+void Delay(__IO uint16_t nTime);
+
+#endif /* __BOARD_H */

+ 83 - 0
lib/htu21.c

@@ -0,0 +1,83 @@
+#include "stm8s.h"
+#include "htu21.h"
+#include "i2c.h"
+#include "delay.h"
+
+#define HTU_T_MEASURE 0xF3
+#define HTU_H_MEASURE 0xF5
+
+static uint8_t buf[3];
+static const uint8_t addr = 0x40;
+static t_i2c_status i2cs;
+static uint32_t val;
+
+static uint8_t CalcSht21Crc(uint8_t *data, uint8_t nbrOfBytes);
+
+htu_err_t htu_GetTemperature(int16_t * temperature) {
+  i2cs = i2c_wr_reg(addr, HTU_T_MEASURE);
+  if (i2cs == 0) {
+    Delay(90);
+    i2c_rd_reg(addr, buf);
+    if(buf[2] == CalcSht21Crc(buf,2)) {
+      val = buf[0];
+      val <<= 8;
+      val |= (buf[1] & 0xfc);
+      // Temp = val * 175.72 / 2^16 - 46.85
+      val *= 4393; // 175.72/4*100
+      val *= 100; // for .xx degree
+      val += 819200; // for round
+      val /= 1638400; // 2^16/4*100
+      *temperature = val - 4685;
+      return HTU_OK;
+    } else {
+      return HTU_CRC_Temp;
+    }
+  } else {
+    return HTU_I2C;
+  }
+}
+
+htu_err_t htu_GetHumidity(uint16_t * humidity) {
+  i2cs = i2c_wr_reg(addr, HTU_H_MEASURE);
+  if (i2cs == 0) {
+    Delay(60);
+    i2c_rd_reg(addr, buf);
+    if(buf[2] == CalcSht21Crc(buf,2)) {
+      val = buf[0];
+      val <<= 8;
+      val |= (buf[1] & 0xfc);
+      // Humidity = val * 125 / 2^16 - 6
+      val *= 125;
+      val *= 10; // for .x %H
+      val += 32768; // for round
+      val /= 65536;
+      *humidity = val - 60;
+      return HTU_OK;
+    } else {
+      return HTU_CRC_Humidity;
+    }
+  } else {
+    return HTU_I2C;
+  }
+}
+
+static uint8_t CalcSht21Crc(uint8_t *data, const uint8_t nbrOfBytes) {
+	// CRC
+	//const u16t POLYNOMIAL = 0x131; //P(x)=x^8+x^5+x^4+1 = 100110001
+	
+	uint8_t byteCtr,bit,crc;
+
+	crc = 0;
+
+	//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) ^ 0x131;
+				else 		crc = (crc << 1);
+		}
+	}
+	return(crc);
+}

+ 17 - 0
lib/htu21.h

@@ -0,0 +1,17 @@
+#pragma once
+#ifndef HTU21_H
+#define HTU21_H
+
+#include "stm8s.h"
+
+typedef enum {
+  HTU_OK = 0,
+  HTU_I2C,
+  HTU_CRC_Temp,
+  HTU_CRC_Humidity
+} htu_err_t;
+
+htu_err_t htu_GetTemperature(int16_t * temperature);
+htu_err_t htu_GetHumidity(uint16_t * humidity);
+
+#endif // HTU21_H

+ 14 - 47
lib/i2c.c

@@ -57,7 +57,7 @@ void i2c_master_init(void) {
 /**
  * @brief Запись регистра slave-устройства
  */
-t_i2c_status i2c_wr_reg(uint8_t address, uint8_t reg_addr, uint16_t data) {
+t_i2c_status i2c_wr_reg(const uint8_t address, const uint8_t data) {
 
   //Ждем освобождения шины I2C
   wait_event((I2C->SR3 & I2C_SR3_BUSY), 10);
@@ -79,17 +79,7 @@ t_i2c_status i2c_wr_reg(uint8_t address, uint8_t reg_addr, uint16_t data) {
   //Ждем освобождения регистра данных
   wait_event(!(I2C->SR1 & I2C_SR1_TXE), 1);
   //Отправляем адрес регистра
-  I2C->DR = reg_addr;
-
-  //Отправка данных
-  //Ждем освобождения регистра данных
-  wait_event(!(I2C->SR1 & I2C_SR1_TXE), 1);
-  //Отправляем адрес регистра
-  I2C->DR = (uint8_t)(data >> 8);
-  //Ждем освобождения регистра данных
-  wait_event(!(I2C->SR1 & I2C_SR1_TXE), 1);
-  //Отправляем адрес регистра
-  I2C->DR = (uint8_t)data;
+  I2C->DR = data;
 
   //Ловим момент, когда DR освободился и данные попали в сдвиговый регистр
   wait_event(!((I2C->SR1 & I2C_SR1_TXE) && (I2C->SR1 & I2C_SR1_BTF)), 1);
@@ -106,7 +96,7 @@ t_i2c_status i2c_wr_reg(uint8_t address, uint8_t reg_addr, uint16_t data) {
  * @brief Чтение регистра slave-устройства
  * @note Start -> Slave Addr -> Reg. addr -> Restart -> Slave Addr <- data ... -> Stop
  */
-t_i2c_status i2c_rd_reg(uint8_t address, uint8_t reg_addr, uint16_t * data) {
+t_i2c_status i2c_rd_reg(const uint8_t address, uint8_t * data) {
 
   //Ждем освобождения шины I2C
   wait_event((I2C->SR3 & I2C_SR3_BUSY), 10);
@@ -119,56 +109,33 @@ t_i2c_status i2c_rd_reg(uint8_t address, uint8_t reg_addr, uint16_t * data) {
   //Ждем установки бита SB
   wait_event(!(I2C->SR1 & I2C_SR1_SB), 1);
 
-  //Записываем в регистр данных адрес ведомого устройства
-  I2C->DR = address & 0xFE;
-  //Ждем подтверждения передачи адреса
-  wait_event(!(I2C->SR1 & I2C_SR1_ADDR), 1);
-  //Очистка бита ADDR чтением регистра SR3
-  I2C->SR3;
-
-  //Ждем освобождения регистра данных RD
-  wait_event(!(I2C->SR1 & I2C_SR1_TXE), 1);
-
-  //Передаем адрес регистра slave-устройства, который хотим прочитать
-  I2C->DR = reg_addr;
-  //Ловим момент, когда DR освободился и данные попали в сдвиговый регистр
-  wait_event(!((I2C->SR1 & I2C_SR1_TXE) && (I2C->SR1 & I2C_SR1_BTF)), 1);
-
-  //Генерация СТАРТ-посылки (рестарт)
-  I2C->CR2 |= I2C_CR2_START;
-  //Ждем установки бита SB
-  wait_event(!(I2C->SR1 & I2C_SR1_SB), 1);
-
   //Записываем в регистр данных адрес ведомого устройства и переходим
   //в режим чтения (установкой младшего бита в 1)
   I2C->DR = address | 0x01;
-
-  //Отправка двух байт данных
   //Бит который разрешает NACK на следующем принятом байте
-  I2C->CR2 |= I2C_CR2_POS;
+  //I2C->CR2 |= I2C_CR2_POS;
   //Ждем подтверждения передачи адреса
   wait_event(!(I2C->SR1 & I2C_SR1_ADDR), 1);
-  //Заплатка из Errata
-  disableInterrupts();
   //Очистка бита ADDR чтением регистра SR3
   I2C->SR3;
+  // wait for BTF
+  wait_event(!(I2C->SR1 & I2C_SR1_BTF), 1);
   //Запрещаем подтверждение в конце посылки
   I2C->CR2 &= (uint8_t)(~I2C_CR2_ACK);
-  //Заплатка из Errata
-  enableInterrupts();
-  //Ждем момента, когда первый байт окажется в DR,
-  //а второй в сдвиговом регистре
-  wait_event(!(I2C->SR1 & I2C_SR1_BTF), 1);
-
   //Заплатка из Errata
   disableInterrupts();
+  // Read 1st byte
+  data[0] = I2C->DR;
   //Устанавлием бит STOP
   I2C->CR2 |= I2C_CR2_STOP;
-  //Читаем принятые байты
-  *data = I2C->DR << 8;
+  // Read 2nd byte
+  data[1] = I2C->DR;
   //Заплатка из Errata
   enableInterrupts();
-  *data |= I2C->DR;
+  // Wait for RXNE
+  wait_event(!(I2C->SR1 & I2C_SR1_RXNE), 1);
+  // Read 3rd Data byte
+  data[2] = I2C->DR;
 
   //Ждем отправки СТОП посылки
   wait_event((I2C->CR2 & I2C_CR2_STOP), 1);

+ 4 - 4
lib/i2c.h

@@ -25,9 +25,9 @@ typedef enum {
 // Инициализация I2C интерфейса
 extern void i2c_master_init(void);
 
-// Запись регистра slave-устройства
-extern t_i2c_status  i2c_wr_reg(uint8_t address, uint8_t reg_addr, uint16_t data);
+// Wrie 1 byte
+extern t_i2c_status  i2c_wr_reg(uint8_t address, uint8_t data);
 
-// Чтение регистра slave-устройства
-extern t_i2c_status  i2c_rd_reg(uint8_t address, uint8_t reg_addr, uint16_t * data);
+// Read 3 bytes
+extern t_i2c_status  i2c_rd_reg(uint8_t address, uint8_t * data);
 #endif // I2C_H

+ 8 - 3
src/main.c

@@ -23,6 +23,7 @@
 #include "i2c.h"
 #include "led.h"
 #include "delay.h"
+#include "htu21.h"
 
 /* Private define ------------------------------------------------------------*/
 #define TIM4_PERIOD  (uint8_t)124
@@ -32,6 +33,8 @@
 /* Private variables ---------------------------------------------------------*/
 __IO uint16_t ConversionBuffer[ADC_SMPLS];
 __IO uint8_t BufferIndex = 0;
+static int16_t Temperature;
+static uint16_t Humidity;
 
 /* Private function prototypes -----------------------------------------------*/
 static void boardInit(void);
@@ -42,12 +45,14 @@ void main(void)
   boardInit();
 
   /* I2C Configuration */
-  //i2c_master_init();
+  i2c_master_init();
 
   /* Infinite loop */
   while (1) {
-
-    wfi();
+    htu_GetTemperature(&Temperature);
+    Delay(410);
+    htu_GetHumidity(&Humidity);
+    Delay(440);
   }
 
 }

+ 6 - 0
src/stm8s_it.c

@@ -44,6 +44,7 @@ extern __IO uint16_t ConversionBuffer[64];
 extern __IO uint8_t BufferIndex;
 static uint8_t LedCnt = 0;
 static __IO uint16_t TimingDelay;
+__IO uint8_t I2C_timeout;
 
 /* Private function prototypes -----------------------------------------------*/
 /* Private functions ---------------------------------------------------------*/
@@ -521,6 +522,11 @@ INTERRUPT_HANDLER(TIM6_UPD_OVF_TRG_IRQHandler, 23)
    if (TimingDelay > 0) {
       TimingDelay --;
    }
+
+  /* for I2C */
+  if (I2C_timeout != 0) {
+    I2C_timeout --;
+  }
  }
 #endif /* (STM8S903) || (STM8AF622x)*/