first commit

This commit is contained in:
2024-10-12 22:13:04 +02:00
commit d3e8839f9d
1085 changed files with 792189 additions and 0 deletions

View File

@ -0,0 +1,106 @@
/*
* ADBMS_Abstraction.h
*
* Created on: 14.07.2022
* Author: max
*/
#ifndef INC_ADBMS_ABSTRACTION_H_
#define INC_ADBMS_ABSTRACTION_H_
#include "ADBMS_CMD_MAKROS.h"
#include "ADBMS_LL_Driver.h"
#include "main.h"
#define MAXIMUM_CELL_VOLTAGES 16
#define MAXIMUM_AUX_VOLTAGES 10
#define MAXIMUM_GPIO 10
//see table 103 in datasheet (page 71)
#define DEFAULT_UV 417 //VUV * 16 * 150 uV + 1.5 V Default Setting 2.5V
#define DEFAULT_OV 1125 //VOV * 16 * 150 uV + 1.5 V Default Setting 4.2V
#define mV_from_ADBMS6830(x) (((((int16_t) (x))) * 0.150) + 1500)
struct ADBMS6830_Internal_Status {
uint16 CS_FLT : 16; //ADC fault - mismatch between S- and C-ADC
uint16 : 3;
uint16 CCTS : 13; //Conversion counter
uint16 VA_OV : 1; //5V analog supply overvoltage
uint16 VA_UV : 1; //5V analog supply undervoltage
uint16 VD_OV : 1; //3V digital supply overvoltage
uint16 VD_UV : 1; //3V digital supply undervoltage
uint16 CED : 1; //C-ADC single trim error (correctable)
uint16 CMED : 1; //C-ADC multiple trim error (uncorrectable)
uint16 SED : 1; //S-ADC single trim error (correctable)
uint16 SMED : 1; //S-ADC multiple trim error (uncorrectable)
uint16 VDEL : 1; //Latent supply voltage error
uint16 VDE : 1; //Supply voltage error
uint16 COMPARE : 1; //Comparasion between S- and C-ADC active
uint16 SPIFLT : 1; //SPI fault
uint16 SLEEP : 1; //Sleep mode previously entered
uint16 THSD : 1; //Thermal shutdown
uint16 TMODCHK : 1; //Test mode check
uint16 OSCCHK : 1; //Oscillator check
};
typedef struct {
int16_t cellVoltages[MAXIMUM_CELL_VOLTAGES];
int16_t auxVoltages[MAXIMUM_AUX_VOLTAGES];
struct ADBMS6830_Internal_Status status;
uint16 internalDieTemp;
uint16 analogSupplyVoltage;
uint16 digitalSupplyVoltage;
uint16 sumOfCellMeasurements;
uint16 refVoltage;
uint16 GPIO_Values[MAXIMUM_GPIO];
uint32 overVoltage;
uint32 underVoltage;
} Cell_Module;
uint8 amsReset();
uint8 initAMS(SPI_HandleTypeDef* hspi, uint8 numofcells, uint8 numofaux);
uint8 amsWakeUp();
uint8 amsCellMeasurement(Cell_Module* module);
uint8 amsConfigCellMeasurement(uint8 numberofChannels);
uint8 amsAuxAndStatusMeasurement(Cell_Module* module);
uint8 amsConfigAuxMeasurement(uint16 Channels);
uint8 amsConfigGPIO(uint16 gpios);
uint8 amsSetGPIO(uint16 gpios);
uint8 readGPIO(Cell_Module* module);
uint8 amsConfigBalancing(uint32 Channels, uint8 dutyCycle);
uint8 amsStartBalancing(uint8 dutyCycle);
uint8 amsStopBalancing();
uint8 amsSelfTest();
uint8 amsConfigOverUnderVoltage(uint16 overVoltage, uint16 underVoltage);
uint8 amsCheckUnderOverVoltage(Cell_Module* module);
uint8 amsConfigOverVoltage(uint16 overVoltage);
uint8 amscheckOpenCellWire(Cell_Module* module);
uint8 amsClearStatus();
uint8 amsClearAux();
uint8 amsClearCells();
uint8 amsSendWarning();
uint8 amsSendError();
uint8 amsClearWarning();
uint8 amsClearError();
uint8 amsReadCellVoltages(Cell_Module* module);
#endif /* INC_ADBMS_ABSTRACTION_H_ */

171
Core/Inc/ADBMS_CMD_MAKROS.h Normal file
View File

@ -0,0 +1,171 @@
/*
* ADBMS_CMD_MAKROS.h
*
* Created on: 14.07.2022
* Author: max
*/
#ifndef INC_ADBMS_CMD_MAKROS_H_
#define INC_ADBMS_CMD_MAKROS_H_
#include <stdint.h>
#define WRCFGA 0x0001 // Write Configuration Register Group A
#define RDCFGA 0x0002 // Read Configuration Register Group A
#define WRCFGB 0x0024 // Write Configuration Register Group B
#define RDCFGB 0x0026 // Read Configuration Register Group B
#define WRPWMA 0x0020 // Write PWM Register Group A
#define RDPWMA 0x0022 // Read PWM Register Group A
#define WRPWMB 0x0021 // Write PWM Register Group B
#define RDPWMB 0x0023 // Read PWM Register Group B
#define RDCVA 0x0004 // Read Cell Voltage Register Group A
#define RDCVB 0x0006 // Read Cell Voltage Register Group B
#define RDCVC 0x0008 // Read Cell Voltage Register Group C
#define RDCVD 0x000A // Read Cell Voltage Register Group D
#define RDCVE 0x0009 // Read Cell Voltage Register Group E
#define RDCVF 0x000B // Read Cell Voltage Register Group F
#define RDCVALL 0x000C // Read All Cell Voltage Register Groups
#define RDACA 0x0044 // Read averaged Cell Voltage Register Group A
#define RDACB 0x0046 // Read averaged Cell Voltage Register Group B
#define RDACC 0x0048 // Read averaged Cell Voltage Register Group C
#define RDACD 0x004A // Read averaged Cell Voltage Register Group D
#define RDACE 0x0049 // Read averaged Cell Voltage Register Group E
#define RDACF 0x004B // Read averaged Cell Voltage Register Group F
#define RDACALL 0x004C // Read averaged All Cell Voltage Register Groups
#define RDAUXA 0x0019 // Read Auxilliary Register Group A
#define RDAUXB 0x001A // Read Auxilliary Register Group B
#define RDAUXC 0x001B // Read Auxilliary Register Group C
#define RDAUXD 0x001F // Read Auxilliary Register Group D
#define RDAUXALL 0x0035 // Read All Auxilliary and Status Register Groups
#define RDSTATA 0x0030 // Read Status Register Group A
#define RDSTATB 0x0031 // Read Status Register Group B
#define RDSTATC 0x0032 // Read Status Register Group C
#define RDSTATD 0x0033 // Read Status Register Group D
#define RDSTATE 0x0034 // Read Status Register Group E
#define ADCV 0x0260 // Start Cell Voltage Conversion with C-ADC
#define ADCV_OW_0 (1u << 0)
#define ADCV_OW_1 (1u << 1)
#define ADCV_RSTF (1u << 2)
#define ADCV_DCP (1u << 4)
#define ADCV_CONT (1u << 7) // Continuous Mode
#define ADCV_RD (1u << 8) // Redundancy Mode
#define ADSV 0x0168 // Start Cell Voltage Conversion with S-ADC
#define ADSV_OW_0 (1u << 0)
#define ADSV_OW_1 (1u << 1)
#define ADSV_DCP (1u << 4)
#define ADSV_CONT (1u << 7) // Continuous Mode
#define ADAX 0x0410 // Start GPIOs and Vref2 Conversion
#define ADAX_CONV_ALL 0x0000 // Convert all GPIOs, VREF2, VD, VA, ITEMP
#define ADAX_OW (1u << 8)
#define CLRCELL 0x0711 // Clear Cell Voltage Register Groups
#define CLRAUX 0x0712 // Clear Auxiliary Register Groups
#define CLOVUV 0x0715 // Clear Overvoltage and Undervoltage Flags
#define CLRFLAG 0x0717 // Clear all Flags
#define PLADC 0x0718 // Poll ADC Conversion Status
#define PLAUX 0x071E // Poll AUX Conversion Status
#define SRST 0x0027 //Soft reset
#define DIAGN 0x0715 // Diagnos MUX and Poll Status
#define WRCOMM 0x0721 // Write COMM Register Group
#define RDCOMM 0x0722 // Read COMM Register Group
#define STCOMM 0x0723 // Start I2C/SPI Communication
#define MUTE 0x0028 // Mute Discharge
#define UNMUTE 0x0029 // Unmute Discharge
/* GPIO Selection for ADC Converion
* 000: GPIO1 to 5, 2nd Reference, GPIO 6 to 9
* 001: GPIO1 and GPIO6
* 010 GPIO2 and GPIO7
* 011 GPIO3 and GPIO8
* 100 GPIO4 and GPIO9
* 101 GPIO5
* 110 2nd Reference
*/
#define CHG000 (0x00)
#define CHG001 (0x01)
#define CHG010 (0x02)
#define CHG011 (0x03)
#define CHG100 (0x04)
#define CHG101 (0x05)
#define CHG110 (0x06)
/* Status Group Selection
* 000: SC,ITMP,VA,VD
* 001: SC
* 010: ITMP
* 011: VA
* 100: VD
*/
#define CHST000 (0x00)
#define CHST001 (0x01)
#define CHST010 (0x02)
#define CHST011 (0x03)
#define CHST100 (0x04)
#define PEC_FIELD_SIZE 2
#define CFG_GROUP_A_SIZE 6
#define CFG_GROUP_B_SIZE 6
#define PWM_GROUP_A_SIZE 6
#define PWM_GROUP_B_SIZE 2
#define CV_GROUP_A_SIZE 6
#define CV_GROUP_B_SIZE 6
#define CV_GROUP_C_SIZE 6
#define CV_GROUP_D_SIZE 6
#define CV_GROUP_E_SIZE 6
#define CV_GROUP_F_SIZE 6
#define AUX_GROUP_A_SIZE 6
#define AUX_GROUP_B_SIZE 6
#define AUX_GROUP_C_SIZE 6
#define AUX_GROUP_D_SIZE 6
#define STATUS_GROUP_A_SIZE 6
#define STATUS_GROUP_B_SIZE 6
#define STATUS_GROUP_C_SIZE 6
#define STATUS_GROUP_D_SIZE 6
#define STATUS_GROUP_E_SIZE 6
#define COMM_GROUP_SIZE 6
#define S_CONTROL_GROUP_SIZE 6
#define PWM_GROUP_SIZE 6
#define PWM_S_CONTROL_GROUP_B_SIZE 6
#define CFG_GROUP_A_ID 1
#define CFG_GROUP_B_ID 2
#define CV_GROUP_A_ID 3
#define CV_GROUP_B_ID 4
#define CV_GROUP_C_ID 5
#define CV_GROUP_D_ID 6
#define CV_GROUP_E_ID 7
#define CV_GROUP_F_ID 8
#define AUX_GROUP_A_ID 9
#define AUX_GROUP_B_ID 10
#define AUX_GROUP_C_ID 11
#define AUX_GROUP_D_ID 12
#define STATUS_GROUP_A_ID 13
#define STATUS_GROUP_B_ID 14
#define COMM_GROUP_ID 15
#define S_CONTROL_GROUP_ID 16
#define PWM_GROUP_ID 17
#define PWM_S_CONTROL_GROUP_B_ID 18
#endif /* INC_ADBMS_CMD_MAKROS_H_ */

View File

@ -0,0 +1,44 @@
/*
* ADBMS_LL_Driver.h
*
* Created on: 05.06.2022
* Author: max
*/
#ifndef ADBMS_LL_DRIVER_H_
#define ADBMS_LL_DRIVER_H_
#define TARGET_STM32
#include "main.h"
#ifdef TARGET_STM32
typedef uint8_t uint8;
typedef uint16_t uint16;
typedef uint32_t uint32;
#endif
uint8 adbmsDriverInit(SPI_HandleTypeDef* hspi);
uint8 calculateCommandPEC(uint8* data, uint8 datalen);
uint16 updateCommandPEC(uint16 currentPEC, uint8 din);
uint8 checkCommandPEC(uint8* data, uint8 datalen);
uint8 calculateDataPEC(uint8* data, uint8 datalen);
uint16 updateDataPEC(uint16 currentPEC, uint8 din);
uint8 checkDataPEC(uint8* data, uint8 datalen);
uint8 writeCMD(uint16 command, uint8* args, uint8 arglen);
uint8 readCMD(uint16 command, uint8* buffer, uint8 buflen);
uint8 pollCMD(uint16 command);
void mcuAdbmsCSLow();
void mcuAdbmsCSHigh();
uint8 mcuSPITransmit(uint8* buffer, uint8 buffersize);
uint8 mcuSPIReceive(uint8* buffer, uint8 buffersize);
uint8 mcuSPITransmitReceive(uint8* rxbuffer, uint8* txbuffer, uint8 buffersize);
uint8 wakeUpCmd();
void mcuDelay(uint16 delay);
#endif /* ADBMS_LL_DRIVER_H_ */

40
Core/Inc/AMS_HighLevel.h Normal file
View File

@ -0,0 +1,40 @@
/*
* AMS_HighLevel.h
*
* Created on: 20.07.2022
* Author: max
*/
#ifndef INC_AMS_HIGHLEVEL_H_
#define INC_AMS_HIGHLEVEL_H_
#include "ADBMS_Abstraction.h"
#include "ADBMS_CMD_MAKROS.h"
#include "ADBMS_LL_Driver.h"
#include <stdbool.h>
typedef enum {
AMSDEACTIVE,
AMSIDLE,
AMSCHARGING,
AMSIDLEBALANCING,
AMSDISCHARGING,
AMSWARNING,
AMSERROR
} amsState;
extern amsState currentAMSState;
extern Cell_Module module;
extern uint32_t balancedCells;
extern bool BalancingActive;
extern uint8_t numberofCells;
extern uint8_t numberofAux;
uint8_t AMS_Init(SPI_HandleTypeDef* hspi);
void AMS_Loop();
uint8_t AMS_Idle_Loop();
#endif /* INC_AMS_HIGHLEVEL_H_ */

16
Core/Inc/TMP1075.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef INC_TMP1075_H_
#define INC_TMP1075_H_
#include "stm32f3xx_hal.h"
#include <stdint.h>
#define N_CELLS 16
#define N_TEMP_SENSORS 8
extern int16_t tmp1075_temps[N_TEMP_SENSORS];
HAL_StatusTypeDef tmp1075_init(I2C_HandleTypeDef* hi2c);
HAL_StatusTypeDef tmp1075_measure();
HAL_StatusTypeDef tmp1075_sensor_init(int n);
HAL_StatusTypeDef tmp1075_sensor_read(int n, int16_t* res);
#endif // INC_TMP1075_H_

83
Core/Inc/main.h Normal file
View File

@ -0,0 +1,83 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.h
* @brief : Header for main.c file.
* This file contains the common defines of the application.
******************************************************************************
* @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 */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MAIN_H
#define __MAIN_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f3xx_hal.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
/* USER CODE END ET */
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
/* USER CODE END EC */
/* Exported macro ------------------------------------------------------------*/
/* USER CODE BEGIN EM */
/* USER CODE END EM */
/* Exported functions prototypes ---------------------------------------------*/
void Error_Handler(void);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */
/* Private defines -----------------------------------------------------------*/
#define B1_Pin GPIO_PIN_13
#define B1_GPIO_Port GPIOC
#define USART_TX_Pin GPIO_PIN_2
#define USART_TX_GPIO_Port GPIOA
#define USART_RX_Pin GPIO_PIN_3
#define USART_RX_GPIO_Port GPIOA
#define TMS_Pin GPIO_PIN_13
#define TMS_GPIO_Port GPIOA
#define TCK_Pin GPIO_PIN_14
#define TCK_GPIO_Port GPIOA
#define SWO_Pin GPIO_PIN_3
#define SWO_GPIO_Port GPIOB
#define CSB_Pin GPIO_PIN_6
#define CSB_GPIO_Port GPIOB
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
#ifdef __cplusplus
}
#endif
#endif /* __MAIN_H */

View File

@ -0,0 +1,359 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32f3xx_hal_conf.h
* @brief HAL configuration file.
******************************************************************************
* @attention
*
* Copyright (c) 2016 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 */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F3xx_HAL_CONF_H
#define __STM32F3xx_HAL_CONF_H
#ifdef __cplusplus
extern "C" {
#endif
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* ########################## Module Selection ############################## */
/**
* @brief This is the list of modules to be used in the HAL driver
*/
#define HAL_MODULE_ENABLED
/*#define HAL_ADC_MODULE_ENABLED */
/*#define HAL_CRYP_MODULE_ENABLED */
/*#define HAL_CAN_MODULE_ENABLED */
/*#define HAL_CEC_MODULE_ENABLED */
/*#define HAL_NAND_MODULE_ENABLED */
/*#define HAL_NOR_MODULE_ENABLED */
/*#define HAL_PCCARD_MODULE_ENABLED */
/*#define HAL_SRAM_MODULE_ENABLED */
/*#define HAL_HRTIM_MODULE_ENABLED */
/*#define HAL_OPAMP_MODULE_ENABLED */
/*#define HAL_SDADC_MODULE_ENABLED */
/*#define HAL_TSC_MODULE_ENABLED */
/*#define HAL_COMP_MODULE_ENABLED */
/*#define HAL_CRC_MODULE_ENABLED */
/*#define HAL_CRYP_MODULE_ENABLED */
/*#define HAL_DAC_MODULE_ENABLED */
/*#define HAL_I2S_MODULE_ENABLED */
/*#define HAL_IWDG_MODULE_ENABLED */
/*#define HAL_LCD_MODULE_ENABLED */
/*#define HAL_LPTIM_MODULE_ENABLED */
/*#define HAL_RNG_MODULE_ENABLED */
/*#define HAL_RTC_MODULE_ENABLED */
#define HAL_SPI_MODULE_ENABLED
/*#define HAL_TIM_MODULE_ENABLED */
/*#define HAL_UART_MODULE_ENABLED */
/*#define HAL_USART_MODULE_ENABLED */
/*#define HAL_IRDA_MODULE_ENABLED */
/*#define HAL_SMARTCARD_MODULE_ENABLED */
/*#define HAL_SMBUS_MODULE_ENABLED */
/*#define HAL_WWDG_MODULE_ENABLED */
/*#define HAL_PCD_MODULE_ENABLED */
#define HAL_GPIO_MODULE_ENABLED
#define HAL_EXTI_MODULE_ENABLED
/* #define HAL_CAN_LEGACY_MODULE_ENABLED */
#define HAL_DMA_MODULE_ENABLED
#define HAL_RCC_MODULE_ENABLED
#define HAL_FLASH_MODULE_ENABLED
#define HAL_PWR_MODULE_ENABLED
#define HAL_CORTEX_MODULE_ENABLED
#define HAL_I2C_MODULE_ENABLED
/* ########################## HSE/HSI Values adaptation ##################### */
/**
* @brief Adjust the value of External High Speed oscillator (HSE) used in your application.
* This value is used by the RCC HAL module to compute the system frequency
* (when HSE is used as system clock source, directly or through the PLL).
*/
#if !defined (HSE_VALUE)
#define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */
/**
* @brief In the following line adjust the External High Speed oscillator (HSE) Startup
* Timeout value
*/
#if !defined (HSE_STARTUP_TIMEOUT)
#define HSE_STARTUP_TIMEOUT ((uint32_t)100) /*!< Time out for HSE start up, in ms */
#endif /* HSE_STARTUP_TIMEOUT */
/**
* @brief Internal High Speed oscillator (HSI) value.
* This value is used by the RCC HAL module to compute the system frequency
* (when HSI is used as system clock source, directly or through the PLL).
*/
#if !defined (HSI_VALUE)
#define HSI_VALUE ((uint32_t)8000000) /*!< Value of the Internal oscillator in Hz*/
#endif /* HSI_VALUE */
/**
* @brief In the following line adjust the Internal High Speed oscillator (HSI) Startup
* Timeout value
*/
#if !defined (HSI_STARTUP_TIMEOUT)
#define HSI_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for HSI start up */
#endif /* HSI_STARTUP_TIMEOUT */
/**
* @brief Internal Low Speed oscillator (LSI) value.
*/
#if !defined (LSI_VALUE)
#define LSI_VALUE ((uint32_t)40000)
#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz
The real value may vary depending on the variations
in voltage and temperature. */
/**
* @brief External Low Speed oscillator (LSE) value.
*/
#if !defined (LSE_VALUE)
#define LSE_VALUE ((uint32_t)32768) /*!< Value of the External Low Speed oscillator in Hz */
#endif /* LSE_VALUE */
/**
* @brief Time out for LSE start up value in ms.
*/
#if !defined (LSE_STARTUP_TIMEOUT)
#define LSE_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for LSE start up, in ms */
#endif /* LSE_STARTUP_TIMEOUT */
/**
* @brief External clock source for I2S peripheral
* This value is used by the I2S HAL module to compute the I2S clock source
* frequency, this source is inserted directly through I2S_CKIN pad.
* - External clock generated through external PLL component on EVAL 303 (based on MCO or crystal)
* - External clock not generated on EVAL 373
*/
#if !defined (EXTERNAL_CLOCK_VALUE)
#define EXTERNAL_CLOCK_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz*/
#endif /* EXTERNAL_CLOCK_VALUE */
/* Tip: To avoid modifying this file each time you need to use different HSE,
=== you can define the HSE value in your toolchain compiler preprocessor. */
/* ########################### System Configuration ######################### */
/**
* @brief This is the HAL system configuration section
*/
#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */
#define TICK_INT_PRIORITY ((uint32_t)0) /*!< tick interrupt priority (lowest by default) */
#define USE_RTOS 0
#define PREFETCH_ENABLE 1
#define INSTRUCTION_CACHE_ENABLE 0
#define DATA_CACHE_ENABLE 0
#define USE_SPI_CRC 0U
#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */
#define USE_HAL_CAN_REGISTER_CALLBACKS 0U /* CAN register callback disabled */
#define USE_HAL_COMP_REGISTER_CALLBACKS 0U /* COMP register callback disabled */
#define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */
#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */
#define USE_HAL_SRAM_REGISTER_CALLBACKS 0U /* SRAM register callback disabled */
#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U /* SMBUS register callback disabled */
#define USE_HAL_NAND_REGISTER_CALLBACKS 0U /* NAND register callback disabled */
#define USE_HAL_NOR_REGISTER_CALLBACKS 0U /* NOR register callback disabled */
#define USE_HAL_PCCARD_REGISTER_CALLBACKS 0U /* PCCARD register callback disabled */
#define USE_HAL_HRTIM_REGISTER_CALLBACKS 0U /* HRTIM register callback disabled */
#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */
#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */
#define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */
#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U /* IRDA register callback disabled */
#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U /* SMARTCARD register callback disabled */
#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */
#define USE_HAL_OPAMP_REGISTER_CALLBACKS 0U /* OPAMP register callback disabled */
#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */
#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */
#define USE_HAL_I2S_REGISTER_CALLBACKS 0U /* I2S register callback disabled */
#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */
#define USE_HAL_TSC_REGISTER_CALLBACKS 0U /* TSC register callback disabled */
#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */
/* ########################## Assert Selection ############################## */
/**
* @brief Uncomment the line below to expanse the "assert_param" macro in the
* HAL drivers code
*/
/* #define USE_FULL_ASSERT 1U */
/* Includes ------------------------------------------------------------------*/
/**
* @brief Include module's header file
*/
#ifdef HAL_RCC_MODULE_ENABLED
#include "stm32f3xx_hal_rcc.h"
#endif /* HAL_RCC_MODULE_ENABLED */
#ifdef HAL_GPIO_MODULE_ENABLED
#include "stm32f3xx_hal_gpio.h"
#endif /* HAL_GPIO_MODULE_ENABLED */
#ifdef HAL_EXTI_MODULE_ENABLED
#include "stm32f3xx_hal_exti.h"
#endif /* HAL_EXTI_MODULE_ENABLED */
#ifdef HAL_DMA_MODULE_ENABLED
#include "stm32f3xx_hal_dma.h"
#endif /* HAL_DMA_MODULE_ENABLED */
#ifdef HAL_CORTEX_MODULE_ENABLED
#include "stm32f3xx_hal_cortex.h"
#endif /* HAL_CORTEX_MODULE_ENABLED */
#ifdef HAL_ADC_MODULE_ENABLED
#include "stm32f3xx_hal_adc.h"
#endif /* HAL_ADC_MODULE_ENABLED */
#ifdef HAL_CAN_MODULE_ENABLED
#include "stm32f3xx_hal_can.h"
#endif /* HAL_CAN_MODULE_ENABLED */
#ifdef HAL_CAN_LEGACY_MODULE_ENABLED
#include "stm32f3xx_hal_can_legacy.h"
#endif /* HAL_CAN_LEGACY_MODULE_ENABLED */
#ifdef HAL_CEC_MODULE_ENABLED
#include "stm32f3xx_hal_cec.h"
#endif /* HAL_CEC_MODULE_ENABLED */
#ifdef HAL_COMP_MODULE_ENABLED
#include "stm32f3xx_hal_comp.h"
#endif /* HAL_COMP_MODULE_ENABLED */
#ifdef HAL_CRC_MODULE_ENABLED
#include "stm32f3xx_hal_crc.h"
#endif /* HAL_CRC_MODULE_ENABLED */
#ifdef HAL_DAC_MODULE_ENABLED
#include "stm32f3xx_hal_dac.h"
#endif /* HAL_DAC_MODULE_ENABLED */
#ifdef HAL_FLASH_MODULE_ENABLED
#include "stm32f3xx_hal_flash.h"
#endif /* HAL_FLASH_MODULE_ENABLED */
#ifdef HAL_SRAM_MODULE_ENABLED
#include "stm32f3xx_hal_sram.h"
#endif /* HAL_SRAM_MODULE_ENABLED */
#ifdef HAL_NOR_MODULE_ENABLED
#include "stm32f3xx_hal_nor.h"
#endif /* HAL_NOR_MODULE_ENABLED */
#ifdef HAL_NAND_MODULE_ENABLED
#include "stm32f3xx_hal_nand.h"
#endif /* HAL_NAND_MODULE_ENABLED */
#ifdef HAL_PCCARD_MODULE_ENABLED
#include "stm32f3xx_hal_pccard.h"
#endif /* HAL_PCCARD_MODULE_ENABLED */
#ifdef HAL_HRTIM_MODULE_ENABLED
#include "stm32f3xx_hal_hrtim.h"
#endif /* HAL_HRTIM_MODULE_ENABLED */
#ifdef HAL_I2C_MODULE_ENABLED
#include "stm32f3xx_hal_i2c.h"
#endif /* HAL_I2C_MODULE_ENABLED */
#ifdef HAL_I2S_MODULE_ENABLED
#include "stm32f3xx_hal_i2s.h"
#endif /* HAL_I2S_MODULE_ENABLED */
#ifdef HAL_IRDA_MODULE_ENABLED
#include "stm32f3xx_hal_irda.h"
#endif /* HAL_IRDA_MODULE_ENABLED */
#ifdef HAL_IWDG_MODULE_ENABLED
#include "stm32f3xx_hal_iwdg.h"
#endif /* HAL_IWDG_MODULE_ENABLED */
#ifdef HAL_OPAMP_MODULE_ENABLED
#include "stm32f3xx_hal_opamp.h"
#endif /* HAL_OPAMP_MODULE_ENABLED */
#ifdef HAL_PCD_MODULE_ENABLED
#include "stm32f3xx_hal_pcd.h"
#endif /* HAL_PCD_MODULE_ENABLED */
#ifdef HAL_PWR_MODULE_ENABLED
#include "stm32f3xx_hal_pwr.h"
#endif /* HAL_PWR_MODULE_ENABLED */
#ifdef HAL_RTC_MODULE_ENABLED
#include "stm32f3xx_hal_rtc.h"
#endif /* HAL_RTC_MODULE_ENABLED */
#ifdef HAL_SDADC_MODULE_ENABLED
#include "stm32f3xx_hal_sdadc.h"
#endif /* HAL_SDADC_MODULE_ENABLED */
#ifdef HAL_SMARTCARD_MODULE_ENABLED
#include "stm32f3xx_hal_smartcard.h"
#endif /* HAL_SMARTCARD_MODULE_ENABLED */
#ifdef HAL_SMBUS_MODULE_ENABLED
#include "stm32f3xx_hal_smbus.h"
#endif /* HAL_SMBUS_MODULE_ENABLED */
#ifdef HAL_SPI_MODULE_ENABLED
#include "stm32f3xx_hal_spi.h"
#endif /* HAL_SPI_MODULE_ENABLED */
#ifdef HAL_TIM_MODULE_ENABLED
#include "stm32f3xx_hal_tim.h"
#endif /* HAL_TIM_MODULE_ENABLED */
#ifdef HAL_TSC_MODULE_ENABLED
#include "stm32f3xx_hal_tsc.h"
#endif /* HAL_TSC_MODULE_ENABLED */
#ifdef HAL_UART_MODULE_ENABLED
#include "stm32f3xx_hal_uart.h"
#endif /* HAL_UART_MODULE_ENABLED */
#ifdef HAL_USART_MODULE_ENABLED
#include "stm32f3xx_hal_usart.h"
#endif /* HAL_USART_MODULE_ENABLED */
#ifdef HAL_WWDG_MODULE_ENABLED
#include "stm32f3xx_hal_wwdg.h"
#endif /* HAL_WWDG_MODULE_ENABLED */
/* Exported macro ------------------------------------------------------------*/
#ifdef USE_FULL_ASSERT
/**
* @brief The assert_param macro is used for function's parameters check.
* @param expr If expr is false, it calls assert_failed function
* which reports the name of the source file and the source
* line number of the call that failed.
* If expr is true, it returns no value.
* @retval None
*/
#define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__))
/* Exported functions ------------------------------------------------------- */
void assert_failed(uint8_t* file, uint32_t line);
#else
#define assert_param(expr) ((void)0U)
#endif /* USE_FULL_ASSERT */
#ifdef __cplusplus
}
#endif
#endif /* __STM32F3xx_HAL_CONF_H */

66
Core/Inc/stm32f3xx_it.h Normal file
View File

@ -0,0 +1,66 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32f3xx_it.h
* @brief This file contains the headers of the interrupt handlers.
******************************************************************************
* @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 */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F3xx_IT_H
#define __STM32F3xx_IT_H
#ifdef __cplusplus
extern "C" {
#endif
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
/* USER CODE END ET */
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
/* USER CODE END EC */
/* Exported macro ------------------------------------------------------------*/
/* USER CODE BEGIN EM */
/* USER CODE END EM */
/* Exported functions prototypes ---------------------------------------------*/
void NMI_Handler(void);
void HardFault_Handler(void);
void MemManage_Handler(void);
void BusFault_Handler(void);
void UsageFault_Handler(void);
void SVC_Handler(void);
void DebugMon_Handler(void);
void PendSV_Handler(void);
void SysTick_Handler(void);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */
#ifdef __cplusplus
}
#endif
#endif /* __STM32F3xx_IT_H */

View File

@ -0,0 +1,246 @@
/*
* ADBMS_Abstraction.c
*
* Created on: 14.07.2022
* Author: max
*/
#include "ADBMS_Abstraction.h"
#include "ADBMS_CMD_MAKROS.h"
#include "ADBMS_LL_Driver.h"
#include <stddef.h>
uint8 numberofcells;
uint8 numberofauxchannels;
#define CHECK_RETURN(x) \
{ \
uint8 status = x; \
if (status != 0) \
return status; \
}
uint8 amsReset() {
amsWakeUp();
readCMD(SRST, NULL, 0);
mcuDelay(10);
amsWakeUp();
amsStopBalancing();
amsConfigOverUnderVoltage(DEFAULT_OV, DEFAULT_UV);
uint8 buffer[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
CHECK_RETURN(writeCMD(CLRFLAG, buffer, 6)); //clear flags,
CHECK_RETURN(writeCMD(CLOVUV, buffer, 6)); //OVUV flags
CHECK_RETURN(writeCMD(ADCV | ADCV_CONT | ADCV_RD, NULL, 0)); //start continuous cell voltage measurement with redundancy
CHECK_RETURN(writeCMD(ADAX | ADAX_CONV_ALL, NULL, 0)); //start aux measurement
return 0;
}
uint8 initAMS(SPI_HandleTypeDef* hspi, uint8 numofcells, uint8 numofaux) {
adbmsDriverInit(hspi);
numberofcells = numofcells;
numberofauxchannels = numofaux;
return amsReset();
}
uint8 amsWakeUp() {
uint8 buf[6];
return readCMD(RDCFGA, buf, 6);
}
uint8 amsCellMeasurement(Cell_Module* module) {
#warning check conversion counter to ensure that continous conversion has not been stopped
#warning check for OW conditions: ADSV | ADSV_OW_0 / ADSV_OW_1
return amsReadCellVoltages(module);
}
uint8 amsConfigCellMeasurement(uint8 numberofChannels) {
numberofcells = numberofChannels;
return 0;
}
uint8 amsAuxAndStatusMeasurement(Cell_Module* module) {
uint8 rxbuf[AUX_GROUP_A_SIZE] = {};
CHECK_RETURN(readCMD(RDSTATC, rxbuf, STATUS_GROUP_C_SIZE));
module->status.CS_FLT = rxbuf[0] | (rxbuf[1] << 8);
module->status.CCTS = rxbuf[2] | (rxbuf[3] << 8);
module->status.VA_OV = (rxbuf[4] >> 7) & 0x01;
module->status.VA_UV = (rxbuf[4] >> 6) & 0x01;
module->status.VD_OV = (rxbuf[4] >> 5) & 0x01;
module->status.VD_UV = (rxbuf[4] >> 4) & 0x01;
module->status.CED = (rxbuf[4] >> 3) & 0x01;
module->status.CMED = (rxbuf[4] >> 2) & 0x01;
module->status.SED = (rxbuf[4] >> 1) & 0x01;
module->status.SMED = (rxbuf[4] >> 0) & 0x01;
module->status.VDEL = (rxbuf[5] >> 7) & 0x01;
module->status.VDE = (rxbuf[5] >> 6) & 0x01;
module->status.COMPARE= (rxbuf[5] >> 5) & 0x01;
module->status.SPIFLT = (rxbuf[5] >> 4) & 0x01;
module->status.SLEEP = (rxbuf[5] >> 3) & 0x01;
module->status.THSD = (rxbuf[5] >> 2) & 0x01;
module->status.TMODCHK= (rxbuf[5] >> 1) & 0x01;
module->status.OSCCHK = (rxbuf[5] >> 0) & 0x01;
if (pollCMD(PLAUX) == 0x0) { //TODO: check for SPI fault
return 0; // aux ADC data not ready
}
CHECK_RETURN(readCMD(RDAUXA, rxbuf, AUX_GROUP_A_SIZE));
module->auxVoltages[0] = mV_from_ADBMS6830(rxbuf[0] | (rxbuf[1] << 8));
module->auxVoltages[1] = mV_from_ADBMS6830(rxbuf[2] | (rxbuf[3] << 8));
module->auxVoltages[2] = mV_from_ADBMS6830(rxbuf[4] | (rxbuf[5] << 8));
CHECK_RETURN(readCMD(RDAUXB, rxbuf, AUX_GROUP_A_SIZE));
module->auxVoltages[3] = mV_from_ADBMS6830(rxbuf[0] | (rxbuf[1] << 8));
module->auxVoltages[4] = mV_from_ADBMS6830(rxbuf[2] | (rxbuf[3] << 8));
module->auxVoltages[5] = mV_from_ADBMS6830(rxbuf[4] | (rxbuf[5] << 8));
CHECK_RETURN(readCMD(RDAUXC, rxbuf, AUX_GROUP_A_SIZE));
module->auxVoltages[6] = mV_from_ADBMS6830(rxbuf[0] | (rxbuf[1] << 8));
module->auxVoltages[7] = mV_from_ADBMS6830(rxbuf[2] | (rxbuf[3] << 8));
module->auxVoltages[8] = mV_from_ADBMS6830(rxbuf[4] | (rxbuf[5] << 8));
CHECK_RETURN(readCMD(RDAUXD, rxbuf, AUX_GROUP_A_SIZE));
module->auxVoltages[9] = mV_from_ADBMS6830(rxbuf[0] | (rxbuf[1] << 8));
uint8 rxbuffer[STATUS_GROUP_A_SIZE];
CHECK_RETURN(readCMD(RDSTATA, rxbuffer, STATUS_GROUP_A_SIZE));
module->internalDieTemp = rxbuffer[2] | (rxbuffer[3] << 8);
CHECK_RETURN(readCMD(RDSTATB, rxbuffer, STATUS_GROUP_B_SIZE));
module->digitalSupplyVoltage = mV_from_ADBMS6830(rxbuffer[0] | (rxbuffer[1] << 8));
module->analogSupplyVoltage = mV_from_ADBMS6830(rxbuffer[2] | (rxbuffer[3] << 8));
module->refVoltage = mV_from_ADBMS6830(rxbuffer[4] | (rxbuffer[5] << 8));
CHECK_RETURN(writeCMD(ADAX | ADAX_CONV_ALL, NULL, 0)); //start aux measurement for next cycle
return 0;
}
uint8 amsConfigBalancing(uint32 channels, uint8 dutyCycle) {
uint8 buffer_a[PWM_GROUP_A_SIZE] = {};
uint8 buffer_b[PWM_GROUP_B_SIZE] = {};
CHECK_RETURN(readCMD(RDPWMA, buffer_a, CFG_GROUP_A_SIZE));
CHECK_RETURN(readCMD(RDPWMB, buffer_b, CFG_GROUP_B_SIZE));
if (dutyCycle > 0x0F) { // there are only 4 bits for duty cycle
return 1;
}
#warning fixme
for (size_t i = 0; i < 16; i += 2) {
if (i < 12) { // cells 0, 1 are in regbuffer[0], cells 2, 3 in regbuffer[1], ...
buffer_a[i / 2] = ((channels & (1 << (i + 1))) ? (dutyCycle << 4) : 0) |
((channels & (1 << i)) ? dutyCycle : 0);
} else {
buffer_b[(i - 12) / 2] = ((channels & (1 << (i + 1))) ? (dutyCycle << 4) : 0) |
((channels & (1 << i)) ? dutyCycle : 0);
}
}
CHECK_RETURN(writeCMD(WRPWMA, buffer_a, CFG_GROUP_A_SIZE));
CHECK_RETURN(writeCMD(WRPWMB, buffer_b, CFG_GROUP_B_SIZE));
return 0;
}
uint8 amsStartBalancing(uint8 dutyCycle) { return writeCMD(UNMUTE, NULL, 0); }
uint8 amsStopBalancing() { return writeCMD(MUTE, NULL, 0); }
uint8 amsSelfTest() { return 0; }
uint8 amsConfigOverUnderVoltage(uint16 overVoltage, uint16 underVoltage) {
uint8 buffer[CFG_GROUP_A_SIZE];
if (underVoltage & 0xF000 || overVoltage & 0xF000) { // only 12 bits allowed
return 1;
}
CHECK_RETURN(readCMD(RDCFGB, buffer, CFG_GROUP_A_SIZE));
//UV
buffer[0] = (uint8) (underVoltage & 0xFF);
buffer[1] &= 0xF0;
buffer[1] |= (uint8) ((underVoltage >> 8) & 0x0F);
//OV
buffer[1] &= 0x0F;
buffer[1] |= (uint8) (overVoltage << 4);
buffer[2] = (uint8) (overVoltage >> 4);
return writeCMD(WRCFGB, buffer, CFG_GROUP_A_SIZE);
}
uint8 amsCheckUnderOverVoltage(Cell_Module* module) {
uint8 regbuffer[STATUS_GROUP_D_SIZE];
uint32 ov_uv_data = 0;
CHECK_RETURN(readCMD(RDSTATD, regbuffer, STATUS_GROUP_D_SIZE));
ov_uv_data = (regbuffer[0] << 0) | (regbuffer[1] << 8) |
(regbuffer[2] << 16) | (regbuffer[3] << 24);
module->overVoltage = 0;
module->underVoltage = 0;
for (size_t i = 0; i < numberofcells; i++) { // ov/uv flags are 1-bit flags for each cell C0UV, C0OV, C1UV, C1OV, ...
module->underVoltage |= (ov_uv_data >> (i * 2)) & 0x01;
module->overVoltage |= (ov_uv_data >> (i * 2 + 1)) & 0x01;
}
return 0;
}
uint8 amsClearAux() {
uint8 buffer[6];
return writeCMD(CLRAUX, buffer, 0);
}
uint8 amsClearCells() {
uint8 buffer[6];
return writeCMD(CLRCELL, buffer, 0);
}
uint8 amsReadCellVoltages(Cell_Module* module) {
uint8 rxbuffer[CV_GROUP_A_SIZE];
CHECK_RETURN(readCMD(RDCVA, rxbuffer, CV_GROUP_A_SIZE));
module->cellVoltages[0] = mV_from_ADBMS6830(rxbuffer[0] | (rxbuffer[1] << 8));
module->cellVoltages[1] = mV_from_ADBMS6830(rxbuffer[2] | (rxbuffer[3] << 8));
module->cellVoltages[2] = mV_from_ADBMS6830(rxbuffer[4] | (rxbuffer[5] << 8));
CHECK_RETURN(readCMD(RDCVB, rxbuffer, CV_GROUP_A_SIZE));
module->cellVoltages[3] = mV_from_ADBMS6830(rxbuffer[0] | (rxbuffer[1] << 8));
module->cellVoltages[4] = mV_from_ADBMS6830(rxbuffer[2] | (rxbuffer[3] << 8));
module->cellVoltages[5] = mV_from_ADBMS6830(rxbuffer[4] | (rxbuffer[5] << 8));
CHECK_RETURN(readCMD(RDCVC, rxbuffer, CV_GROUP_A_SIZE));
module->cellVoltages[6] = mV_from_ADBMS6830(rxbuffer[0] | (rxbuffer[1] << 8));
module->cellVoltages[7] = mV_from_ADBMS6830(rxbuffer[2] | (rxbuffer[3] << 8));
module->cellVoltages[8] = mV_from_ADBMS6830(rxbuffer[4] | (rxbuffer[5] << 8));
CHECK_RETURN(readCMD(RDCVD, rxbuffer, CV_GROUP_A_SIZE));
module->cellVoltages[9] = mV_from_ADBMS6830(rxbuffer[0] | (rxbuffer[1] << 8));
module->cellVoltages[10] = mV_from_ADBMS6830(rxbuffer[2] | (rxbuffer[3] << 8));
module->cellVoltages[11] = mV_from_ADBMS6830(rxbuffer[4] | (rxbuffer[5] << 8));
CHECK_RETURN(readCMD(RDCVE, rxbuffer, CV_GROUP_A_SIZE));
module->cellVoltages[12] = mV_from_ADBMS6830(rxbuffer[0] | (rxbuffer[1] << 8));
module->cellVoltages[13] = mV_from_ADBMS6830(rxbuffer[2] | (rxbuffer[3] << 8));
module->cellVoltages[14] = mV_from_ADBMS6830(rxbuffer[4] | (rxbuffer[5] << 8));
CHECK_RETURN(readCMD(RDCVF, rxbuffer, CV_GROUP_A_SIZE));
module->cellVoltages[15] = mV_from_ADBMS6830(rxbuffer[0] | (rxbuffer[1] << 8));
return 0;
}

347
Core/Src/ADBMS_LL_Driver.c Normal file
View File

@ -0,0 +1,347 @@
/*
* ADBMS_LL_Driver.c
*
* Created on: 05.06.2022
* Author: max
*/
#include "ADBMS_LL_Driver.h"
#include <stdbool.h>
#define INITIAL_COMMAND_PEC 0x0010
#define INITIAL_DATA_PEC 0x0010
#define ADBMS_SPI_TIMEOUT 100 // Timeout in ms
#warning ask about the timeout value
SPI_HandleTypeDef* adbmsspi;
uint8 adbmsDriverInit(SPI_HandleTypeDef* hspi) {
mcuAdbmsCSLow();
HAL_Delay(1);
mcuAdbmsCSHigh();
adbmsspi = hspi;
return 0;
}
//command PEC calculation
//CRC-15
//x^15 + x^14 + x^10 + x^8 + x^7 + x^4 + x^3 + 1
uint8 calculateCommandPEC(uint8_t* data, uint8_t datalen) {
uint16 currentpec = INITIAL_COMMAND_PEC;
if (datalen >= 3) {
for (int i = 0; i < (datalen - 2); i++) {
for (int n = 0; n < 8; n++) {
uint8 din = data[i] << (n);
currentpec = updateCommandPEC(currentpec, din);
}
}
data[datalen - 2] = (currentpec >> 7) & 0xFF;
data[datalen - 1] = (currentpec << 1) & 0xFF;
return 0;
} else {
return 1;
}
}
uint8 checkCommandPEC(uint8* data, uint8 datalen) {
if (datalen <= 3) {
return 255;
}
uint16 currentpec = INITIAL_COMMAND_PEC;
for (int i = 0; i < (datalen - 2); i++) {
for (int n = 0; n < 8; n++) {
uint8 din = data[i] << (n);
currentpec = updateCommandPEC(currentpec, din);
}
}
uint8 pechigh = (currentpec >> 7) & 0xFF;
uint8 peclow = (currentpec << 1) & 0xFF;
if ((pechigh == data[datalen - 2]) && (peclow == data[datalen - 1])) {
return 0;
}
return 1;
}
uint16 updateCommandPEC(uint16 currentPEC, uint8 din) {
din = (din >> 7) & 0x01;
uint8 in0 = din ^ ((currentPEC >> 14) & 0x01);
uint8 in3 = in0 ^ ((currentPEC >> 2) & 0x01);
uint8 in4 = in0 ^ ((currentPEC >> 3) & 0x01);
uint8 in7 = in0 ^ ((currentPEC >> 6) & 0x01);
uint8 in8 = in0 ^ ((currentPEC >> 7) & 0x01);
uint8 in10 = in0 ^ ((currentPEC >> 9) & 0x01);
uint8 in14 = in0 ^ ((currentPEC >> 13) & 0x01);
uint16 newPEC = 0;
newPEC |= in14 << 14;
newPEC |= (currentPEC & (0x01 << 12)) << 1;
newPEC |= (currentPEC & (0x01 << 11)) << 1;
newPEC |= (currentPEC & (0x01 << 10)) << 1;
newPEC |= in10 << 10;
newPEC |= (currentPEC & (0x01 << 8)) << 1;
newPEC |= in8 << 8;
newPEC |= in7 << 7;
newPEC |= (currentPEC & (0x01 << 5)) << 1;
newPEC |= (currentPEC & (0x01 << 4)) << 1;
newPEC |= in4 << 4;
newPEC |= in3 << 3;
newPEC |= (currentPEC & (0x01 << 1)) << 1;
newPEC |= (currentPEC & (0x01)) << 1;
newPEC |= in0;
return newPEC;
}
//data PEC calculation
//CRC-10
//x^10 + x^7 + x^3 + x^2 + x + 1
uint16_t pec10_calc(bool rx_cmd, int len, uint8_t* data) {
uint16_t remainder = 16; /* PEC_SEED; 0000010000 */
uint16_t polynom = 0x8F; /* x10 + x7 + x3 + x2 + x + 1 <- the CRC15 polynomial
100 1000 1111 48F */
/* Perform modulo-2 division, a byte at a time. */
for (uint8_t pbyte = 0; pbyte < len; ++pbyte) {
/* Bring the next byte into the remainder. */
remainder ^= (uint16_t)(data[pbyte] << 2);
/* Perform modulo-2 division, a bit at a time.*/
for (uint8_t bit_ = 8; bit_ > 0; --bit_) {
/* Try to divide the current data bit. */
if ((remainder & 0x200) >
0) // equivalent to remainder & 2^14 simply check for MSB
{
remainder = (uint16_t)((remainder << 1));
remainder = (uint16_t)(remainder ^ polynom);
} else {
remainder = (uint16_t)(remainder << 1);
}
}
}
if (rx_cmd == true) {
remainder ^= (uint16_t)((data[len] & 0xFC) << 2);
/* Perform modulo-2 division, a bit at a time */
for (uint8_t bit_ = 6; bit_ > 0; --bit_) {
/* Try to divide the current data bit */
if ((remainder & 0x200) >
0) // equivalent to remainder & 2^14 simply check for MSB
{
remainder = (uint16_t)((remainder << 1));
remainder = (uint16_t)(remainder ^ polynom);
} else {
remainder = (uint16_t)((remainder << 1));
}
}
}
return ((uint16_t)(remainder & 0x3FF));
}
typedef uint16_t crc;
crc F_CRC_CalculaCheckSum(uint8_t const AF_Datos[], uint16_t VF_nBytes);
uint8 calculateDataPEC(uint8_t* data, uint8_t datalen) {
if (datalen >= 3) {
crc currentpec = pec10_calc(true, datalen - 2, data) & 0x3FF; // mask to 10 bits
// memory layout is [[zeroes], PEC[9:8]], [PEC[7:0]]
data[datalen - 2] = (currentpec >> 8) & 0xFF;
data[datalen - 1] = currentpec & 0xFF;
volatile uint8 result = pec10_calc(true, datalen, data);
return 0;
} else {
return 1;
}
}
uint8 checkDataPEC(uint8* data, uint8 len) {
if (len <= 2) {
return 255;
}
crc currentpec = F_CRC_CalculaCheckSum(data, len);
return (currentpec == 0) ? 0 : 1;
}
static crc F_CRC_ObtenValorDeTabla(uint8_t VP_Pos_Tabla) {
crc VP_CRCTableValue = 0;
uint8_t VP_Pos_bit = 0;
VP_CRCTableValue = ((crc)(VP_Pos_Tabla)) << (10 - 8);
for (VP_Pos_bit = 0; VP_Pos_bit < 8; VP_Pos_bit++) {
if (VP_CRCTableValue & (((crc)1) << (10 - 1))) {
VP_CRCTableValue = (VP_CRCTableValue << 1) ^ 0x8F;
} else {
VP_CRCTableValue = (VP_CRCTableValue << 1);
}
}
return ((VP_CRCTableValue));
}
crc F_CRC_CalculaCheckSum(uint8_t const AF_Datos[], uint16_t VF_nBytes) {
crc VP_CRCTableValue = 16;
int16_t VP_bytes = 0;
for (VP_bytes = 0; VP_bytes < VF_nBytes; VP_bytes++) {
VP_CRCTableValue = (VP_CRCTableValue << 8) ^
F_CRC_ObtenValorDeTabla(
((uint8_t)((VP_CRCTableValue >> (10 - 8)) & 0xFF)) ^
AF_Datos[VP_bytes]);
}
if ((8 * sizeof(crc)) > 10) {
VP_CRCTableValue = VP_CRCTableValue & ((((crc)(1)) << 10) - 1);
}
return (VP_CRCTableValue ^ 0x0000);
}
uint16 updateDataPEC(uint16 currentPEC, uint8 din) {
din = (din >> 7) & 0x01;
uint8 in0 = din ^ ((currentPEC >> 9) & 0x01);
uint8 in2 = in0 ^ ((currentPEC >> 1) & 0x01);
uint8 in3 = in0 ^ ((currentPEC >> 2) & 0x01);
uint8 in7 = in0 ^ ((currentPEC >> 6) & 0x01);
uint16 newPEC = 0;
newPEC |= (currentPEC & (0x01 << 8)) << 1;
newPEC |= (currentPEC & (0x01 << 7)) << 1;
newPEC |= in7 << 7;
newPEC |= (currentPEC & (0x01 << 5)) << 1;
newPEC |= (currentPEC & (0x01 << 4)) << 1;
newPEC |= in3 << 3;
newPEC |= in2 << 2;
newPEC |= (currentPEC & (0x01)) << 1;
newPEC |= in0;
return newPEC;
}
uint8 writeCMD(uint16 command, uint8* args, uint8 arglen) {
uint8 ret;
if (arglen > 0) {
uint8 buffer[6 + arglen]; //command + PEC (2 bytes) + data + DPEC (2 bytes)
buffer[0] = (command >> 8) & 0xFF;
buffer[1] = (command) & 0xFF;
calculateCommandPEC(buffer, 4);
for (uint8 i = 0; i < arglen; i++) {
buffer[4 + i] = args[i];
}
calculateDataPEC(&buffer[4], arglen + 2); //DPEC is calculated over the data, not the command, and placed at the end of the data
mcuAdbmsCSLow();
ret = mcuSPITransmit(buffer, 6 + arglen);
mcuAdbmsCSHigh();
} else {
uint8 buffer[4];
buffer[0] = (command >> 8) & 0xFF;
buffer[1] = (command) & 0xFF;
calculateCommandPEC(buffer, 4);
mcuAdbmsCSLow();
ret = mcuSPITransmit(buffer, 4);
mcuAdbmsCSHigh();
}
return ret;
}
uint8 readCMD(uint16 command, uint8* buffer, uint8 buflen) {
uint8 txbuffer[6 + buflen];
uint8 rxbuffer[6 + buflen];
txbuffer[0] = (command >> 8) & 0xFF;
txbuffer[1] = (command)&0xFF;
calculateCommandPEC(txbuffer, 4);
mcuAdbmsCSLow();
uint8 status = mcuSPITransmitReceive(rxbuffer, txbuffer, 6 + buflen);
mcuAdbmsCSHigh();
if (status != 0) {
return status;
}
for (uint8 i = 0; i < buflen; i++) {
buffer[i] = rxbuffer[i + 4];
}
[[maybe_unused]] uint8 commandCounter = rxbuffer[sizeof(rxbuffer) - 2] & 0xFC; //command counter is bits 7-2
//TODO: check command counter?
return checkDataPEC(&rxbuffer[4], buflen + 2);
}
//check poll command - no data PEC sent back
uint8 pollCMD(uint16 command) {
uint8 txbuffer[5] = {};
uint8 rxbuffer[5] = {};
txbuffer[0] = (command >> 8) & 0xFF;
txbuffer[1] = (command)&0xFF;
calculateCommandPEC(txbuffer, 4);
mcuAdbmsCSLow();
uint8 status = mcuSPITransmitReceive(rxbuffer, txbuffer, 5);
mcuAdbmsCSHigh();
if (status != 0) {
return status;
}
return rxbuffer[4]; //last byte will be poll response
}
void mcuAdbmsCSLow() {
HAL_GPIO_WritePin(CSB_GPIO_Port, CSB_Pin, GPIO_PIN_RESET);
}
void mcuAdbmsCSHigh() {
HAL_GPIO_WritePin(CSB_GPIO_Port, CSB_Pin, GPIO_PIN_SET);
}
uint8 mcuSPITransmit(uint8* buffer, uint8 buffersize) {
HAL_StatusTypeDef status;
uint8 rxbuf[buffersize];
status = HAL_SPI_TransmitReceive(adbmsspi, buffer, rxbuf, buffersize,
ADBMS_SPI_TIMEOUT);
__HAL_SPI_CLEAR_OVRFLAG(adbmsspi);
return status;
}
uint8 mcuSPIReceive(uint8* buffer, uint8 buffersize) {
HAL_StatusTypeDef status;
status = HAL_SPI_Receive(adbmsspi, buffer, buffersize, ADBMS_SPI_TIMEOUT);
return status;
}
uint8 mcuSPITransmitReceive(uint8* rxbuffer, uint8* txbuffer,
uint8 buffersize) {
HAL_StatusTypeDef status;
status = HAL_SPI_TransmitReceive(adbmsspi, txbuffer, rxbuffer, buffersize,
ADBMS_SPI_TIMEOUT);
return status;
}
inline void mcuDelay(uint16 delay) { HAL_Delay(delay); }

69
Core/Src/AMS_HighLevel.c Normal file
View File

@ -0,0 +1,69 @@
/*
* AMS_HighLevel.c
*
* Created on: 20.07.2022
* Author: max
*/
#include "AMS_HighLevel.h"
#include "ADBMS_Abstraction.h"
#include "TMP1075.h"
#include "stm32f3xx_hal.h"
#include <stdint.h>
#include <string.h>
Cell_Module module = {};
uint16_t amsuv = 0;
uint16_t amsov = 0;
uint8_t numberofCells = 15;
uint8_t numberofAux = 0;
uint8_t packetChecksumFails = 0;
#define MAX_PACKET_CHECKSUM_FAILS 5
uint8_t deviceSleeps = 0;
#define MAX_DEVICE_SLEEP 3 //TODO: change to correct value
struct pollingTimes {
uint32_t S_ADC_OW_CHECK;
uint32_t TMP1075;
};
struct pollingTimes pollingTimes = {0, 0};
uint8_t AMS_Init(SPI_HandleTypeDef* hspi) {
uint8_t ret = initAMS(hspi, numberofCells, numberofAux);
amsov = DEFAULT_OV;
amsuv = DEFAULT_UV;
pollingTimes = (struct pollingTimes) {HAL_GetTick(), HAL_GetTick()};
return ret;
}
uint8_t AMS_Idle_Loop() {
if (!amsWakeUp()) {
//error_data.data_kind = SEK_INTERNAL_BMS_TIMEOUT; //we don't receive data for the wakeup command
//set_error_source(ERROR_SOURCE_INTERNAL); //so we can't tell if we timed out
}
packetChecksumFails += amsAuxAndStatusMeasurement(&module);
if (module.status.SLEEP) {
deviceSleeps++;
if (deviceSleeps > MAX_DEVICE_SLEEP) {
} else {
amsReset();
}
}
packetChecksumFails += amsCellMeasurement(&module);
packetChecksumFails += amsCheckUnderOverVoltage(&module);
//tmp1075_measure();
return 0;
}

55
Core/Src/TMP1075.c Normal file
View File

@ -0,0 +1,55 @@
#include "TMP1075.h"
#include <stdint.h>
#include <string.h>
#define MAX_TEMP ((int16_t)(59 / 0.0625f))
#define MIN_TEMP 0
#define MAX_FAILED_TEMP 12 //TODO: change value for compliance with the actual number of sensors
#warning "change value for compliance with the actual number of sensors"
int16_t tmp1075_temps[N_TEMP_SENSORS] = {0};
I2C_HandleTypeDef* hi2c;
HAL_StatusTypeDef tmp1075_init(I2C_HandleTypeDef* handle) {
hi2c = handle;
for (int i = 0; i < N_TEMP_SENSORS; i++) {
HAL_StatusTypeDef status = tmp1075_sensor_init(i);
if (status != HAL_OK) {
return status;
}
}
return HAL_OK;
}
HAL_StatusTypeDef tmp1075_measure() {
for (int i = 0; i < N_TEMP_SENSORS; i++) {
if (tmp1075_sensor_read(i, &tmp1075_temps[i]) != HAL_OK ||
(tmp1075_temps[i] & 0x000F) != 0) {
return HAL_ERROR;
}
return HAL_OK;
}
}
HAL_StatusTypeDef tmp1075_sensor_init(int n) {
uint16_t addr = (0b1000000 | n) << 1;
uint8_t data[] = {0};
return HAL_I2C_Master_Transmit(hi2c, addr, data, sizeof(data), 100);
}
HAL_StatusTypeDef tmp1075_sensor_read(int n, int16_t* res) {
uint16_t addr = (0b1000000 | n) << 1;
addr |= 1; // Read
uint8_t result[2];
HAL_StatusTypeDef status =
HAL_I2C_Master_Receive(hi2c, addr, result, sizeof(result), 5); //5ms timeout for failure (cascading faliure max = 30 * 5 = 150ms)
if (status == HAL_OK) {
*res = (result[0] << 8) | result[1];
}
return status;
}

266
Core/Src/main.c Normal file
View File

@ -0,0 +1,266 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @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 "AMS_HighLevel.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* 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 ---------------------------------------------------------*/
SPI_HandleTypeDef hspi2;
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI2_Init(void);
/* USER CODE BEGIN PFP */
/* 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_SPI2_Init();
AMS_Init(&hspi2);
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
AMS_Idle_Loop();
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL16;
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_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief SPI2 Initialization Function
* @param None
* @retval None
*/
static void MX_SPI2_Init(void)
{
/* USER CODE BEGIN SPI2_Init 0 */
/* USER CODE END SPI2_Init 0 */
/* USER CODE BEGIN SPI2_Init 1 */
/* USER CODE END SPI2_Init 1 */
/* SPI2 parameter configuration*/
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_MASTER;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_4BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi2.Init.CRCPolynomial = 7;
hspi2.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi2.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
if (HAL_SPI_Init(&hspi2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI2_Init 2 */
/* USER CODE END SPI2_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_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(CSB_GPIO_Port, CSB_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin : B1_Pin */
GPIO_InitStruct.Pin = B1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(B1_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pins : USART_TX_Pin USART_RX_Pin */
GPIO_InitStruct.Pin = USART_TX_Pin|USART_RX_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pin : CSB_Pin */
GPIO_InitStruct.Pin = CSB_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(CSB_GPIO_Port, &GPIO_InitStruct);
/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}
/* USER CODE BEGIN 4 */
/* 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 */

View File

@ -0,0 +1,151 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32f3xx_hal_msp.c
* @brief This file provides code for the MSP Initialization
* and de-Initialization codes.
******************************************************************************
* @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"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN TD */
/* USER CODE END TD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN Define */
/* USER CODE END Define */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN Macro */
/* USER CODE END Macro */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* External functions --------------------------------------------------------*/
/* USER CODE BEGIN ExternalFunctions */
/* USER CODE END ExternalFunctions */
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* Initializes the Global MSP.
*/
void HAL_MspInit(void)
{
/* USER CODE BEGIN MspInit 0 */
/* USER CODE END MspInit 0 */
__HAL_RCC_SYSCFG_CLK_ENABLE();
__HAL_RCC_PWR_CLK_ENABLE();
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_0);
/* System interrupt init*/
/* USER CODE BEGIN MspInit 1 */
/* USER CODE END MspInit 1 */
}
/**
* @brief SPI MSP Initialization
* This function configures the hardware resources used in this example
* @param hspi: SPI handle pointer
* @retval None
*/
void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(hspi->Instance==SPI2)
{
/* USER CODE BEGIN SPI2_MspInit 0 */
/* USER CODE END SPI2_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_SPI2_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**SPI2 GPIO Configuration
PB13 ------> SPI2_SCK
PB14 ------> SPI2_MISO
PB15 ------> SPI2_MOSI
*/
GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USER CODE BEGIN SPI2_MspInit 1 */
/* USER CODE END SPI2_MspInit 1 */
}
}
/**
* @brief SPI MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param hspi: SPI handle pointer
* @retval None
*/
void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi)
{
if(hspi->Instance==SPI2)
{
/* USER CODE BEGIN SPI2_MspDeInit 0 */
/* USER CODE END SPI2_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_SPI2_CLK_DISABLE();
/**SPI2 GPIO Configuration
PB13 ------> SPI2_SCK
PB14 ------> SPI2_MISO
PB15 ------> SPI2_MOSI
*/
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15);
/* USER CODE BEGIN SPI2_MspDeInit 1 */
/* USER CODE END SPI2_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */

203
Core/Src/stm32f3xx_it.c Normal file
View File

@ -0,0 +1,203 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32f3xx_it.c
* @brief Interrupt Service Routines.
******************************************************************************
* @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 "stm32f3xx_it.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN TD */
/* USER CODE END TD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/* External variables --------------------------------------------------------*/
/* USER CODE BEGIN EV */
/* USER CODE END EV */
/******************************************************************************/
/* Cortex-M4 Processor Interruption and Exception Handlers */
/******************************************************************************/
/**
* @brief This function handles Non maskable interrupt.
*/
void NMI_Handler(void)
{
/* USER CODE BEGIN NonMaskableInt_IRQn 0 */
/* USER CODE END NonMaskableInt_IRQn 0 */
/* USER CODE BEGIN NonMaskableInt_IRQn 1 */
while (1)
{
}
/* USER CODE END NonMaskableInt_IRQn 1 */
}
/**
* @brief This function handles Hard fault interrupt.
*/
void HardFault_Handler(void)
{
/* USER CODE BEGIN HardFault_IRQn 0 */
/* USER CODE END HardFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_HardFault_IRQn 0 */
/* USER CODE END W1_HardFault_IRQn 0 */
}
}
/**
* @brief This function handles Memory management fault.
*/
void MemManage_Handler(void)
{
/* USER CODE BEGIN MemoryManagement_IRQn 0 */
/* USER CODE END MemoryManagement_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
/* USER CODE END W1_MemoryManagement_IRQn 0 */
}
}
/**
* @brief This function handles Pre-fetch fault, memory access fault.
*/
void BusFault_Handler(void)
{
/* USER CODE BEGIN BusFault_IRQn 0 */
/* USER CODE END BusFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_BusFault_IRQn 0 */
/* USER CODE END W1_BusFault_IRQn 0 */
}
}
/**
* @brief This function handles Undefined instruction or illegal state.
*/
void UsageFault_Handler(void)
{
/* USER CODE BEGIN UsageFault_IRQn 0 */
/* USER CODE END UsageFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_UsageFault_IRQn 0 */
/* USER CODE END W1_UsageFault_IRQn 0 */
}
}
/**
* @brief This function handles System service call via SWI instruction.
*/
void SVC_Handler(void)
{
/* USER CODE BEGIN SVCall_IRQn 0 */
/* USER CODE END SVCall_IRQn 0 */
/* USER CODE BEGIN SVCall_IRQn 1 */
/* USER CODE END SVCall_IRQn 1 */
}
/**
* @brief This function handles Debug monitor.
*/
void DebugMon_Handler(void)
{
/* USER CODE BEGIN DebugMonitor_IRQn 0 */
/* USER CODE END DebugMonitor_IRQn 0 */
/* USER CODE BEGIN DebugMonitor_IRQn 1 */
/* USER CODE END DebugMonitor_IRQn 1 */
}
/**
* @brief This function handles Pendable request for system service.
*/
void PendSV_Handler(void)
{
/* USER CODE BEGIN PendSV_IRQn 0 */
/* USER CODE END PendSV_IRQn 0 */
/* USER CODE BEGIN PendSV_IRQn 1 */
/* USER CODE END PendSV_IRQn 1 */
}
/**
* @brief This function handles System tick timer.
*/
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick();
/* USER CODE BEGIN SysTick_IRQn 1 */
/* USER CODE END SysTick_IRQn 1 */
}
/******************************************************************************/
/* STM32F3xx Peripheral Interrupt Handlers */
/* Add here the Interrupt Handlers for the used peripherals. */
/* For the available peripheral interrupt handler names, */
/* please refer to the startup file (startup_stm32f3xx.s). */
/******************************************************************************/
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */

176
Core/Src/syscalls.c Normal file
View File

@ -0,0 +1,176 @@
/**
******************************************************************************
* @file syscalls.c
* @author Auto-generated by STM32CubeMX
* @brief Minimal System calls file
*
* For more information about which c-functions
* need which of these lowlevel functions
* please consult the Newlib libc-manual
******************************************************************************
* @attention
*
* Copyright (c) 2020-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.
*
******************************************************************************
*/
/* Includes */
#include <sys/stat.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <sys/times.h>
/* Variables */
extern int __io_putchar(int ch) __attribute__((weak));
extern int __io_getchar(void) __attribute__((weak));
char *__env[1] = { 0 };
char **environ = __env;
/* Functions */
void initialise_monitor_handles()
{
}
int _getpid(void)
{
return 1;
}
int _kill(int pid, int sig)
{
(void)pid;
(void)sig;
errno = EINVAL;
return -1;
}
void _exit (int status)
{
_kill(status, -1);
while (1) {} /* Make sure we hang here */
}
__attribute__((weak)) int _read(int file, char *ptr, int len)
{
(void)file;
int DataIdx;
for (DataIdx = 0; DataIdx < len; DataIdx++)
{
*ptr++ = __io_getchar();
}
return len;
}
__attribute__((weak)) int _write(int file, char *ptr, int len)
{
(void)file;
int DataIdx;
for (DataIdx = 0; DataIdx < len; DataIdx++)
{
__io_putchar(*ptr++);
}
return len;
}
int _close(int file)
{
(void)file;
return -1;
}
int _fstat(int file, struct stat *st)
{
(void)file;
st->st_mode = S_IFCHR;
return 0;
}
int _isatty(int file)
{
(void)file;
return 1;
}
int _lseek(int file, int ptr, int dir)
{
(void)file;
(void)ptr;
(void)dir;
return 0;
}
int _open(char *path, int flags, ...)
{
(void)path;
(void)flags;
/* Pretend like we always fail */
return -1;
}
int _wait(int *status)
{
(void)status;
errno = ECHILD;
return -1;
}
int _unlink(char *name)
{
(void)name;
errno = ENOENT;
return -1;
}
int _times(struct tms *buf)
{
(void)buf;
return -1;
}
int _stat(char *file, struct stat *st)
{
(void)file;
st->st_mode = S_IFCHR;
return 0;
}
int _link(char *old, char *new)
{
(void)old;
(void)new;
errno = EMLINK;
return -1;
}
int _fork(void)
{
errno = EAGAIN;
return -1;
}
int _execve(char *name, char **argv, char **env)
{
(void)name;
(void)argv;
(void)env;
errno = ENOMEM;
return -1;
}

79
Core/Src/sysmem.c Normal file
View File

@ -0,0 +1,79 @@
/**
******************************************************************************
* @file sysmem.c
* @author Generated by STM32CubeMX
* @brief System Memory calls file
*
* For more information about which C functions
* need which of these lowlevel functions
* please consult the newlib libc manual
******************************************************************************
* @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.
*
******************************************************************************
*/
/* Includes */
#include <errno.h>
#include <stdint.h>
/**
* Pointer to the current high watermark of the heap usage
*/
static uint8_t *__sbrk_heap_end = NULL;
/**
* @brief _sbrk() allocates memory to the newlib heap and is used by malloc
* and others from the C library
*
* @verbatim
* ############################################################################
* # .data # .bss # newlib heap # MSP stack #
* # # # # Reserved by _Min_Stack_Size #
* ############################################################################
* ^-- RAM start ^-- _end _estack, RAM end --^
* @endverbatim
*
* This implementation starts allocating at the '_end' linker symbol
* The '_Min_Stack_Size' linker symbol reserves a memory for the MSP stack
* The implementation considers '_estack' linker symbol to be RAM end
* NOTE: If the MSP stack, at any point during execution, grows larger than the
* reserved size, please increase the '_Min_Stack_Size'.
*
* @param incr Memory size
* @return Pointer to allocated memory
*/
void *_sbrk(ptrdiff_t incr)
{
extern uint8_t _end; /* Symbol defined in the linker script */
extern uint8_t _estack; /* Symbol defined in the linker script */
extern uint32_t _Min_Stack_Size; /* Symbol defined in the linker script */
const uint32_t stack_limit = (uint32_t)&_estack - (uint32_t)&_Min_Stack_Size;
const uint8_t *max_heap = (uint8_t *)stack_limit;
uint8_t *prev_heap_end;
/* Initialize heap end at first call */
if (NULL == __sbrk_heap_end)
{
__sbrk_heap_end = &_end;
}
/* Protect heap from growing into the reserved MSP stack */
if (__sbrk_heap_end + incr > max_heap)
{
errno = ENOMEM;
return (void *)-1;
}
prev_heap_end = __sbrk_heap_end;
__sbrk_heap_end += incr;
return (void *)prev_heap_end;
}

287
Core/Src/system_stm32f3xx.c Normal file
View File

@ -0,0 +1,287 @@
/**
******************************************************************************
* @file system_stm32f3xx.c
* @author MCD Application Team
* @brief CMSIS Cortex-M4 Device Peripheral Access Layer System Source File.
*
* 1. This file provides two functions and one global variable to be called from
* user application:
* - SystemInit(): This function is called at startup just after reset and
* before branch to main program. This call is made inside
* the "startup_stm32f3xx.s" file.
*
* - SystemCoreClock variable: Contains the core clock (HCLK), it can be used
* by the user application to setup the SysTick
* timer or configure other parameters.
*
* - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
* be called whenever the core clock is changed
* during program execution.
*
* 2. After each device reset the HSI (8 MHz) is used as system clock source.
* Then SystemInit() function is called, in "startup_stm32f3xx.s" file, to
* configure the system clock before to branch to main program.
*
* 3. This file configures the system clock as follows:
*=============================================================================
* Supported STM32F3xx device
*-----------------------------------------------------------------------------
* System Clock source | HSI
*-----------------------------------------------------------------------------
* SYSCLK(Hz) | 8000000
*-----------------------------------------------------------------------------
* HCLK(Hz) | 8000000
*-----------------------------------------------------------------------------
* AHB Prescaler | 1
*-----------------------------------------------------------------------------
* APB2 Prescaler | 1
*-----------------------------------------------------------------------------
* APB1 Prescaler | 1
*-----------------------------------------------------------------------------
* USB Clock | DISABLE
*-----------------------------------------------------------------------------
*=============================================================================
******************************************************************************
* @attention
*
* Copyright (c) 2016 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.
*
******************************************************************************
*/
/** @addtogroup CMSIS
* @{
*/
/** @addtogroup stm32f3xx_system
* @{
*/
/** @addtogroup STM32F3xx_System_Private_Includes
* @{
*/
#include "stm32f3xx.h"
/**
* @}
*/
/** @addtogroup STM32F3xx_System_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @addtogroup STM32F3xx_System_Private_Defines
* @{
*/
#if !defined (HSE_VALUE)
#define HSE_VALUE ((uint32_t)8000000) /*!< Default value of the External oscillator in Hz.
This value can be provided and adapted by the user application. */
#endif /* HSE_VALUE */
#if !defined (HSI_VALUE)
#define HSI_VALUE ((uint32_t)8000000) /*!< Default value of the Internal oscillator in Hz.
This value can be provided and adapted by the user application. */
#endif /* HSI_VALUE */
/* Note: Following vector table addresses must be defined in line with linker
configuration. */
/*!< Uncomment the following line if you need to relocate the vector table
anywhere in Flash or Sram, else the vector table is kept at the automatic
remap of boot address selected */
/* #define USER_VECT_TAB_ADDRESS */
#if defined(USER_VECT_TAB_ADDRESS)
/*!< Uncomment the following line if you need to relocate your vector Table
in Sram else user remap will be done in Flash. */
/* #define VECT_TAB_SRAM */
#if defined(VECT_TAB_SRAM)
#define VECT_TAB_BASE_ADDRESS SRAM_BASE /*!< Vector Table base address field.
This value must be a multiple of 0x200. */
#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.
This value must be a multiple of 0x200. */
#else
#define VECT_TAB_BASE_ADDRESS FLASH_BASE /*!< Vector Table base address field.
This value must be a multiple of 0x200. */
#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.
This value must be a multiple of 0x200. */
#endif /* VECT_TAB_SRAM */
#endif /* USER_VECT_TAB_ADDRESS */
/******************************************************************************/
/**
* @}
*/
/** @addtogroup STM32F3xx_System_Private_Macros
* @{
*/
/**
* @}
*/
/** @addtogroup STM32F3xx_System_Private_Variables
* @{
*/
/* This variable is updated in three ways:
1) by calling CMSIS function SystemCoreClockUpdate()
2) by calling HAL API function HAL_RCC_GetHCLKFreq()
3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
Note: If you use this function to configure the system clock there is no need to
call the 2 first functions listed above, since SystemCoreClock variable is
updated automatically.
*/
uint32_t SystemCoreClock = 8000000;
const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4};
/**
* @}
*/
/** @addtogroup STM32F3xx_System_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @addtogroup STM32F3xx_System_Private_Functions
* @{
*/
/**
* @brief Setup the microcontroller system
* @param None
* @retval None
*/
void SystemInit(void)
{
/* FPU settings --------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
#endif
/* Configure the Vector Table location -------------------------------------*/
#if defined(USER_VECT_TAB_ADDRESS)
SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
#endif /* USER_VECT_TAB_ADDRESS */
}
/**
* @brief Update SystemCoreClock variable according to Clock Register Values.
* The SystemCoreClock variable contains the core clock (HCLK), it can
* be used by the user application to setup the SysTick timer or configure
* other parameters.
*
* @note Each time the core clock (HCLK) changes, this function must be called
* to update SystemCoreClock variable value. Otherwise, any configuration
* based on this variable will be incorrect.
*
* @note - The system frequency computed by this function is not the real
* frequency in the chip. It is calculated based on the predefined
* constant and the selected clock source:
*
* - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*)
*
* - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**)
*
* - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**)
* or HSI_VALUE(*) multiplied/divided by the PLL factors.
*
* (*) HSI_VALUE is a constant defined in stm32f3xx_hal.h file (default value
* 8 MHz) but the real value may vary depending on the variations
* in voltage and temperature.
*
* (**) HSE_VALUE is a constant defined in stm32f3xx_hal.h file (default value
* 8 MHz), user has to ensure that HSE_VALUE is same as the real
* frequency of the crystal used. Otherwise, this function may
* have wrong result.
*
* - The result of this function could be not correct when using fractional
* value for HSE crystal.
*
* @param None
* @retval None
*/
void SystemCoreClockUpdate (void)
{
uint32_t tmp = 0, pllmull = 0, pllsource = 0, predivfactor = 0;
/* Get SYSCLK source -------------------------------------------------------*/
tmp = RCC->CFGR & RCC_CFGR_SWS;
switch (tmp)
{
case RCC_CFGR_SWS_HSI: /* HSI used as system clock */
SystemCoreClock = HSI_VALUE;
break;
case RCC_CFGR_SWS_HSE: /* HSE used as system clock */
SystemCoreClock = HSE_VALUE;
break;
case RCC_CFGR_SWS_PLL: /* PLL used as system clock */
/* Get PLL clock source and multiplication factor ----------------------*/
pllmull = RCC->CFGR & RCC_CFGR_PLLMUL;
pllsource = RCC->CFGR & RCC_CFGR_PLLSRC;
pllmull = ( pllmull >> 18) + 2;
#if defined (STM32F302xE) || defined (STM32F303xE) || defined (STM32F398xx)
predivfactor = (RCC->CFGR2 & RCC_CFGR2_PREDIV) + 1;
if (pllsource == RCC_CFGR_PLLSRC_HSE_PREDIV)
{
/* HSE oscillator clock selected as PREDIV1 clock entry */
SystemCoreClock = (HSE_VALUE / predivfactor) * pllmull;
}
else
{
/* HSI oscillator clock selected as PREDIV1 clock entry */
SystemCoreClock = (HSI_VALUE / predivfactor) * pllmull;
}
#else
if (pllsource == RCC_CFGR_PLLSRC_HSI_DIV2)
{
/* HSI oscillator clock divided by 2 selected as PLL clock entry */
SystemCoreClock = (HSI_VALUE >> 1) * pllmull;
}
else
{
predivfactor = (RCC->CFGR2 & RCC_CFGR2_PREDIV) + 1;
/* HSE oscillator clock selected as PREDIV1 clock entry */
SystemCoreClock = (HSE_VALUE / predivfactor) * pllmull;
}
#endif /* STM32F302xE || STM32F303xE || STM32F398xx */
break;
default: /* HSI used as system clock */
SystemCoreClock = HSI_VALUE;
break;
}
/* Compute HCLK clock frequency ----------------*/
/* Get HCLK prescaler */
tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)];
/* HCLK clock frequency */
SystemCoreClock >>= tmp;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/