Subversion Repositories EngineBay2

Rev

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