Subversion Repositories EngineBay2

Rev

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