Merge sht4x_minimal

This commit is contained in:
dooku
2021-07-18 10:35:07 +02:00
62 changed files with 282 additions and 4205 deletions

22
fw/Core/Inc/crc8.h Normal file
View File

@@ -0,0 +1,22 @@
/*
* crc.h
*
* Created on: Jun 9, 2021
* Author: user
*/
#ifndef INC_CRC8_H_
#define INC_CRC8_H_
#include "stdint.h"
/*
* Definitions & macros
*/
#define CRC8_POLYNOMIAL 0x31
#define CRC8_INIT 0xFF
uint8_t crc8_calculate(const uint8_t *data, uint16_t count);
#endif /* INC_CRC8_H_ */

46
fw/Core/Inc/i2c.h Normal file
View File

@@ -0,0 +1,46 @@
/*
* i2c.h
*
* Created on: Jun 8, 2021
* Author: user
*/
#ifndef INC_I2C_H_
#define INC_I2C_H_
#include "stdint.h"
#include "stm32l0xx_ll_i2c.h"
/*
* Defines & macros
*/
#define NULL 0
/*
* Return values for I2C functions
*/
#define I2C_OK 0
#define I2C_ERROR -1 // generic error
#define I2C_ERROR_NACK -2 // NACK was received during transfer
#define I2C_ERROR_TX_INCOMPLETE -3 // number of TXed bytes != buffer length
#define I2C_ERROR_RX_INCOMPLETE -4 // number of RXed bytes != buffer length
/*
* Type definitions
*/
typedef struct {
I2C_TypeDef *i2c;
} i2c_context_t;
/*
* Function declarations
*/
int i2c_init(i2c_context_t *context);
int i2c_transmit(uint8_t address, uint8_t *buffer, int len);
int i2c_receive(uint8_t address, uint8_t *buffer, int len);
#endif /* INC_I2C_H_ */

View File

@@ -48,6 +48,8 @@ extern "C" {
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "i2c.h"
#include "sht4x.h"
/* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/

57
fw/Core/Inc/sht4x.h Normal file
View File

@@ -0,0 +1,57 @@
/*
* sht4x.h
*
* Created on: Jun 8, 2021
* Author: user
*/
#ifndef INC_SHT4X_H_
#define INC_SHT4X_H_
#include "stdint.h"
#include "stm32l0xx_ll_i2c.h"
#include "stm32l0xx_ll_utils.h"
#include "i2c.h"
#include "crc8.h"
/*
* Defines & macros
*/
#define SHT4X_I2C_ADDRESS 0x44
/*
* Return values
*/
#define SHT4X_OK 0
#define SHT4X_ERROR -1 // generic error
#define SHT4X_CRC8_ERROR -2 // checksum failed
/*
* Data types
*/
typedef enum {
START_MEAS_HIGH_PRECISION = 0xFD,
START_MEAS_MEDIUM_PRECISION = 0xF6,
START_MEAS_LOW_PRECISION = 0xE0,
READ_SERIAL = 0x89,
SOFT_RESET = 0x94,
HEATER_200_mW_1_s = 0x39,
HEATER_200_mW_01_s = 0x32,
HEATER_110_mW_1_s = 0x2F,
HEATER_110_mW_01_s = 0x24,
HEATER_20_mW_1_s = 0x1E,
HEATER_20_mW_01_s = 0x15
} sht4x_cmd_t;
/*
* Function prototypes
*/
int8_t sht4x_send_cmd(sht4x_cmd_t cmd);
int8_t sht4x_read_data(uint8_t *buffer, int len);
int8_t sht4x_measure(int *temperature, int *relative_humidity);
#endif /* INC_SHT4X_H_ */

28
fw/Core/Src/crc8.c Normal file
View File

@@ -0,0 +1,28 @@
/*
* crc.c
*
* Created on: Jun 9, 2021
* Author: user
*/
#include "crc8.h"
/* Stolen from Sensirion SCD4x datasheet, section 3.11 */
uint8_t crc8_calculate(const uint8_t *data, uint16_t count)
{
uint16_t current_byte;
uint8_t crc = CRC8_INIT;
uint8_t crc_bit;
/* calculates 8-Bit checksum with given polynomial */
for (current_byte = 0; current_byte < count; ++current_byte) {
crc ^= (data[current_byte]);
for(crc_bit = 8; crc_bit > 0; --crc_bit) {
if (crc & 0x80) {
crc =(crc << 1) ^ CRC8_POLYNOMIAL;
} else {
crc = (crc << 1);
}
}
}
return crc;
}

64
fw/Core/Src/i2c.c Normal file
View File

@@ -0,0 +1,64 @@
/*
* i2c.c
*
* Created on: Jun 8, 2021
* Author: user
*/
#include "i2c.h"
i2c_context_t *i2c_context;
int i2c_init(i2c_context_t *context)
{
if (context == NULL) {
return I2C_ERROR;
}
i2c_context = context;
return I2C_OK;
}
int i2c_transmit(uint8_t address, uint8_t *buffer, int len)
{
LL_I2C_HandleTransfer(i2c_context->i2c, address, LL_I2C_ADDRSLAVE_7BIT, len,
LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_WRITE);
int i = 0;
// Autoend mode will raise STOP flag if NACK is detected
// (or if desired number of bytes is transmitted)
while (!LL_I2C_IsActiveFlag_STOP(i2c_context->i2c)) {
if (LL_I2C_IsActiveFlag_TXE(i2c_context->i2c)) {
if (i < len) {
LL_I2C_TransmitData8(i2c_context->i2c, buffer[i++]);
}
}
}
LL_I2C_ClearFlag_STOP(i2c_context->i2c);
if (LL_I2C_IsActiveFlag_NACK(i2c_context->i2c)) {
return I2C_ERROR_NACK;
}
if (len != i) {
// this will probably never happen, as NACK flag
// is raised everytime len != number of TXed bytes
return I2C_ERROR_TX_INCOMPLETE;
}
return I2C_OK;
}
int i2c_receive(uint8_t address, uint8_t *buffer, int len)
{
LL_I2C_HandleTransfer(i2c_context->i2c, address, LL_I2C_ADDRSLAVE_7BIT, len,
LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_READ);
int i = 0;
while (!LL_I2C_IsActiveFlag_STOP(i2c_context->i2c)) {
if (LL_I2C_IsActiveFlag_RXNE(i2c_context->i2c)) {
if (i < len) {
buffer[i++] = LL_I2C_ReceiveData8(i2c_context->i2c);
}
}
}
LL_I2C_ClearFlag_STOP(i2c_context->i2c);
if (len != i) {
return I2C_ERROR_RX_INCOMPLETE;
}
return I2C_OK; // TODO error detection
}

View File

@@ -98,7 +98,10 @@ int main(void)
/* USER CODE BEGIN 2 */
LL_I2C_Enable(I2C1);
LL_LPUART_Enable(LPUART1);
/* LED PWM context */
/* I2C context init (for SHT4x and SCD4x) */
i2c_context_t i2c_context;
i2c_context.i2c = I2C1;
i2c_init(&i2c_context);
/* USER CODE END 2 */
@@ -107,13 +110,17 @@ int main(void)
uint8_t uart_data_dummy = 0;
while (1)
{
/* RS485 test */
LL_LPUART_SetDESignalPolarity(LPUART1, 1);
LL_LPUART_TransmitData8(LPUART1, uart_data_dummy);
uart_data_dummy++;
/* SHT41 measurement */
int T, RH;
sht4x_measure(&T, &RH);
LL_mDelay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
@@ -216,7 +223,6 @@ static void MX_I2C1_Init(void)
LL_I2C_Init(I2C1, &I2C_InitStruct);
LL_I2C_SetOwnAddress2(I2C1, 0, LL_I2C_OWNADDRESS2_NOMASK);
/* USER CODE BEGIN I2C1_Init 2 */
/* USER CODE END I2C1_Init 2 */
}

53
fw/Core/Src/sht4x.c Normal file
View File

@@ -0,0 +1,53 @@
/*
* sht4x.c
*
* Created on: Jun 8, 2021
* Author: user
*/
#include "sht4x.h"
int8_t sht4x_send_cmd(sht4x_cmd_t cmd)
{
}
int8_t sht4x_read_data(uint8_t *buffer, int len)
{
}
int8_t sht4x_measure(int *temperature, int *relative_humidity)
{
uint8_t buffer[32];
int result;
// start measurement
buffer[0] = START_MEAS_HIGH_PRECISION;
result = i2c_transmit(SHT4X_I2C_ADDRESS<<1, buffer, 1);
if (result != I2C_OK) {
return SHT4X_ERROR;
}
LL_mDelay(100); // 10 ms should be enough
// read out
result = i2c_receive(SHT4X_I2C_ADDRESS<<1, buffer, 6);
if (result != I2C_OK) {
return SHT4X_ERROR;
}
// TODO checksum
// Convert to T and RH; taken directly from pseudocode in SHT4x datasheet, page 3
uint32_t t_ticks = (buffer[0] << 8) + buffer[1];
uint32_t rh_ticks = (buffer[3] << 8) + buffer[4];
int t_degC = -45 + 175 * t_ticks / 65535;
int rh_pRH = -6 + 125 * rh_ticks / 65535;
if (rh_pRH > 100) {
rh_pRH = 100;
}
if (rh_pRH < 0) {
rh_pRH = 0;
}
*temperature = t_degC;
*relative_humidity = rh_pRH;
return SHT4X_OK;
}