Subversion Repositories EngineBay2

Rev

Rev 54 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /* USER CODE BEGIN Header */
  2. /**
  3.  ******************************************************************************
  4.  * @file           : main.c
  5.  * @brief          : Main program body
  6.  ******************************************************************************
  7.  * @attention
  8.  *
  9.  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
  10.  * All rights reserved.</center></h2>
  11.  *
  12.  * This software component is licensed by ST under BSD 3-Clause license,
  13.  * the "License"; You may not use this file except in compliance with the
  14.  * License. You may obtain a copy of the License at:
  15.  *                        opensource.org/licenses/BSD-3-Clause
  16.  *
  17.  ******************************************************************************
  18.  */
  19. /* USER CODE END Header */
  20. /* Includes ------------------------------------------------------------------*/
  21. #include "main.h"
  22.  
  23. /* Private includes ----------------------------------------------------------*/
  24. /* USER CODE BEGIN Includes */
  25. #include <string.h>
  26. #include <math.h>
  27. #include "libSerial/serial.h"
  28. #include "libPLX/plx.h"
  29. #include "libPLX/commsLib.h"
  30. #include "misc.h"
  31.  
  32. #include "libIgnTiming/rpm.h"
  33.  
  34.  
  35.  
  36. /* USER CODE END Includes */
  37.  
  38. /* Private typedef -----------------------------------------------------------*/
  39. /* USER CODE BEGIN PTD */
  40.  
  41. /* USER CODE END PTD */
  42.  
  43. /* Private define ------------------------------------------------------------*/
  44. /* USER CODE BEGIN PD */
  45. /* USER CODE END PD */
  46.  
  47. /* Private macro -------------------------------------------------------------*/
  48. /* USER CODE BEGIN PM */
  49. #define ADC_CHANNELS 7
  50.  
  51. #define ADC_MAP_CHAN 2
  52.  
  53. #define ADC_PRESSURE_CHAN 3
  54.  
  55. #define ADC_REF_CHAN 5
  56.  
  57. #define ADC_TEMP_CHAN 6
  58.  
  59. // wait for about 1 second to decide whether or not starter is on
  60.  
  61. #define STARTER_LIMIT 10
  62.  
  63. /* USER CODE END PM */
  64.  
  65. /* Private variables ---------------------------------------------------------*/
  66. ADC_HandleTypeDef hadc1;
  67. DMA_HandleTypeDef hdma_adc1;
  68.  
  69. CAN_HandleTypeDef hcan;
  70.  
  71. IWDG_HandleTypeDef hiwdg;
  72.  
  73. SPI_HandleTypeDef hspi1;
  74.  
  75. TIM_HandleTypeDef htim2;
  76. TIM_HandleTypeDef htim3;
  77. TIM_HandleTypeDef htim4;
  78.  
  79. UART_HandleTypeDef huart1;
  80.  
  81. /* USER CODE BEGIN PV */
  82.  
  83. // Storage for USART
  84. #define USART_TX_BUFF_SIZE 256
  85. #define USART_RX_BUFF_SIZE 256
  86. uint8_t usartTxBuff[USART_TX_BUFF_SIZE];
  87. uint8_t usartRxBuff[USART_RX_BUFF_SIZE];
  88.  
  89. // storage for ADC
  90. uint16_t ADC_Samples[ADC_CHANNELS] = {[0 ... ADC_CHANNELS - 1] = 0};
  91.  
  92. uint32_t FILT_Samples[ADC_CHANNELS] = {[0 ... ADC_CHANNELS - 1] = 0}; // filtered ADC samples * Scale
  93.  
  94. #define NOM_VREF 3.3
  95. // initial ADC vref
  96. float adc_vref = NOM_VREF;
  97.  
  98. // internal bandgap voltage reference
  99. const float STM32REF = 1.2; // 1.2V typical
  100.  
  101. // scale factor initially assuming
  102. float ADC_Scale = 1 / (Scale * 4096) * NOM_VREF;
  103.  
  104. unsigned int Coded_RPM = 0;
  105. unsigned int Coded_CHT = 0;
  106.  
  107. uint32_t PowerTempTimer;
  108.  
  109. uint16_t Starter_Debounce = 0;
  110.  
  111. /* USER CODE END PV */
  112.  
  113. /* Private function prototypes -----------------------------------------------*/
  114. void SystemClock_Config(void);
  115. static void MX_GPIO_Init(void);
  116. static void MX_DMA_Init(void);
  117. static void MX_ADC1_Init(void);
  118. static void MX_CAN_Init(void);
  119. static void MX_SPI1_Init(void);
  120. static void MX_TIM2_Init(void);
  121. static void MX_TIM3_Init(void);
  122. static void MX_TIM4_Init(void);
  123. static void MX_USART1_UART_Init(void);
  124. static void MX_IWDG_Init(void);
  125. /* USER CODE BEGIN PFP */
  126.  
  127. /* USER CODE END PFP */
  128.  
  129. /* Private user code ---------------------------------------------------------*/
  130. /* USER CODE BEGIN 0 */
  131. void libPLXcallbackRecievedData(PLX_SensorInfo * data)
  132. {
  133.   (void )data;
  134.  
  135. }
  136.  
  137.  
  138. void filter_ADC_samples()
  139. {
  140.   int i;
  141.   for (i = 0; i < ADC_CHANNELS; i++)
  142.   {
  143.     FILT_Samples[i] += (ADC_Samples[i] * Scale - FILT_Samples[i]) / 2;
  144.   }
  145. }
  146.  
  147. /****!
  148.  * @brief this reads the reference voltage within the STM32L151
  149.  * Powers up reference voltage and temperature sensor, waits 3mS  and takes reading
  150.  * Requires that the ADC be powered up
  151.  */
  152.  
  153. void CalibrateADC(void)
  154. {
  155.   float adc_val = FILT_Samples[ADC_REF_CHAN]; // as set up in device config
  156.  
  157.   float adc_vref = STM32REF * (4096.0 * Scale) / adc_val; // the estimate for checking
  158.  
  159.   ADC_Scale = 1 / (Scale * 4096) * adc_vref;
  160. }
  161.  
  162. void ProcessRPM(struct usart_ctl * handle)
  163. {
  164.   static unsigned int Coded_RPM = 0;
  165.   int32_t rpm = CalculateRPM();
  166.   // suppress the EDIS "heartbeat" 90 RPM
  167.   if (rpm >= 100)
  168.     Coded_RPM = rpm / 19.55;
  169.  
  170.   // send the current RPM *calculation
  171.   sendPlxInfo(handle, PLX_RPM, Coded_RPM/ Scale);
  172. }
  173.  
  174. // this uses a MAX6675 which is a simple 16 bit read
  175. // SPI is configured for 8 bits so I can use an OLED display if I need it
  176. // must wait > 0.22 seconds between conversion attempts as this is the measurement time
  177. //
  178.  
  179. FunctionalState CHT_Enable = ENABLE;
  180.  
  181. #define CORR 3
  182.  
  183.  
  184. typedef struct  
  185. {
  186.   uint16_t store[TEMP_CORR];
  187.   uint16_t result;
  188. } tempObservation_t;
  189.  
  190. tempObservation_t Temp_Observations[NUM_SPI_TEMP_SENS];
  191.  
  192. void ResetTemp()
  193. {
  194.   int i,j;
  195.   for (i=0;i<NUM_SPI_TEMP_SENS;i++)
  196.   {
  197.     Temp_Observations[i].result = 0;
  198.     for (j=0;j<TEMP_CORR;j++)
  199.       Temp_Observations[i].store[j]=0;
  200.   }
  201. }
  202.  
  203. void AddTempReading(uint16_t reading, int channel)
  204. {
  205.   int j;
  206.   for (j=TEMP_CORR-1; j>=1 ; j--)
  207.   {
  208.     Temp_Observations[channel].store[j] = Temp_Observations[channel].store[j-1];
  209.   }
  210.   Temp_Observations[channel].store[0] = reading;
  211.  
  212.   // are all the stored values close to the current reading, if so allow it through
  213.   // the check here is for 5 degrees C
  214.   char good = 1;
  215.   for (j=1; j<TEMP_CORR; j++)
  216.     if (abs((int)Temp_Observations[channel].store[j]- (int)reading)>5)
  217.       good = 0;
  218.  
  219.   if (good)
  220.     Temp_Observations[channel].result = reading;
  221. }
  222.  
  223.  
  224. /// \param item The array index to send
  225. /// \param type the code to use for this observation
  226. void ProcessTemp(struct usart_ctl * handle,char item, enum PLX_Observations type)
  227. {
  228.   if (item > NUM_SPI_TEMP_SENS)
  229.     return;
  230.  
  231.   sendPlxInfo(handle, type , Temp_Observations[(int)item].result);
  232.  
  233. }
  234.  
  235. /// \brief Reset the temperature chip select system
  236. void resetTempCS(void)
  237. {
  238.   HAL_GPIO_WritePin(SPI_CS_D_GPIO_Port, SPI_CS_D_Pin, GPIO_PIN_SET);
  239.   HAL_GPIO_WritePin(SPI_CS_Clk_GPIO_Port, SPI_CS_Clk_Pin,
  240.                     GPIO_PIN_SET);
  241.  
  242.   for (int i = 0; i < 8; i++)
  243.   {
  244.     HAL_GPIO_WritePin(SPI_CS_Clk_GPIO_Port, SPI_CS_Clk_Pin,
  245.                       GPIO_PIN_RESET);
  246.     HAL_GPIO_WritePin(SPI_CS_Clk_GPIO_Port, SPI_CS_Clk_Pin,
  247.                       GPIO_PIN_SET);
  248.   }
  249.  
  250.   // prepare for selecting next pin
  251.   HAL_GPIO_WritePin(SPI_CS_D_GPIO_Port, SPI_CS_D_Pin, GPIO_PIN_RESET);
  252. }
  253.  
  254. void nextTempCS(void)
  255. {
  256.   HAL_GPIO_WritePin(SPI_CS_Clk_GPIO_Port, SPI_CS_Clk_Pin,
  257.                     GPIO_PIN_RESET);
  258.   HAL_GPIO_WritePin(SPI_CS_Clk_GPIO_Port, SPI_CS_Clk_Pin,
  259.                     GPIO_PIN_SET);
  260.   HAL_GPIO_WritePin(SPI_CS_D_GPIO_Port, SPI_CS_D_Pin, GPIO_PIN_SET);
  261. }
  262.  
  263. void EnableTempSensors(FunctionalState state)
  264.  
  265. {
  266.   GPIO_InitTypeDef GPIO_InitStruct;
  267.  
  268.   CHT_Enable = state;
  269.  
  270.   /* enable SPI in live mode : assume it and its GPIOs are already initialised in SPI mode */
  271.   if (state == ENABLE)
  272.   {
  273.     HAL_GPIO_WritePin(ENA_AUX_5V_GPIO_Port, ENA_AUX_5V_Pin, GPIO_PIN_SET);
  274.  
  275.     resetTempCS();
  276.  
  277.     /* put the SPI pins back into SPI AF mode */
  278.     GPIO_InitStruct.Pin = SPI1_MOSI_Pin | SPI1_MISO_Pin | SPI1_SCK_Pin;
  279.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  280.     GPIO_InitStruct.Pull = GPIO_NOPULL;
  281.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  282.     HAL_GPIO_Init(SPI1_SCK_GPIO_Port, &GPIO_InitStruct);
  283.   }
  284.   else
  285.   {
  286.     /*  Power down the SPI interface taking signals all low */
  287.     HAL_GPIO_WritePin(ENA_AUX_5V_GPIO_Port, ENA_AUX_5V_Pin, GPIO_PIN_RESET);
  288.  
  289.     HAL_GPIO_WritePin(SPI1_SCK_GPIO_Port,
  290.                       SPI1_MOSI_Pin | SPI1_MISO_Pin | SPI1_SCK_Pin,
  291.                       GPIO_PIN_RESET);
  292.  
  293.     /* put the SPI pins back into GPIO mode */
  294.     GPIO_InitStruct.Pin = SPI1_MOSI_Pin | SPI1_MISO_Pin | SPI1_SCK_Pin;
  295.     GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  296.     GPIO_InitStruct.Pull = GPIO_NOPULL;
  297.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  298.     HAL_GPIO_Init(SPI1_SCK_GPIO_Port, &GPIO_InitStruct);
  299.   }
  300. }
  301.  
  302. // 1023 is 20.00 volts.
  303. /// \param item - used to lookup the index of the local reading
  304. void ProcessBatteryVoltage(struct usart_ctl * handle, int item)
  305. {
  306.   float reading = FILT_Samples[item] * ADC_Scale;
  307.   reading = reading * 7.8125; // real voltage
  308.   reading = reading * 51.15;  // PLC scaling =  1023/20
  309.  
  310.   sendPlxInfo(handle, PLX_Volts, reading);
  311.  
  312. }
  313.  
  314. void ProcessCPUTemperature(struct usart_ctl * handle)
  315. {
  316.   // this is defined in the STM32F103 reference manual . #
  317.   // V25 = 1.43 volts
  318.   // Avg_slope = 4.3mV /degree C
  319.   // temperature = {(V25 - VSENSE) / Avg_Slope} + 25
  320.  
  321.   /* get the ADC reading corresponding to ADC channel 16 after turning on the ADC */
  322.  
  323.   float temp_val = FILT_Samples[ADC_TEMP_CHAN] * ADC_Scale;
  324.   /* renormalise temperature value to account for different ADC Vref  : normalise to that which we would get for a 3000mV reference */
  325.   temp_val = (1.43 - temp_val) / 4.3e-3 + 25;
  326.  
  327.   int32_t result = temp_val;
  328.  
  329.   sendPlxInfo(handle, PLX_FluidTemp, result);
  330.  
  331. }
  332.  
  333. // the MAP sensor is giving us a reading of
  334. // 4.6 volts for 1019mB or 2.27 volts at the ADC input (resistive divider by 2.016)
  335. // I believe the sensor reads  4.5V at 1000kPa and 0.5V at  0kPa
  336. // Calibration is a bit off
  337. // Real   Displayed
  338. // 989    968
  339. // 994.1    986
  340. // 992.3  984
  341.  
  342. void ProcessMAP(struct usart_ctl * handle)
  343. {
  344.   // Using ADC_Samples[3] as the MAP input
  345.   float reading = FILT_Samples[ADC_MAP_CHAN] * ADC_Scale;
  346.   reading = reading * 2.016; // real voltage
  347.   // values computed from slope / intercept of map.ods
  348.   // reading = (reading) * 56.23 + 743.2; // do not assume 0.5 volt offset : reading from 0 to 4.5 instead of 0.5 to 4.5
  349.   // using a pressure gauge.
  350.   reading = (reading) * 150 + 326;
  351.  
  352.   sendPlxInfo(handle, PLX_MAP, reading);
  353.  
  354. }
  355.  
  356. // the Oil pressi sensor is giving us a reading of
  357. // 4.5 volts for 100 PSI or  2.25 volts at the ADC input (resistive divider by 2.016)
  358. // I believe the sensor reads  4.5V at 100PSI and 0.5V at  0PSI
  359. // an observation of 1024 is 200PSI, so observation of 512 is 100 PSI.
  360.  
  361. void ProcessOilPress(struct usart_ctl * handle)
  362. {
  363.   // Using ADC_Samples[2] as the MAP input
  364.   float reading = FILT_Samples[ADC_PRESSURE_CHAN] * ADC_Scale;
  365.   reading = reading * 2.00;            // real voltage
  366.   reading = (reading - 0.5) * 512 / 4; // this is 1023 * 100/200
  367.  
  368.   sendPlxInfo(handle, PLX_FluidPressure, reading);
  369.  
  370. }
  371.  
  372.  
  373. void libPLXcallbackSendUserData(struct usart_ctl * handle)
  374. {
  375.   // send the observations
  376.   ProcessRPM(handle);
  377.   ProcessTemp(handle,0, PLX_X_CHT);
  378.   ProcessTemp(handle,1, PLX_X_CHT);
  379.   ProcessTemp(handle,2, PLX_AIT);
  380.   ProcessTemp(handle,3, PLX_AIT);
  381.   ProcessBatteryVoltage(handle,0); // Batt 1
  382.   ProcessBatteryVoltage(handle,1); // Batt 2
  383.   ProcessCPUTemperature(handle);  //  built in temperature sensor
  384.  
  385.   ProcessMAP(handle);
  386.   ProcessOilPress(handle);
  387. }
  388. /* USER CODE END 0 */
  389.  
  390. /**
  391.   * @brief  The application entry point.
  392.   * @retval int
  393.   */
  394. int main(void)
  395. {
  396.  
  397.   /* USER CODE BEGIN 1 */
  398.  
  399.   /* USER CODE END 1 */
  400.  
  401.   /* MCU Configuration--------------------------------------------------------*/
  402.  
  403.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  404.   HAL_Init();
  405.  
  406.   /* USER CODE BEGIN Init */
  407.  
  408.   /* USER CODE END Init */
  409.  
  410.   /* Configure the system clock */
  411.   SystemClock_Config();
  412.  
  413.   /* USER CODE BEGIN SysInit */
  414.  
  415.   /* USER CODE END SysInit */
  416.  
  417.   /* Initialize all configured peripherals */
  418.   MX_GPIO_Init();
  419.   MX_DMA_Init();
  420.   MX_ADC1_Init();
  421.   MX_CAN_Init();
  422.   MX_SPI1_Init();
  423.   MX_TIM2_Init();
  424.   MX_TIM3_Init();
  425.   MX_TIM4_Init();
  426.   MX_USART1_UART_Init();
  427.   MX_IWDG_Init();
  428.   /* USER CODE BEGIN 2 */
  429.   HAL_MspInit();
  430.  
  431.   // Not using HAL USART code
  432.   __HAL_RCC_USART1_CLK_ENABLE(); // PLX comms port
  433.   /* setup the USART control blocks */
  434.   init_usart_ctl(&uc1, &huart1,
  435.                  usartTxBuff,
  436.                  usartRxBuff,
  437.                  USART_TX_BUFF_SIZE,
  438.                  USART_RX_BUFF_SIZE);
  439.  
  440.   EnableSerialRxInterrupt(&uc1);
  441.  
  442.   HAL_SPI_MspInit(&hspi1);
  443.  
  444.   HAL_ADC_MspInit(&hadc1);
  445.  
  446.   HAL_ADC_Start_DMA(&hadc1, (uint32_t *)ADC_Samples, ADC_CHANNELS);
  447.  
  448.   HAL_ADC_Start_IT(&hadc1);
  449.  
  450.     ResetTemp(); // reset temperature store
  451.  
  452.   HAL_TIM_Base_MspInit(&htim4);
  453.   HAL_TIM_Base_Start_IT(&htim4);
  454.  
  455.   // initialise all the STMCubeMX stuff
  456.   HAL_TIM_Base_MspInit(&htim2);
  457.   // Start the counter
  458.   HAL_TIM_Base_Start(&htim2);
  459.   // Start the input capture and the rising edge interrupt
  460.   HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
  461.   // Start the input capture and the falling edge interrupt
  462.   HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_2);
  463.  
  464.   HAL_TIM_Base_MspInit(&htim3);
  465.   __HAL_TIM_ENABLE_IT(&htim3, TIM_IT_UPDATE);
  466.   uint32_t Ticks = HAL_GetTick() + 100;
  467.   int CalCounter = 0;
  468.  
  469.   PowerTempTimer = HAL_GetTick() + 1000; /* wait 10 seconds before powering up the CHT sensor */
  470.  
  471.   ResetRxBuffer(&uc1);
  472.  
  473.   resetPLX();
  474.   /* USER CODE END 2 */
  475.  
  476.   /* Infinite loop */
  477.   /* USER CODE BEGIN WHILE */
  478.   while (1)
  479.   {
  480.     /* USER CODE END WHILE */
  481.  
  482.     /* USER CODE BEGIN 3 */
  483.  
  484.     if (HAL_GetTick() > Ticks)
  485.     {
  486.       Ticks += 100;
  487.       filter_ADC_samples();
  488.       // delay to calibrate ADC
  489.       if (CalCounter < 1000)
  490.       {
  491.         CalCounter += 100;
  492.       }
  493.  
  494.       if (CalCounter == 900)
  495.       {
  496.         CalibrateADC();
  497.       }
  498.     }
  499.     /* when the starter motor is on then power down the CHT sensors as they seem to fail */
  500.  
  501.     if (HAL_GPIO_ReadPin(STARTER_ON_GPIO_Port, STARTER_ON_Pin) == GPIO_PIN_RESET)
  502.     {
  503.       if (Starter_Debounce < STARTER_LIMIT)
  504.       {
  505.         Starter_Debounce++;
  506.       }
  507.     }
  508.     else
  509.     {
  510.       if (Starter_Debounce > 0)
  511.       {
  512.         Starter_Debounce--;
  513.       }
  514.     }
  515.  
  516.     if (Starter_Debounce == STARTER_LIMIT)
  517.     {
  518.       EnableTempSensors(DISABLE);
  519.       PowerTempTimer = HAL_GetTick() + 1000;
  520.     }
  521.     else
  522.     /* if the PowerTempTimer is set then wait for it to timeout, then power up CHT */
  523.     {
  524.       if ((PowerTempTimer > 0) && (HAL_GetTick() > PowerTempTimer))
  525.       {
  526.         EnableTempSensors(ENABLE);
  527.         PowerTempTimer = 0;
  528.       }
  529.     }
  530.  
  531.     // check to see if we have any incoming data, copy and append if so, if no data then create our own frames.
  532.  
  533.     // poll the input data and produce automatic output if the timer expires and no serial input data
  534.     libPLXpollData(&uc1);
  535.  
  536.     HAL_IWDG_Refresh(&hiwdg);
  537.   }
  538.  
  539.   /* USER CODE END 3 */
  540. }
  541.  
  542. /**
  543.   * @brief System Clock Configuration
  544.   * @retval None
  545.   */
  546. void SystemClock_Config(void)
  547. {
  548.   RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  549.   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  550.   RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
  551.  
  552.   /** Initializes the RCC Oscillators according to the specified parameters
  553.   * in the RCC_OscInitTypeDef structure.
  554.   */
  555.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_HSE;
  556.   RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  557.   RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  558.   RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  559.   RCC_OscInitStruct.LSIState = RCC_LSI_ON;
  560.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  561.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  562.   RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  563.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  564.   {
  565.     Error_Handler();
  566.   }
  567.  
  568.   /** Initializes the CPU, AHB and APB buses clocks
  569.   */
  570.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
  571.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  572.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  573.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  574.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  575.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
  576.  
  577.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  578.   {
  579.     Error_Handler();
  580.   }
  581.   PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
  582.   PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;
  583.   if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  584.   {
  585.     Error_Handler();
  586.   }
  587. }
  588.  
  589. /**
  590.   * @brief ADC1 Initialization Function
  591.   * @param None
  592.   * @retval None
  593.   */
  594. static void MX_ADC1_Init(void)
  595. {
  596.  
  597.   /* USER CODE BEGIN ADC1_Init 0 */
  598.  
  599.   /* USER CODE END ADC1_Init 0 */
  600.  
  601.   ADC_ChannelConfTypeDef sConfig = {0};
  602.  
  603.   /* USER CODE BEGIN ADC1_Init 1 */
  604.  
  605.   /* USER CODE END ADC1_Init 1 */
  606.  
  607.   /** Common config
  608.   */
  609.   hadc1.Instance = ADC1;
  610.   hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
  611.   hadc1.Init.ContinuousConvMode = DISABLE;
  612.   hadc1.Init.DiscontinuousConvMode = DISABLE;
  613.   hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T3_TRGO;
  614.   hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  615.   hadc1.Init.NbrOfConversion = 7;
  616.   if (HAL_ADC_Init(&hadc1) != HAL_OK)
  617.   {
  618.     Error_Handler();
  619.   }
  620.  
  621.   /** Configure Regular Channel
  622.   */
  623.   sConfig.Channel = ADC_CHANNEL_0;
  624.   sConfig.Rank = ADC_REGULAR_RANK_1;
  625.   sConfig.SamplingTime = ADC_SAMPLETIME_71CYCLES_5;
  626.   if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  627.   {
  628.     Error_Handler();
  629.   }
  630.  
  631.   /** Configure Regular Channel
  632.   */
  633.   sConfig.Channel = ADC_CHANNEL_1;
  634.   sConfig.Rank = ADC_REGULAR_RANK_2;
  635.   if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  636.   {
  637.     Error_Handler();
  638.   }
  639.  
  640.   /** Configure Regular Channel
  641.   */
  642.   sConfig.Channel = ADC_CHANNEL_2;
  643.   sConfig.Rank = ADC_REGULAR_RANK_3;
  644.   if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  645.   {
  646.     Error_Handler();
  647.   }
  648.  
  649.   /** Configure Regular Channel
  650.   */
  651.   sConfig.Channel = ADC_CHANNEL_3;
  652.   sConfig.Rank = ADC_REGULAR_RANK_4;
  653.   if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  654.   {
  655.     Error_Handler();
  656.   }
  657.  
  658.   /** Configure Regular Channel
  659.   */
  660.   sConfig.Channel = ADC_CHANNEL_4;
  661.   sConfig.Rank = ADC_REGULAR_RANK_5;
  662.   if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  663.   {
  664.     Error_Handler();
  665.   }
  666.  
  667.   /** Configure Regular Channel
  668.   */
  669.   sConfig.Channel = ADC_CHANNEL_VREFINT;
  670.   sConfig.Rank = ADC_REGULAR_RANK_6;
  671.   if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  672.   {
  673.     Error_Handler();
  674.   }
  675.  
  676.   /** Configure Regular Channel
  677.   */
  678.   sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
  679.   sConfig.Rank = ADC_REGULAR_RANK_7;
  680.   if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  681.   {
  682.     Error_Handler();
  683.   }
  684.   /* USER CODE BEGIN ADC1_Init 2 */
  685.  
  686.   /* USER CODE END ADC1_Init 2 */
  687.  
  688. }
  689.  
  690. /**
  691.   * @brief CAN Initialization Function
  692.   * @param None
  693.   * @retval None
  694.   */
  695. static void MX_CAN_Init(void)
  696. {
  697.  
  698.   /* USER CODE BEGIN CAN_Init 0 */
  699.  
  700.   /* USER CODE END CAN_Init 0 */
  701.  
  702.   /* USER CODE BEGIN CAN_Init 1 */
  703.  
  704.   /* USER CODE END CAN_Init 1 */
  705.   hcan.Instance = CAN1;
  706.   hcan.Init.Prescaler = 16;
  707.   hcan.Init.Mode = CAN_MODE_NORMAL;
  708.   hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
  709.   hcan.Init.TimeSeg1 = CAN_BS1_1TQ;
  710.   hcan.Init.TimeSeg2 = CAN_BS2_1TQ;
  711.   hcan.Init.TimeTriggeredMode = DISABLE;
  712.   hcan.Init.AutoBusOff = DISABLE;
  713.   hcan.Init.AutoWakeUp = DISABLE;
  714.   hcan.Init.AutoRetransmission = DISABLE;
  715.   hcan.Init.ReceiveFifoLocked = DISABLE;
  716.   hcan.Init.TransmitFifoPriority = DISABLE;
  717.   if (HAL_CAN_Init(&hcan) != HAL_OK)
  718.   {
  719.     Error_Handler();
  720.   }
  721.   /* USER CODE BEGIN CAN_Init 2 */
  722.  
  723.   /* USER CODE END CAN_Init 2 */
  724.  
  725. }
  726.  
  727. /**
  728.   * @brief IWDG Initialization Function
  729.   * @param None
  730.   * @retval None
  731.   */
  732. static void MX_IWDG_Init(void)
  733. {
  734.  
  735.   /* USER CODE BEGIN IWDG_Init 0 */
  736.  
  737.   /* USER CODE END IWDG_Init 0 */
  738.  
  739.   /* USER CODE BEGIN IWDG_Init 1 */
  740.  
  741.   /* USER CODE END IWDG_Init 1 */
  742.   hiwdg.Instance = IWDG;
  743.   hiwdg.Init.Prescaler = IWDG_PRESCALER_64;
  744.   hiwdg.Init.Reload = 4095;
  745.   if (HAL_IWDG_Init(&hiwdg) != HAL_OK)
  746.   {
  747.     Error_Handler();
  748.   }
  749.   /* USER CODE BEGIN IWDG_Init 2 */
  750.  
  751.   /* USER CODE END IWDG_Init 2 */
  752.  
  753. }
  754.  
  755. /**
  756.   * @brief SPI1 Initialization Function
  757.   * @param None
  758.   * @retval None
  759.   */
  760. static void MX_SPI1_Init(void)
  761. {
  762.  
  763.   /* USER CODE BEGIN SPI1_Init 0 */
  764.  
  765.   /* USER CODE END SPI1_Init 0 */
  766.  
  767.   /* USER CODE BEGIN SPI1_Init 1 */
  768.  
  769.   /* USER CODE END SPI1_Init 1 */
  770.   /* SPI1 parameter configuration*/
  771.   hspi1.Instance = SPI1;
  772.   hspi1.Init.Mode = SPI_MODE_MASTER;
  773.   hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  774.   hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  775.   hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  776.   hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  777.   hspi1.Init.NSS = SPI_NSS_SOFT;
  778.   hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
  779.   hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  780.   hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  781.   hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  782.   hspi1.Init.CRCPolynomial = 10;
  783.   if (HAL_SPI_Init(&hspi1) != HAL_OK)
  784.   {
  785.     Error_Handler();
  786.   }
  787.   /* USER CODE BEGIN SPI1_Init 2 */
  788.  
  789.   /* USER CODE END SPI1_Init 2 */
  790.  
  791. }
  792.  
  793. /**
  794.   * @brief TIM2 Initialization Function
  795.   * @param None
  796.   * @retval None
  797.   */
  798. static void MX_TIM2_Init(void)
  799. {
  800.  
  801.   /* USER CODE BEGIN TIM2_Init 0 */
  802.  
  803.   /* USER CODE END TIM2_Init 0 */
  804.  
  805.   TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  806.   TIM_MasterConfigTypeDef sMasterConfig = {0};
  807.   TIM_IC_InitTypeDef sConfigIC = {0};
  808.  
  809.   /* USER CODE BEGIN TIM2_Init 1 */
  810.  
  811.   /* USER CODE END TIM2_Init 1 */
  812.   htim2.Instance = TIM2;
  813.   htim2.Init.Prescaler = 719;
  814.   htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  815.   htim2.Init.Period = 65535;
  816.   htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  817.   htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  818.   if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  819.   {
  820.     Error_Handler();
  821.   }
  822.   sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  823.   if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  824.   {
  825.     Error_Handler();
  826.   }
  827.   if (HAL_TIM_IC_Init(&htim2) != HAL_OK)
  828.   {
  829.     Error_Handler();
  830.   }
  831.   sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
  832.   sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  833.   if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  834.   {
  835.     Error_Handler();
  836.   }
  837.   sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
  838.   sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
  839.   sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
  840.   sConfigIC.ICFilter = 15;
  841.   if (HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_1) != HAL_OK)
  842.   {
  843.     Error_Handler();
  844.   }
  845.   sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING;
  846.   sConfigIC.ICSelection = TIM_ICSELECTION_INDIRECTTI;
  847.   sConfigIC.ICFilter = 0;
  848.   if (HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_2) != HAL_OK)
  849.   {
  850.     Error_Handler();
  851.   }
  852.   /* USER CODE BEGIN TIM2_Init 2 */
  853.  
  854.   /* USER CODE END TIM2_Init 2 */
  855.  
  856. }
  857.  
  858. /**
  859.   * @brief TIM3 Initialization Function
  860.   * @param None
  861.   * @retval None
  862.   */
  863. static void MX_TIM3_Init(void)
  864. {
  865.  
  866.   /* USER CODE BEGIN TIM3_Init 0 */
  867.  
  868.   /* USER CODE END TIM3_Init 0 */
  869.  
  870.   TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  871.   TIM_MasterConfigTypeDef sMasterConfig = {0};
  872.   TIM_OC_InitTypeDef sConfigOC = {0};
  873.  
  874.   /* USER CODE BEGIN TIM3_Init 1 */
  875.  
  876.   /* USER CODE END TIM3_Init 1 */
  877.   htim3.Instance = TIM3;
  878.   htim3.Init.Prescaler = 719;
  879.   htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  880.   htim3.Init.Period = 199;
  881.   htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  882.   htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  883.   if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
  884.   {
  885.     Error_Handler();
  886.   }
  887.   sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  888.   if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
  889.   {
  890.     Error_Handler();
  891.   }
  892.   if (HAL_TIM_OC_Init(&htim3) != HAL_OK)
  893.   {
  894.     Error_Handler();
  895.   }
  896.   if (HAL_TIM_OnePulse_Init(&htim3, TIM_OPMODE_SINGLE) != HAL_OK)
  897.   {
  898.     Error_Handler();
  899.   }
  900.   sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC1;
  901.   sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  902.   if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
  903.   {
  904.     Error_Handler();
  905.   }
  906.   sConfigOC.OCMode = TIM_OCMODE_TIMING;
  907.   sConfigOC.Pulse = 198;
  908.   sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  909.   sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  910.   if (HAL_TIM_OC_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  911.   {
  912.     Error_Handler();
  913.   }
  914.   /* USER CODE BEGIN TIM3_Init 2 */
  915.  
  916.   /* USER CODE END TIM3_Init 2 */
  917.  
  918. }
  919.  
  920. /**
  921.   * @brief TIM4 Initialization Function
  922.   * @param None
  923.   * @retval None
  924.   */
  925. static void MX_TIM4_Init(void)
  926. {
  927.  
  928.   /* USER CODE BEGIN TIM4_Init 0 */
  929.  
  930.   /* USER CODE END TIM4_Init 0 */
  931.  
  932.   TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  933.   TIM_MasterConfigTypeDef sMasterConfig = {0};
  934.  
  935.   /* USER CODE BEGIN TIM4_Init 1 */
  936.  
  937.   /* USER CODE END TIM4_Init 1 */
  938.   htim4.Instance = TIM4;
  939.   htim4.Init.Prescaler = 719;
  940.   htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
  941.   htim4.Init.Period = 9999;
  942.   htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  943.   htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  944.   if (HAL_TIM_Base_Init(&htim4) != HAL_OK)
  945.   {
  946.     Error_Handler();
  947.   }
  948.   sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  949.   if (HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig) != HAL_OK)
  950.   {
  951.     Error_Handler();
  952.   }
  953.   sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
  954.   sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  955.   if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK)
  956.   {
  957.     Error_Handler();
  958.   }
  959.   /* USER CODE BEGIN TIM4_Init 2 */
  960.  
  961.   /* USER CODE END TIM4_Init 2 */
  962.  
  963. }
  964.  
  965. /**
  966.   * @brief USART1 Initialization Function
  967.   * @param None
  968.   * @retval None
  969.   */
  970. static void MX_USART1_UART_Init(void)
  971. {
  972.  
  973.   /* USER CODE BEGIN USART1_Init 0 */
  974.  
  975.   /* USER CODE END USART1_Init 0 */
  976.  
  977.   /* USER CODE BEGIN USART1_Init 1 */
  978.  
  979.   /* USER CODE END USART1_Init 1 */
  980.   huart1.Instance = USART1;
  981.   huart1.Init.BaudRate = 19200;
  982.   huart1.Init.WordLength = UART_WORDLENGTH_8B;
  983.   huart1.Init.StopBits = UART_STOPBITS_1;
  984.   huart1.Init.Parity = UART_PARITY_NONE;
  985.   huart1.Init.Mode = UART_MODE_TX_RX;
  986.   huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  987.   huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  988.   if (HAL_UART_Init(&huart1) != HAL_OK)
  989.   {
  990.     Error_Handler();
  991.   }
  992.   /* USER CODE BEGIN USART1_Init 2 */
  993.  
  994.   /* USER CODE END USART1_Init 2 */
  995.  
  996. }
  997.  
  998. /**
  999.   * Enable DMA controller clock
  1000.   */
  1001. static void MX_DMA_Init(void)
  1002. {
  1003.  
  1004.   /* DMA controller clock enable */
  1005.   __HAL_RCC_DMA1_CLK_ENABLE();
  1006.  
  1007.   /* DMA interrupt init */
  1008.   /* DMA1_Channel1_IRQn interrupt configuration */
  1009.   HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
  1010.   HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
  1011.  
  1012. }
  1013.  
  1014. /**
  1015.   * @brief GPIO Initialization Function
  1016.   * @param None
  1017.   * @retval None
  1018.   */
  1019. static void MX_GPIO_Init(void)
  1020. {
  1021.   GPIO_InitTypeDef GPIO_InitStruct = {0};
  1022. /* USER CODE BEGIN MX_GPIO_Init_1 */
  1023. /* USER CODE END MX_GPIO_Init_1 */
  1024.  
  1025.   /* GPIO Ports Clock Enable */
  1026.   __HAL_RCC_GPIOC_CLK_ENABLE();
  1027.   __HAL_RCC_GPIOD_CLK_ENABLE();
  1028.   __HAL_RCC_GPIOA_CLK_ENABLE();
  1029.   __HAL_RCC_GPIOB_CLK_ENABLE();
  1030.  
  1031.   /*Configure GPIO pin Output Level */
  1032.   HAL_GPIO_WritePin(LED_Blink_GPIO_Port, LED_Blink_Pin, GPIO_PIN_RESET);
  1033.  
  1034.   /*Configure GPIO pin Output Level */
  1035.   HAL_GPIO_WritePin(GPIOB, SPI_CS_Clk_Pin|SPI_CS_D_Pin|ENA_AUX_5V_Pin, GPIO_PIN_RESET);
  1036.  
  1037.   /*Configure GPIO pin : LED_Blink_Pin */
  1038.   GPIO_InitStruct.Pin = LED_Blink_Pin;
  1039.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  1040.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  1041.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  1042.   HAL_GPIO_Init(LED_Blink_GPIO_Port, &GPIO_InitStruct);
  1043.  
  1044.   /*Configure GPIO pins : SPI_CS_Clk_Pin SPI_CS_D_Pin */
  1045.   GPIO_InitStruct.Pin = SPI_CS_Clk_Pin|SPI_CS_D_Pin;
  1046.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  1047.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  1048.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  1049.   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  1050.  
  1051.   /*Configure GPIO pin : STARTER_ON_Pin */
  1052.   GPIO_InitStruct.Pin = STARTER_ON_Pin;
  1053.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  1054.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  1055.   HAL_GPIO_Init(STARTER_ON_GPIO_Port, &GPIO_InitStruct);
  1056.  
  1057.   /*Configure GPIO pin : ENA_AUX_5V_Pin */
  1058.   GPIO_InitStruct.Pin = ENA_AUX_5V_Pin;
  1059.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  1060.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  1061.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  1062.   HAL_GPIO_Init(ENA_AUX_5V_GPIO_Port, &GPIO_InitStruct);
  1063.  
  1064. /* USER CODE BEGIN MX_GPIO_Init_2 */
  1065. /* USER CODE END MX_GPIO_Init_2 */
  1066. }
  1067.  
  1068. /* USER CODE BEGIN 4 */
  1069.  
  1070. /* USER CODE END 4 */
  1071.  
  1072. /**
  1073.   * @brief  This function is executed in case of error occurrence.
  1074.   * @retval None
  1075.   */
  1076. void Error_Handler(void)
  1077. {
  1078.   /* USER CODE BEGIN Error_Handler_Debug */
  1079.   /* User can add his own implementation to report the HAL error return state */
  1080.  
  1081.   /* USER CODE END Error_Handler_Debug */
  1082. }
  1083.  
  1084. #ifdef  USE_FULL_ASSERT
  1085. /**
  1086.   * @brief  Reports the name of the source file and the source line number
  1087.   *         where the assert_param error has occurred.
  1088.   * @param  file: pointer to the source file name
  1089.   * @param  line: assert_param error line source number
  1090.   * @retval None
  1091.   */
  1092. void assert_failed(uint8_t *file, uint32_t line)
  1093. {
  1094.   /* USER CODE BEGIN 6 */
  1095.   /* User can add his own implementation to report the file name and line number,
  1096.      tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  1097.   /* USER CODE END 6 */
  1098. }
  1099. #endif /* USE_FULL_ASSERT */
  1100.