Subversion Repositories EngineBay2

Rev

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