I implemented this software to connect to an SPS 30 PM sensor and it will not connect. I wrote my own drivers but only ever recieved back 0xff for bytes. I then implemented sps30-i2c-3.1.1 on a custom board using an STM32L071KZT6 MCU. The I2c bus has several sensors on it and they communicate well. I have three sps30 sensors and they all do the same. I modified the sensirion_hw_i2c_implementation for my i2c bus and should be correct. Its the same initialization as in my main.c, I am using STM32CubeIDE for this project. What are the chances i have three faulty sensors? I am not sure what i am doing wrong. I will paste my implementation below:
sensirion_hw_i2c_implementation:
#include <stm32l0xx_hal.h>
#include "sensirion_arch_config.h"
#include "sensirion_i2c.h"
/**
- Create new I2C instance. You may also use a different interface, e.g. hi2c2,
- depending on your CubeMX configuration
*/
static I2C_HandleTypeDef hi2c1;
/**
-
Initialize all hard- and software components that are needed for the I2C
-
communication.
/
void sensirion_i2c_init(void) {
// hi2c1.Instance = I2C1;
//hi2c1.Init.ClockSpeed = 100000;
// hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
// hi2c1.Init.OwnAddress1 = 0;
// hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
// hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
// hi2c1.Init.OwnAddress2 = 0;
// hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
// hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
/ Enable the remapping of Pins 6/7 to 8/9 and the I2C clock before the
- initialization of the GPIO Pins in HAL_I2C_Init(). This is a fix of the
- code generated by CubeMX v4.16.0 */
//__HAL_AFIO_REMAP_I2C1_ENABLE();
// __HAL_RCC_I2C1_CLK_ENABLE();
hi2c1.Instance = I2C1;
hi2c1.Init.Timing = 0x00303D5B;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
HAL_I2C_Init(&hi2c1);
}
/**
- Release all resources initialized by sensirion_i2c_init().
*/
void sensirion_i2c_release(void) {
}
/**
- Execute one read transaction on the I2C bus, reading a given number of bytes.
- If the device does not acknowledge the read command, an error shall be
- returned.
- @param address 7-bit I2C address to read from
- @param data pointer to the buffer where the data is to be stored
- @param count number of bytes to read from I2C and store in the buffer
- @returns 0 on success, error code otherwise
/
int8_t sensirion_i2c_read(uint8_t address, uint8_t data, uint16_t count) {
return (int8_t)HAL_I2C_Master_Receive(&hi2c1, (uint16_t)(address << 1),
data, count, 100);
}
/**
- Execute one write transaction on the I2C bus, sending a given number of
- bytes. The bytes in the supplied buffer must be sent to the given address. If
- the slave device does not acknowledge any of the bytes, an error shall be
- returned.
- @param address 7-bit I2C address to write to
- @param data pointer to the buffer containing the data to write
- @param count number of bytes to read from the buffer and send over I2C
- @returns 0 on success, error code otherwise
/
int8_t sensirion_i2c_write(uint8_t address, const uint8_t data,
uint16_t count) {
return (int8_t)HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)(address << 1),
(uint8_t*)data, count, 100);
}
/**
-
Sleep for a given number of microseconds. The function should delay the
-
execution for at least the given time, but may also sleep longer.
-
@param useconds the sleep time in microseconds
*/
void sensirion_sleep_usec(uint32_t useconds) {
uint32_t msec = useconds / 1000;
if (useconds % 1000 > 0) {
msec++;
}
/*
- Increment by 1 if STM32F1 driver version less than 1.1.1
- Old firmwares of STM32F1 sleep 1ms shorter than specified in HAL_Delay.
- This was fixed with firmware 1.6 (driver version 1.1.1), so we have to
- fix it ourselves for older firmwares
*/
if (HAL_GetHalVersion() < 0x01010100) {
msec++;
}
HAL_Delay(msec);
}
main.c:
/* USER CODE BEGIN Header /
/*
- @attention
- Copyright (c) 2024 STMicroelectronics.
- All rights reserved.
- This software is licensed under terms that can be found in the LICENSE file
- in the root directory of this software component.
- If no LICENSE file comes with this software, it is provided AS-IS.
/
/ USER CODE END Header /
/ Includes ------------------------------------------------------------------*/
#include "main.h"
//#include "bme680.c"
#include "bme680.h"
#include "HDC2080.h"
#include "TDE5531.h"
#include "sps30pm.h"
#include "sps30.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Private includes ----------------------------------------------------------/
/ USER CODE BEGIN Includes /
//#include "ssd1306.c"
//#include "fonts.c"
/ USER CODE END Includes */
/* Private typedef -----------------------------------------------------------/
/ USER CODE BEGIN PTD /
#define DELAY_PERIOD_MS (151000) // 15 seconds
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------/
/ USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------/
/ USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
ADC_HandleTypeDef hadc;
CRC_HandleTypeDef hcrc;
I2C_HandleTypeDef hi2c1;
I2C_HandleTypeDef hi2c3;
RTC_HandleTypeDef hrtc;
SPI_HandleTypeDef hspi1;
UART_HandleTypeDef huart1;
UART_HandleTypeDef huart4;
/* USER CODE BEGIN PV */
uint8_t data[10] = {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};
char serial_msg[10];
void serial_string10(char str[10]);
uint8_t ver_buf[3];
uint8_t id_buf[49];
uint8_t pim_buf[3];
uint8_t rdy;
uint8_t num_err;
char i2c_reading_buf[100];
//int8_t rslt = BME680_OK;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ADC_Init(void);
static void MX_I2C1_Init(void);
static void MX_SPI1_Init(void);
static void MX_USART1_UART_Init(void);
static void MX_USART4_UART_Init(void);
static void MX_CRC_Init(void);
static void MX_RTC_Init(void);
static void MX_I2C3_Init(void);
/ USER CODE BEGIN PFP */
uint8_t getPMversion();
int8_t bme680I2cRead(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len);
int8_t bme680I2cWrite(uint8_t dev_id, uint8_t reg_addr, uint8_t reg_data, uint16_t len);
uint8_t getSFA30_id();
uint8_t getPIM_id();
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
/ USER CODE END PFP */
/* Private user code ---------------------------------------------------------/
/ USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
- @brief The application entry point.
- @RetVal int
/
int main(void)
{
/ USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals /
MX_GPIO_Init();
MX_ADC_Init();
MX_I2C1_Init();
MX_SPI1_Init();
MX_USART1_UART_Init();
MX_USART4_UART_Init();
MX_CRC_Init();
MX_RTC_Init();
MX_I2C3_Init();
/ USER CODE BEGIN 2 */
struct bme680_dev bme_sensor;
bme_sensor.dev_id = BME680_I2C_ADDR_PRIMARY;
bme_sensor.intf = BME680_I2C_INTF;
bme_sensor.read = bme680I2cRead;
bme_sensor.write = bme680I2cWrite;
bme_sensor.delay_ms = HAL_Delay;
bme_sensor.amb_temp = 25;
int8_t rslt = BME680_OK;
rslt = bme680_init(&bme_sensor);
uint8_t set_required_settings;
/* Set the temperature, pressure and humidity settings */
bme_sensor.tph_sett.os_hum = BME680_OS_2X;
bme_sensor.tph_sett.os_pres = BME680_OS_4X;
bme_sensor.tph_sett.os_temp = BME680_OS_8X;
bme_sensor.tph_sett.filter = BME680_FILTER_SIZE_3;
/* Set the remaining gas sensor settings and link the heating profile /
bme_sensor.gas_sett.run_gas = BME680_ENABLE_GAS_MEAS;
/ Create a ramp heat waveform in 3 steps /
bme_sensor.gas_sett.heatr_temp = 320; / degree Celsius /
bme_sensor.gas_sett.heatr_dur = 150; / milliseconds */
/* Select the power mode /
/ Must be set before writing the sensor configuration */
bme_sensor.power_mode = BME680_FORCED_MODE;
/* Set the required sensor settings needed */
set_required_settings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_FILTER_SEL
| BME680_GAS_SENSOR_SEL;
/* Set the desired sensor configuration */
rslt = bme680_set_sensor_settings(set_required_settings,&bme_sensor);
/* Set the power mode */
rslt = bme680_set_sensor_mode(&bme_sensor);
HDC2080 hdc_sensor;
num_err = HDC2080_init(&hdc_sensor, &hi2c1);
TDE5531 CO2_sensor;
num_err = 0;
num_err = TDE5531_init(&CO2_sensor, &hi2c1);
//SPS30 pm_sensor;
//rdy = SPS30_init(&pm_sensor, &hi2c1);
/* Get the total measurement duration so as to sleep or wait till the
* measurement is complete */
uint16_t meas_period;
bme680_get_profile_dur(&meas_period, &bme_sensor);
struct bme680_field_data bme_data;
struct sps30_measurement m;
int16_t ret;
while (sps30_probe() != 0) {
printf("SPS sensor probing failed\n");
sensirion_sleep_usec(1000000); /* wait 1s */
}
printf("SPS sensor probing successful\n");
uint8_t fw_major;
uint8_t fw_minor;
ret = sps30_read_firmware_version(&fw_major, &fw_minor);
if (ret) {
printf("error reading firmware version\n");
} else {
printf("FW: %u.%u\n", fw_major, fw_minor);
}
char serial_number[SPS30_MAX_SERIAL_LEN];
ret = sps30_get_serial(serial_number);
if (ret) {
printf("error reading serial number\n");
} else {
printf("Serial Number: %s\n", serial_number);
}
ret = sps30_start_measurement();
if (ret < 0)
printf("error starting measurement\n");
printf("measurements started\n");
// Init lcd using one of the stm32HAL i2c typedefs
// ssd1306_Init(&hi2c1);
/* USER CODE END 2 */
/* Infinite loop /
/ USER CODE BEGIN WHILE /
while (1)
{
/ USER CODE END WHILE */
// HAL_Delay(meas_period); /* Delay till the measurement is ready */
// rslt = bme680_get_sensor_data(&bme_data, &bme_sensor);
// printf("T: %.2f degC, P: %.2f hPa, H %.2f %%rH ", bme_data.temperature / 100.0f,
// bme_data.pressure / 100.0f, bme_data.humidity / 1000.0f );
/* Avoid using measurements from an unstable heating setup */
// if(bme_data.status & BME680_GASM_VALID_MSK)
// printf(", G: %d ohms", bme_data.gas_resistance);
// printf("\r\n");
/* Trigger the next measurement if you would like to read data out continuously */
// if (bme_sensor.power_mode == BME680_FORCED_MODE) {
// rslt = bme680_set_sensor_mode(&bme_sensor);
// }
// HAL_Delay(5000);
sensirion_sleep_usec(SPS30_MEASUREMENT_DURATION_USEC); /* wait 1s */
ret = sps30_read_measurement(&m);
if (ret < 0) {
printf("error reading measurement\n");
} else {
printf("measured values:\n"
"\t%0.2f pm1.0\n"
"\t%0.2f pm2.5\n"
"\t%0.2f pm4.0\n"
"\t%0.2f pm10.0\n"
"\t%0.2f nc0.5\n"
"\t%0.2f nc1.0\n"
"\t%0.2f nc2.5\n"
"\t%0.2f nc4.5\n"
"\t%0.2f nc10.0\n"
"\t%0.2f typical particle size\n\n",
m.mc_1p0, m.mc_2p5, m.mc_4p0, m.mc_10p0, m.nc_0p5, m.nc_1p0,
m.nc_2p5, m.nc_4p0, m.nc_10p0, m.typical_particle_size);
}
/* printf("Hello World\n\r");
HAL_Delay(1000);
HAL_UART_Transmit(&huart1, "hello\n", 6, 1000);
HAL_Delay(1000);
rdy = sps30_wake(&pm_sensor);
rdy = getPMversion();
rdy = getSFA30_id();
rdy = getPIM_id();
rdy = sps30_start_int(&pm_sensor);
// HAL_Delay(5000);
// HAL_Delay(5000);
// HAL_Delay(5000);
// HAL_Delay(5000);
rdy = sps30_getData(&pm_sensor);
rdy = sps30_getStatus(&pm_sensor);
rdy = 1;
// if (rdy == sps30_rdy(&pm_sensor)){
// rdy = sps30_stop(&pm_sensor);
// rdy = sps30_getData(&pm_sensor);
//}// end if
*/
}
/* USER CODE END 3 */
}
/**
- @brief System Clock Configuration
- @RetVal None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
- in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.LSIState = RCC_LSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1|RCC_PERIPHCLK_I2C1
|RCC_PERIPHCLK_I2C3|RCC_PERIPHCLK_RTC;
PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_PCLK1;
PeriphClkInit.I2c3ClockSelection = RCC_I2C3CLKSOURCE_PCLK1;
PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
}
/**
/* USER CODE BEGIN ADC_Init 0 */
/* USER CODE END ADC_Init 0 */
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC_Init 1 */
/* USER CODE END ADC_Init 1 */
/** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc.Instance = ADC1;
hadc.Init.OversamplingMode = DISABLE;
hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV1;
hadc.Init.Resolution = ADC_RESOLUTION_12B;
hadc.Init.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc.Init.ContinuousConvMode = DISABLE;
hadc.Init.DiscontinuousConvMode = DISABLE;
hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc.Init.DMAContinuousRequests = DISABLE;
hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc.Init.LowPowerAutoWait = DISABLE;
hadc.Init.LowPowerFrequencyMode = DISABLE;
hadc.Init.LowPowerAutoPowerOff = DISABLE;
if (HAL_ADC_Init(&hadc) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel to be converted.
*/
sConfig.Channel = ADC_CHANNEL_2;
sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel to be converted.
*/
sConfig.Channel = ADC_CHANNEL_3;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel to be converted.
*/
sConfig.Channel = ADC_CHANNEL_4;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel to be converted.
/
sConfig.Channel = ADC_CHANNEL_5;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
/ USER CODE BEGIN ADC_Init 2 */
/* USER CODE END ADC_Init 2 */
}
/**
/* USER CODE BEGIN CRC_Init 0 */
/* USER CODE END CRC_Init 0 */
/* USER CODE BEGIN CRC_Init 1 */
/* USER CODE END CRC_Init 1 /
hcrc.Instance = CRC;
hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_ENABLE;
hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_ENABLE;
hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE;
hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE;
hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;
if (HAL_CRC_Init(&hcrc) != HAL_OK)
{
Error_Handler();
}
/ USER CODE BEGIN CRC_Init 2 */
/* USER CODE END CRC_Init 2 */
}
/**
- @brief I2C1 Initialization Function
- @param None
- @RetVal None
*/
static void MX_I2C1_Init(void)
{
/* USER CODE BEGIN I2C1_Init 0 */
/* USER CODE END I2C1_Init 0 */
/* USER CODE BEGIN I2C1_Init 1 */
/* USER CODE END I2C1_Init 1 */
hi2c1.Instance = I2C1;
hi2c1.Init.Timing = 0x00303D5B;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
Error_Handler();
}
/** Configure Analogue filter
*/
if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
{
Error_Handler();
}
/** Configure Digital filter
/
if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK)
{
Error_Handler();
}
/ USER CODE BEGIN I2C1_Init 2 */
/* USER CODE END I2C1_Init 2 */
}
/**
- @brief I2C3 Initialization Function
- @param None
- @RetVal None
*/
static void MX_I2C3_Init(void)
{
/* USER CODE BEGIN I2C3_Init 0 */
/* USER CODE END I2C3_Init 0 */
/* USER CODE BEGIN I2C3_Init 1 */
/* USER CODE END I2C3_Init 1 */
hi2c3.Instance = I2C3;
hi2c3.Init.Timing = 0x00303D5B;
hi2c3.Init.OwnAddress1 = 0;
hi2c3.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c3.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c3.Init.OwnAddress2 = 0;
hi2c3.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
hi2c3.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c3.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c3) != HAL_OK)
{
Error_Handler();
}
/** Configure Analogue filter
*/
if (HAL_I2CEx_ConfigAnalogFilter(&hi2c3, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
{
Error_Handler();
}
/** Configure Digital filter
/
if (HAL_I2CEx_ConfigDigitalFilter(&hi2c3, 0) != HAL_OK)
{
Error_Handler();
}
/ USER CODE BEGIN I2C3_Init 2 */
/* USER CODE END I2C3_Init 2 */
}
/**
/* USER CODE BEGIN RTC_Init 0 */
/* USER CODE END RTC_Init 0 */
RTC_TimeTypeDef sTime = {0};
RTC_DateTypeDef sDate = {0};
/* USER CODE BEGIN RTC_Init 1 */
/* USER CODE END RTC_Init 1 */
/** Initialize RTC Only
*/
hrtc.Instance = RTC;
hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
hrtc.Init.AsynchPrediv = 127;
hrtc.Init.SynchPrediv = 255;
hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
if (HAL_RTC_Init(&hrtc) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN Check_RTC_BKUP */
/* USER CODE END Check_RTC_BKUP */
/** Initialize RTC and set the Time and Date
*/
sTime.Hours = 0x0;
sTime.Minutes = 0x0;
sTime.Seconds = 0x0;
sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sTime.StoreOperation = RTC_STOREOPERATION_RESET;
if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
sDate.WeekDay = RTC_WEEKDAY_MONDAY;
sDate.Month = RTC_MONTH_JANUARY;
sDate.Date = 0x1;
sDate.Year = 0x0;
if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN RTC_Init 2 */
/* USER CODE END RTC_Init 2 */
}
/**
- @brief SPI1 Initialization Function
- @param None
- @RetVal None
*/
static void MX_SPI1_Init(void)
{
/* USER CODE BEGIN SPI1_Init 0 */
/* USER CODE END SPI1_Init 0 */
/* USER CODE BEGIN SPI1_Init 1 */
/* USER CODE END SPI1_Init 1 /
/ SPI1 parameter configuration*/
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI1_Init 2 */
/* USER CODE END SPI1_Init 2 */
}
/**
- @brief USART1 Initialization Function
- @param None
- @RetVal None
*/
static void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 /
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
/ USER CODE BEGIN USART1_Init 2 */
/* USER CODE END USART1_Init 2 */
}
/**
- @brief USART4 Initialization Function
- @param None
- @RetVal None
*/
static void MX_USART4_UART_Init(void)
{
/* USER CODE BEGIN USART4_Init 0 */
/* USER CODE END USART4_Init 0 */
/* USER CODE BEGIN USART4_Init 1 */
/* USER CODE END USART4_Init 1 /
huart4.Instance = USART4;
huart4.Init.BaudRate = 115200;
huart4.Init.WordLength = UART_WORDLENGTH_8B;
huart4.Init.StopBits = UART_STOPBITS_1;
huart4.Init.Parity = UART_PARITY_NONE;
huart4.Init.Mode = UART_MODE_TX_RX;
huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart4.Init.OverSampling = UART_OVERSAMPLING_16;
huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart4) != HAL_OK)
{
Error_Handler();
}
/ USER CODE BEGIN USART4_Init 2 */
/* USER CODE END USART4_Init 2 */
}
/**
- @brief GPIO Initialization Function
- @param None
- @RetVal None
/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/ USER CODE BEGIN MX_GPIO_Init_1 /
/ USER CODE END MX_GPIO_Init_1 */
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, ERVH_Pin|ERVL_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_RESET);
/*Configure GPIO pins : CO2Ready_Pin TempHumReady_Pin */
GPIO_InitStruct.Pin = CO2Ready_Pin|TempHumReady_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : ERVH_Pin ERVL_Pin */
GPIO_InitStruct.Pin = ERVH_Pin|ERVL_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pin : PA12 */
GPIO_InitStruct.Pin = GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pin : INTPIM_Pin */
GPIO_InitStruct.Pin = INTPIM_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(INTPIM_GPIO_Port, &GPIO_InitStruct);
/* USER CODE BEGIN MX_GPIO_Init_2 /
/ USER CODE END MX_GPIO_Init_2 */
}
/* USER CODE BEGIN 4 */
void serial_string10(char temp[10]){
for(int i = 0; i < 10; i++){
data[i] = temp[i];
}// end for
}//end serial strin10
uint8_t getPMversion(){
HAL_StatusTypeDef status;
//uint8_t pmAddrPtr[2]= {0xD1, 0x00};
status = HAL_I2C_Mem_Read(&hi2c1, 0x69 << 1, 0xD100, 2, ver_buf, 3, 1000);
if (status == HAL_OK){
serial_string10("version: \n");
HAL_UART_Transmit(&huart1, data, 10, 1000);
HAL_Delay(1000);
HAL_UART_Transmit(&huart1, ver_buf, 3, 1000);
HAL_Delay(1000);
return 1;
}// end if
else return 0;
}///end getpmversion
int8_t bme680I2cRead(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len) {
int8_t result;
if (HAL_I2C_Master_Transmit(&hi2c1, (dev_id << 1), ®_addr, 1, HAL_MAX_DELAY) != HAL_OK) {
result = -1;
} else if (HAL_I2C_Master_Receive (&hi2c1, (dev_id << 1) | 0x01, reg_data, len, HAL_MAX_DELAY) != HAL_OK) {
result = -1;
} else {
result = 0;
}
return result;
}/// end bme read
int8_t bme680I2cWrite(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len) {
int8_t result;
int8_t *buf;
// Allocate and load I2C transmit buffer
buf = malloc(len + 1);
buf[0] = reg_addr;
memcpy(buf + 1, reg_data, len);
if (HAL_I2C_Master_Transmit(&hi2c1, (dev_id << 1), (uint8_t *) buf, len + 1, HAL_MAX_DELAY) != HAL_OK) {
result = -1;
} else {
result = 0;
}
free(buf);
return result;
}// end bme write
uint8_t getSFA30_id(){
HAL_StatusTypeDef status;
id_buf[48] = '\n';
//uint8_t pmAddrPtr[2]= {0xD1, 0x00};
status = HAL_I2C_Mem_Read(&hi2c1, 0x5D << 1, 0xD060, 2, id_buf, 48, 1000);
if (status == HAL_OK){
serial_string10("version: \n");
HAL_UART_Transmit(&huart1, data, 10, 1000);
HAL_Delay(1000);
HAL_UART_Transmit(&huart1, id_buf, 49, 1000);
HAL_Delay(1000);
return 1;
}// end if
return 0;
}//end getSFA30_id
uint8_t getPIM_id(){
HAL_StatusTypeDef status;
pim_buf[2] = '\n';
//uint8_t pmAddrPtr[2]= {0xD1, 0x00};
status = HAL_I2C_Mem_Read(&hi2c1, 0x18 << 1, 0xFBFA, 2, pim_buf, 2, 1000);
if (status == HAL_OK){
serial_string10("version: \n");
HAL_UART_Transmit(&huart1, data, 10, 1000);
HAL_Delay(1000);
HAL_UART_Transmit(&huart1, pim_buf, 2, 1000);
HAL_Delay(1000);
return 1;
}// end if
return 0;
}// end getPIM_id
/**
- @brief Retargets the C library printf function to the USART.
- @param None
- @RetVal None
/
PUTCHAR_PROTOTYPE
{
/ Place your implementation of fputc here /
/ e.g. write a character to the USART1 and Loop until the end of transmission */
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
/* USER CODE END 4 */
/**
- @brief This function is executed in case of error occurrence.
- @RetVal None
/
void Error_Handler(void)
{
/ USER CODE BEGIN Error_Handler_Debug /
/ User can add his own implementation to report the HAL error return state /
__disable_irq();
while (1)
{
}
/ USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
- @brief Reports the name of the source file and the source line number
-
where the assert_param error has occurred.
- @param file: pointer to the source file name
- @param line: assert_param error line source number
- @RetVal None
*/
void assert_failed(uint8_t file, uint32_t line)
{
/ USER CODE BEGIN 6 /
/ User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) /
/ USER CODE END 6 /
}
#endif / USE_FULL_ASSERT */