Subversion Repositories EngineBay2

Rev

Rev 26 | Rev 28 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /**
  2.   ******************************************************************************
  3.   * File Name          : main.c
  4.   * Description        : Main program body
  5.   ******************************************************************************
  6.   *
  7.   * COPYRIGHT(c) 2017 STMicroelectronics
  8.   *
  9.   * Redistribution and use in source and binary forms, with or without modification,
  10.   * are permitted provided that the following conditions are met:
  11.   *   1. Redistributions of source code must retain the above copyright notice,
  12.   *      this list of conditions and the following disclaimer.
  13.   *   2. Redistributions in binary form must reproduce the above copyright notice,
  14.   *      this list of conditions and the following disclaimer in the documentation
  15.   *      and/or other materials provided with the distribution.
  16.   *   3. Neither the name of STMicroelectronics nor the names of its contributors
  17.   *      may be used to endorse or promote products derived from this software
  18.   *      without specific prior written permission.
  19.   *
  20.   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  21.   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22.   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  23.   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  24.   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25.   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  26.   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  27.   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  28.   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29.   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30.   *
  31.   ******************************************************************************
  32.   */
  33. /* Includes ------------------------------------------------------------------*/
  34. #include "stm32l1xx_hal.h"
  35.  
  36. /* USER CODE BEGIN Includes */
  37. #include "serial.h"
  38. #include "plx.h"
  39. #include "misc.h"
  40. /* USER CODE END Includes */
  41.  
  42. /* Private variables ---------------------------------------------------------*/
  43. ADC_HandleTypeDef hadc;
  44. DMA_HandleTypeDef hdma_adc;
  45.  
  46. SPI_HandleTypeDef hspi1;
  47.  
  48. TIM_HandleTypeDef htim2;
  49. TIM_HandleTypeDef htim6;
  50.  
  51. UART_HandleTypeDef huart1;
  52. UART_HandleTypeDef huart2;
  53.  
  54. /* USER CODE BEGIN PV */
  55. /* Private variables ---------------------------------------------------------*/
  56.  
  57. // with a dwell angle of 45 degrees , 4 cylinders and a maximum RPM of 5000
  58. // freq = 5000/60 * 2 = 166Hz. Because the breaker might bounce , we accept the first pulse longer than 1/300 of a second as being a proper closure .
  59. // the TIM2 counter counts in 10uS increments,
  60. #define BREAKER_MIN (RPM_COUNT_RATE/300)
  61.  
  62. // wait for about 1 second to decide whether or not starter is on
  63.  
  64. #define STARTER_LIMIT 10
  65.  
  66. volatile char TimerFlag = 0;
  67.  
  68. volatile char NoSerialInCTR = 0; // Missing characters coming in on USART1
  69. volatile char NoSerialIn = 0;
  70.  
  71. // storage for ADC
  72. uint16_t ADC_Samples[6];
  73.  
  74. #define Scale 1024.0
  75. const float ADC_Scale = 3.3 / (Scale * 4096.0); // convert to a voltage
  76.  
  77. uint32_t FILT_Samples[6]; // filtered ADC samples * 1024
  78. // Rev counter processing from original RevCounter Project
  79. unsigned int RPM_Diff = 0;
  80. unsigned int RPM_Count_Latch = 0;
  81. // accumulators
  82. unsigned int RPM_Pulsecount = 0;
  83. unsigned int RPM_FilteredWidth = 0;
  84.  
  85. unsigned int Coded_RPM = 0;
  86. unsigned int Coded_CHT = 0;
  87.  
  88. uint32_t Power_CHT_Timer;
  89.  
  90. uint16_t Starter_Debounce = 0;
  91.  
  92. /* USER CODE END PV */
  93.  
  94. /* Private function prototypes -----------------------------------------------*/
  95. void SystemClock_Config(void);
  96. void Error_Handler(void);
  97. static void MX_GPIO_Init(void);
  98. static void MX_DMA_Init(void);
  99. static void MX_ADC_Init(void);
  100. static void MX_SPI1_Init(void);
  101. static void MX_TIM2_Init(void);
  102. static void MX_TIM6_Init(void);
  103. static void MX_USART2_UART_Init(void);
  104. static void MX_USART1_UART_Init(void);
  105.  
  106. /* USER CODE BEGIN PFP */
  107. /* Private function prototypes -----------------------------------------------*/
  108.  
  109. /* USER CODE END PFP */
  110.  
  111. /* USER CODE BEGIN 0 */
  112.  
  113. void plx_sendword(int x)
  114. {
  115.         PutCharSerial(&uc1, ((x) >> 6) & 0x3F);
  116.         PutCharSerial(&uc1, (x) & 0x3F);
  117. }
  118.  
  119. void init_ADC_filter()
  120. {
  121.         int i;
  122.         for (i = 0; i < 6; i++)
  123.         {
  124.                 FILT_Samples[i] = 0;
  125.         }
  126. }
  127.  
  128. void filter_ADC_samples()
  129. {
  130.         int i;
  131.         for (i = 0; i < 6; i++)
  132.         {
  133.                 FILT_Samples[i] += (ADC_Samples[i] * Scale - FILT_Samples[i]) / 2;
  134.         }
  135. }
  136.  
  137. void ProcessRPM(int instance)
  138. {
  139. // compute the timer values
  140. // snapshot timers
  141.         unsigned long RPM_Pulsewidth;
  142.         unsigned long RPM_Count_Val;
  143.         __disable_irq(); // copy the counter value
  144.         RPM_Count_Val = RPM_Count;
  145.         __enable_irq();
  146. // do calculations
  147. // if there is only one entry, cannot get difference
  148.         if (RPM_Count_Latch != RPM_Count_Val)
  149.         {
  150.                 while (1)
  151.                 {
  152.                         unsigned int base_time;
  153.                         unsigned int new_time;
  154.                         // if we are at N-1, stop.
  155.                         unsigned int next_count = RPM_Count_Latch + 1;
  156.                         if (next_count == RPM_SAMPLES)
  157.                         {
  158.                                 next_count = 0;
  159.                         }
  160.                         if (next_count == RPM_Count_Val)
  161.                         {
  162.                                 break;
  163.                         }
  164.                         base_time = RPM_Time[RPM_Count_Latch];
  165.                         new_time = RPM_Time[next_count];
  166.                         RPM_Count_Latch = next_count;
  167.                         if (new_time > base_time)
  168.                         {
  169.                                 RPM_Pulsewidth = new_time - base_time; // not wrapped
  170.                         }
  171.                         else
  172.                         {
  173.                                 RPM_Pulsewidth = new_time - base_time + 65536; // deal with wrapping
  174.                         }
  175.  
  176.                         RPM_Diff += RPM_Pulsewidth;
  177.                         // need to check if this is a long pulse. If it is, keep the answer
  178.                         if (RPM_Pulsewidth > BREAKER_MIN)
  179.                         {
  180.                                 RPM_Pulsecount++; // count one pulse
  181.                                 RPM_FilteredWidth += RPM_Diff; // add its width to the accumulator
  182.                                 RPM_Diff = 0; // reset accumulator of all the narrow widths
  183.                         }
  184.                 }
  185.  
  186.         }
  187.  
  188.         if (RPM_Pulsecount > 0)
  189.         {
  190.                 // now have time for N pulses in clocks
  191.                 // need to scale by 19.55: one unit is 19.55 RPM
  192.                 // 1Hz is 60 RPM
  193.                 float New_RPM = (30.0 / 19.55 * RPM_Pulsecount * RPM_COUNT_RATE)
  194.                                 / (RPM_FilteredWidth) + 0.5;
  195. // increase RPM filtering
  196.                 Coded_RPM += (New_RPM * Scale - Coded_RPM) / 8;
  197.  
  198. #if !defined MY_DEBUG
  199.                 // reset here unless we want to debug
  200.                 RPM_Pulsecount = 0;
  201.                 RPM_FilteredWidth = 0;
  202. #endif
  203.         }
  204.  
  205. // send the current RPM *calculation
  206.         plx_sendword(PLX_RPM);
  207.         PutCharSerial(&uc1, instance);
  208.         plx_sendword(Coded_RPM / Scale);
  209. }
  210.  
  211. // this uses a MAX6675 which is a simple 16 bit read
  212. // SPI is configured for 8 bits so I can use an OLED display if I need it
  213. // must wait > 0.22 seconds between conversion attempts as this is the measurement time
  214. //
  215.  
  216. FunctionalState CHT_Enable = ENABLE;
  217.  
  218. #define CORR 3
  219.  
  220. uint8_t CHT_Timer[2] =
  221. { 0, 0 }; // two temperature readings : from two sensors
  222.  
  223.  
  224. uint16_t CHT_Observations[2] =
  225. { 0, 0 };
  226.  
  227. // look for the trigger pin being high then low - the points
  228. // are opening, and skip the reading
  229.  
  230.  
  231. void ProcessCHT(int instance)
  232. {
  233.         uint8_t buffer[2];
  234.         if (instance > 2)
  235.                 return;
  236.         CHT_Timer[instance]++;
  237.  
  238.         static uint8_t prevCB;
  239.  
  240.         uint8_t readCB =
  241.         HAL_GPIO_ReadPin(CB_Pulse_GPIO_Port, CB_Pulse_Pin);
  242.  
  243.         if(!(prevCB == GPIO_PIN_SET && readCB ==
  244.                                  GPIO_PIN_RESET) )
  245.           {
  246.  
  247.         if ((CHT_Enable == ENABLE) && (CHT_Timer[instance] >= 4)) // every 300 milliseconds
  248.         {
  249.  
  250.                 CHT_Timer[instance] = 0;
  251.  
  252.                 uint16_t Pin = (instance == 0) ? SPI_NS_Temp_Pin : SPI_NS_Temp2_Pin;
  253.  
  254.                 HAL_GPIO_WritePin(SPI_NS_Temp_GPIO_Port, Pin, GPIO_PIN_RESET);
  255.  
  256.                 HAL_SPI_Receive(&hspi1, buffer, 2, 2);
  257.  
  258.                 HAL_GPIO_WritePin(SPI_NS_Temp_GPIO_Port, Pin, GPIO_PIN_SET);
  259.  
  260.                 uint16_t obs = (buffer[0] << 8) | buffer[1];
  261.  
  262.                 // good observation if the status bit is clear, and the reading is less than 1023
  263.  
  264.                 uint16_t temp_c = obs>>5;
  265.  
  266.                 uint8_t good = ((obs & 7) == 0) && (temp_c > 0) && (temp_c < 250);
  267.  
  268.                 if (good)
  269.                 {
  270.                         CHT_Observations[instance]=temp_c;
  271.  
  272.                 }
  273.  
  274.         }
  275.           }
  276.  
  277.         prevCB= readCB;
  278.         plx_sendword(PLX_X_CHT);
  279.         PutCharSerial(&uc1, instance);
  280.         plx_sendword(CHT_Observations[instance]);
  281.  
  282. }
  283.  
  284. void EnableCHT(FunctionalState state)
  285.  
  286. {
  287.         GPIO_InitTypeDef GPIO_InitStruct;
  288.  
  289.         CHT_Enable = state;
  290.  
  291.  
  292.         /* enable SPI in live mode : assume it and its GPIOs are already initialised in SPI mode */
  293.         if (state == ENABLE)
  294.         {
  295.                 HAL_GPIO_WritePin(ENA_AUX_5V_GPIO_Port, ENA_AUX_5V_Pin, GPIO_PIN_SET );
  296.                 HAL_GPIO_WritePin(SPI_NS_Temp_GPIO_Port, SPI_NS_Temp_Pin, GPIO_PIN_SET);
  297.                 HAL_GPIO_WritePin(SPI_NS_Temp2_GPIO_Port, SPI_NS_Temp2_Pin,
  298.                                 GPIO_PIN_SET);
  299.  
  300.                 /* put the SPI pins back into SPI AF mode */
  301.                 GPIO_InitStruct.Pin = SPI1_MOSI_Pin | SPI1_MISO_Pin | SPI1_SCK_Pin;
  302.                 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  303.                 GPIO_InitStruct.Pull = GPIO_NOPULL;
  304.                 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  305.                 GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
  306.                 HAL_GPIO_Init(SPI1_SCK_GPIO_Port, &GPIO_InitStruct);
  307.  
  308.         }
  309.         else
  310.         {
  311.                 /*  Power down the SPI interface taking signals all low */
  312.                 HAL_GPIO_WritePin(ENA_AUX_5V_GPIO_Port, ENA_AUX_5V_Pin, GPIO_PIN_RESET );
  313.                 HAL_GPIO_WritePin(SPI_NS_Temp_GPIO_Port, SPI_NS_Temp_Pin,
  314.                                 GPIO_PIN_RESET);
  315.                 HAL_GPIO_WritePin(SPI_NS_Temp2_GPIO_Port, SPI_NS_Temp2_Pin,
  316.                                 GPIO_PIN_RESET);
  317.  
  318.                 HAL_GPIO_WritePin(SPI1_SCK_GPIO_Port,
  319.                                 SPI1_MOSI_Pin | SPI1_MISO_Pin | SPI1_SCK_Pin, GPIO_PIN_RESET);
  320.  
  321.                 /* put the SPI pins back into GPIO mode */
  322.                 GPIO_InitStruct.Pin = SPI1_MOSI_Pin | SPI1_MISO_Pin | SPI1_SCK_Pin;
  323.                 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  324.                 GPIO_InitStruct.Pull = GPIO_NOPULL;
  325.                 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  326.                 HAL_GPIO_Init(SPI1_SCK_GPIO_Port, &GPIO_InitStruct);
  327.  
  328.         }
  329.  
  330. }
  331.  
  332. // 1023 is 20.00 volts.
  333. void ProcessBatteryVoltage(int instance)
  334. {
  335.         float reading = FILT_Samples[instance] * ADC_Scale;
  336.         reading = reading * 7.8125; // real voltage
  337.         reading = reading * 51.15; // 1023/20
  338.  
  339.         plx_sendword(PLX_Volts);
  340.         PutCharSerial(&uc1, instance);
  341.         plx_sendword((uint16_t) reading);
  342.  
  343. }
  344.  
  345. /****!
  346.  * @brief this reads the reference voltage within the STM32L151
  347.  * Powers up reference voltage and temperature sensor, waits 3mS  and takes reading
  348.  * Requires that the ADC be powered up
  349.  */
  350.  
  351. uint32_t ADC_VREF_MV = 3300;           // 3.300V typical
  352. const uint16_t STM32REF_MV = 1224;           // 1.224V typical
  353.  
  354. void CalibrateADC(void)
  355. {
  356.         uint32_t adc_val = FILT_Samples[5];       // as set up in device config
  357.         ADC_VREF_MV = (STM32REF_MV * 4096) / adc_val;
  358. }
  359.  
  360. void ProcessCPUTemperature(int instance)
  361. {
  362.         int32_t temp_val;
  363.  
  364.         uint16_t TS_CAL30 = *(uint16_t *) (0x1FF8007AUL); /* ADC reading for temperature sensor at 30 degrees C with Vref = 3000mV */
  365.         uint16_t TS_CAL110 = *(uint16_t *) (0x1FF8007EUL); /* ADC reading for temperature sensor at 110 degrees C with Vref = 3000mV */
  366.         /* get the ADC reading corresponding to ADC channel 16 after turning on the ADC */
  367.  
  368.         temp_val = FILT_Samples[5];
  369.  
  370.         /* renormalise temperature value to account for different ADC Vref  : normalise to that which we would get for a 3000mV reference */
  371.         temp_val = temp_val * ADC_VREF_MV / (Scale * 3000UL);
  372.  
  373.         int32_t result = 800 * ((int32_t) temp_val - TS_CAL30);
  374.         result = result / (TS_CAL110 - TS_CAL30) + 300;
  375.  
  376.         if (result < 0)
  377.         {
  378.                 result = 0;
  379.         }
  380.         plx_sendword(PLX_FluidTemp);
  381.         PutCharSerial(&uc1, instance);
  382.         plx_sendword(result / 10);
  383.  
  384. }
  385.  
  386. // the MAP sensor is giving us a reading of
  387. // 4.6 volts for 1019mB or 2.27 volts at the ADC input (resistive divider by 2.016)
  388. // I believe the sensor reads  4.5V at 1000kPa and 0.5V at  0kPa
  389. // Calibration is a bit off
  390. // Real   Displayed
  391. // 989    968
  392. // 994.1    986
  393. // 992.3  984
  394.  
  395. void ProcessMAP(int instance)
  396. {
  397. // Using ADC_Samples[3] as the MAP input
  398.         float reading = FILT_Samples[3] * ADC_Scale;
  399.         reading = reading * 2.016;      // real voltage
  400.         // values computed from slope / intercept of map.ods
  401.         //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
  402.         // using a pressure gauge.
  403.         reading = (reading) * 150 + 326;
  404.  
  405.         plx_sendword(PLX_MAP);
  406.         PutCharSerial(&uc1, instance);
  407.         plx_sendword((uint16_t) reading);
  408.  
  409. }
  410.  
  411. // the Oil pressi sensor is giving us a reading of
  412. // 4.5 volts for 100 PSI or  2.25 volts at the ADC input (resistive divider by 2.016)
  413. // I believe the sensor reads  4.5V at 100PSI and 0.5V at  0PSI
  414. // an observation of 1024 is 200PSI, so observation of 512 is 100 PSI.
  415.  
  416. void ProcessOilPress(int instance)
  417. {
  418. // Using ADC_Samples[2] as the MAP input
  419.         float reading = FILT_Samples[2] * ADC_Scale;
  420.         reading = reading * 2.00; // real voltage
  421.         reading = (reading - 0.5) * 512 / 4;  // this is 1023 * 100/200
  422.  
  423.         plx_sendword(PLX_FluidPressure);
  424.         PutCharSerial(&uc1, instance);
  425.         plx_sendword((uint16_t) reading);
  426.  
  427. }
  428.  
  429. void ProcessTiming(int instance)
  430. {
  431.         plx_sendword(PLX_Timing);
  432.         PutCharSerial(&uc1, instance);
  433.         plx_sendword(64 - 15); // make it negative
  434. }
  435.  
  436. /* USER CODE END 0 */
  437.  
  438. int main(void)
  439. {
  440.  
  441.   /* USER CODE BEGIN 1 */
  442.  
  443.   /* USER CODE END 1 */
  444.  
  445.   /* MCU Configuration----------------------------------------------------------*/
  446.  
  447.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  448.   HAL_Init();
  449.  
  450.   /* Configure the system clock */
  451.   SystemClock_Config();
  452.  
  453.   /* Initialize all configured peripherals */
  454.   MX_GPIO_Init();
  455.   MX_DMA_Init();
  456.   MX_ADC_Init();
  457.   MX_SPI1_Init();
  458.   MX_TIM2_Init();
  459.   MX_TIM6_Init();
  460.   MX_USART2_UART_Init();
  461.   MX_USART1_UART_Init();
  462.  
  463.   /* USER CODE BEGIN 2 */
  464.         HAL_MspInit();
  465.  
  466. // Not using HAL USART code
  467.         __HAL_RCC_USART1_CLK_ENABLE()
  468.         ; // PLX comms port
  469.         __HAL_RCC_USART2_CLK_ENABLE()
  470.         ;  // Debug comms port
  471.         /* setup the USART control blocks */
  472.         init_usart_ctl(&uc1, huart1.Instance);
  473.         init_usart_ctl(&uc2, huart2.Instance);
  474.  
  475.         EnableSerialRxInterrupt(&uc1);
  476.         EnableSerialRxInterrupt(&uc2);
  477.  
  478.         HAL_SPI_MspInit(&hspi1);
  479.  
  480.         HAL_ADC_MspInit(&hadc);
  481.  
  482.         HAL_ADC_Start_DMA(&hadc, ADC_Samples, 6);
  483.  
  484.         HAL_ADC_Start_IT(&hadc);
  485.  
  486.         HAL_TIM_Base_MspInit(&htim6);
  487.         HAL_TIM_Base_Start_IT(&htim6);
  488.  
  489. // initialise all the STMCubeMX stuff
  490.         HAL_TIM_Base_MspInit(&htim2);
  491. // Start the counter
  492.         HAL_TIM_Base_Start(&htim2);
  493. // Start the input capture and the interrupt
  494.         HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
  495.  
  496.         init_ADC_filter();
  497.  
  498.         uint32_t Ticks = HAL_GetTick() + 100;
  499.         int CalCounter = 0;
  500.  
  501.         Power_CHT_Timer = HAL_GetTick() + 1000; /* wait 10 seconds before powering up the CHT sensor */
  502.  
  503.  
  504.  
  505.  
  506.   /* USER CODE END 2 */
  507.  
  508.   /* Infinite loop */
  509.   /* USER CODE BEGIN WHILE */
  510.         while (1)
  511.         {
  512.   /* USER CODE END WHILE */
  513.  
  514.   /* USER CODE BEGIN 3 */
  515.  
  516.                 if (HAL_GetTick() > Ticks)
  517.                 {
  518.                         Ticks += 100;
  519.                         filter_ADC_samples();
  520.                         // delay to calibrate ADC
  521.                         if (CalCounter < 1000)
  522.                         {
  523.                                 CalCounter += 100;
  524.                         }
  525.  
  526.                         if (CalCounter == 900)
  527.                         {
  528.                                 CalibrateADC();
  529.                         }
  530.                 }
  531.                 /* when the starter motor is on then power down the CHT sensors as they seem to fail */
  532.  
  533.                 if (HAL_GPIO_ReadPin(STARTER_ON_GPIO_Port, STARTER_ON_Pin)
  534.                                         == GPIO_PIN_RESET )
  535.                 {
  536.                         if(Starter_Debounce < STARTER_LIMIT)
  537.                         {
  538.                                 Starter_Debounce++;
  539.                         }
  540.                 }
  541.                 else
  542.                 {
  543.                         if(Starter_Debounce > 0)
  544.                         {
  545.                                 Starter_Debounce --;
  546.                         }
  547.                 }
  548.  
  549.                 if (Starter_Debounce == STARTER_LIMIT)
  550.                 {
  551.                         EnableCHT(DISABLE);
  552.                         Power_CHT_Timer = HAL_GetTick() + 1000;
  553.                 }
  554.                 else
  555.                 /* if the Power_CHT_Timer is set then wait for it to timeout, then power up CHT */
  556.                 {
  557.                         if ((Power_CHT_Timer > 0) && (HAL_GetTick() > Power_CHT_Timer))
  558.                         {
  559.                                 EnableCHT(ENABLE);
  560.                                 Power_CHT_Timer = 0;
  561.                         }
  562.                 }
  563.  
  564.                 // check to see if we have any incoming data, copy and append if so, if no data then create our own frames.
  565.                 int c;
  566.                 char send = 0;
  567.  
  568.                 // poll the  input for a stop bit or timeout
  569.                 if (PollSerial(&uc1))
  570.                 {
  571.                         c = GetCharSerial(&uc1);
  572.                         if (c != PLX_Stop)
  573.                         {
  574.                                 PutCharSerial(&uc1, c); // echo all but the stop bit
  575.                         }
  576.                         else
  577.                         { // must be a stop character
  578.                                 send = 1; // start our sending process.
  579.                         }
  580.                 }
  581.  
  582.                 // sort out auto-sending
  583.                 if (TimerFlag)
  584.                 {
  585.                         TimerFlag = 0;
  586.                         if (NoSerialIn)
  587.                         {
  588.                                 PutCharSerial(&uc1, PLX_Start);
  589.                                 send = 1;
  590.                         }
  591.                 }
  592.                 if (send)
  593.                 {
  594.                         send = 0;
  595.  
  596.                         uint16_t val;
  597.                         val = __HAL_TIM_GET_COMPARE(&htim2,TIM_CHANNEL_1);
  598.                         PutCharSerial(&uc2, (val & 31) + 32);
  599.  
  600.                         // send the observations
  601.                         ProcessRPM(0);
  602.                         ProcessCHT(0);
  603.                         ProcessCHT(1);
  604.                         ProcessBatteryVoltage(0); // Batt 1
  605.                         ProcessBatteryVoltage(1); // Batt 2
  606.                         ProcessCPUTemperature(0); //  built in temperature sensor
  607.  
  608.                         ProcessMAP(0);
  609.                         ProcessOilPress(0);
  610.  
  611.                         PutCharSerial(&uc1, PLX_Stop);
  612.                 }
  613.         }
  614.   /* USER CODE END 3 */
  615.  
  616. }
  617.  
  618. /** System Clock Configuration
  619. */
  620. void SystemClock_Config(void)
  621. {
  622.  
  623.   RCC_OscInitTypeDef RCC_OscInitStruct;
  624.   RCC_ClkInitTypeDef RCC_ClkInitStruct;
  625.  
  626.   __HAL_RCC_PWR_CLK_ENABLE();
  627.  
  628.   __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  629.  
  630.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  631.   RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  632.   RCC_OscInitStruct.HSICalibrationValue = 16;
  633.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  634.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  635.   RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL6;
  636.   RCC_OscInitStruct.PLL.PLLDIV = RCC_PLL_DIV3;
  637.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  638.   {
  639.     Error_Handler();
  640.   }
  641.  
  642.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
  643.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  644.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  645.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  646.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  647.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
  648.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
  649.   {
  650.     Error_Handler();
  651.   }
  652.  
  653.   HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
  654.  
  655.   HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
  656.  
  657.   /* SysTick_IRQn interrupt configuration */
  658.   HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
  659. }
  660.  
  661. /* ADC init function */
  662. static void MX_ADC_Init(void)
  663. {
  664.  
  665.   ADC_ChannelConfTypeDef sConfig;
  666.  
  667.     /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
  668.     */
  669.   hadc.Instance = ADC1;
  670.   hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
  671.   hadc.Init.Resolution = ADC_RESOLUTION_12B;
  672.   hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  673.   hadc.Init.ScanConvMode = ADC_SCAN_ENABLE;
  674.   hadc.Init.EOCSelection = ADC_EOC_SEQ_CONV;
  675.   hadc.Init.LowPowerAutoWait = ADC_AUTOWAIT_DISABLE;
  676.   hadc.Init.LowPowerAutoPowerOff = ADC_AUTOPOWEROFF_DISABLE;
  677.   hadc.Init.ChannelsBank = ADC_CHANNELS_BANK_A;
  678.   hadc.Init.ContinuousConvMode = DISABLE;
  679.   hadc.Init.NbrOfConversion = 6;
  680.   hadc.Init.DiscontinuousConvMode = DISABLE;
  681.   hadc.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T6_TRGO;
  682.   hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
  683.   hadc.Init.DMAContinuousRequests = ENABLE;
  684.   if (HAL_ADC_Init(&hadc) != HAL_OK)
  685.   {
  686.     Error_Handler();
  687.   }
  688.  
  689.     /**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  690.     */
  691.   sConfig.Channel = ADC_CHANNEL_10;
  692.   sConfig.Rank = 1;
  693.   sConfig.SamplingTime = ADC_SAMPLETIME_384CYCLES;
  694.   if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  695.   {
  696.     Error_Handler();
  697.   }
  698.  
  699.     /**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  700.     */
  701.   sConfig.Channel = ADC_CHANNEL_11;
  702.   sConfig.Rank = 2;
  703.   if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  704.   {
  705.     Error_Handler();
  706.   }
  707.  
  708.     /**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  709.     */
  710.   sConfig.Channel = ADC_CHANNEL_12;
  711.   sConfig.Rank = 3;
  712.   if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  713.   {
  714.     Error_Handler();
  715.   }
  716.  
  717.     /**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  718.     */
  719.   sConfig.Channel = ADC_CHANNEL_13;
  720.   sConfig.Rank = 4;
  721.   if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  722.   {
  723.     Error_Handler();
  724.   }
  725.  
  726.     /**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  727.     */
  728.   sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
  729.   sConfig.Rank = 5;
  730.   if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  731.   {
  732.     Error_Handler();
  733.   }
  734.  
  735.     /**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  736.     */
  737.   sConfig.Channel = ADC_CHANNEL_VREFINT;
  738.   sConfig.Rank = 6;
  739.   if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  740.   {
  741.     Error_Handler();
  742.   }
  743.  
  744. }
  745.  
  746. /* SPI1 init function */
  747. static void MX_SPI1_Init(void)
  748. {
  749.  
  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_64;
  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.  
  767. }
  768.  
  769. /* TIM2 init function */
  770. static void MX_TIM2_Init(void)
  771. {
  772.  
  773.   TIM_ClockConfigTypeDef sClockSourceConfig;
  774.   TIM_MasterConfigTypeDef sMasterConfig;
  775.   TIM_IC_InitTypeDef sConfigIC;
  776.  
  777.   htim2.Instance = TIM2;
  778.   htim2.Init.Prescaler = 320;
  779.   htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  780.   htim2.Init.Period = 65535;
  781.   htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  782.   if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  783.   {
  784.     Error_Handler();
  785.   }
  786.  
  787.   sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  788.   if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  789.   {
  790.     Error_Handler();
  791.   }
  792.  
  793.   if (HAL_TIM_IC_Init(&htim2) != HAL_OK)
  794.   {
  795.     Error_Handler();
  796.   }
  797.  
  798.   sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
  799.   sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  800.   if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  801.   {
  802.     Error_Handler();
  803.   }
  804.  
  805.   sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
  806.   sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
  807.   sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
  808.   sConfigIC.ICFilter = 0;
  809.   if (HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_1) != HAL_OK)
  810.   {
  811.     Error_Handler();
  812.   }
  813.  
  814. }
  815.  
  816. /* TIM6 init function */
  817. static void MX_TIM6_Init(void)
  818. {
  819.  
  820.   TIM_MasterConfigTypeDef sMasterConfig;
  821.  
  822.   htim6.Instance = TIM6;
  823.   htim6.Init.Prescaler = 320;
  824.   htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
  825.   htim6.Init.Period = 9999;
  826.   if (HAL_TIM_Base_Init(&htim6) != HAL_OK)
  827.   {
  828.     Error_Handler();
  829.   }
  830.  
  831.   sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
  832.   sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  833.   if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK)
  834.   {
  835.     Error_Handler();
  836.   }
  837.  
  838. }
  839.  
  840. /* USART1 init function */
  841. static void MX_USART1_UART_Init(void)
  842. {
  843.  
  844.   huart1.Instance = USART1;
  845.   huart1.Init.BaudRate = 19200;
  846.   huart1.Init.WordLength = UART_WORDLENGTH_8B;
  847.   huart1.Init.StopBits = UART_STOPBITS_1;
  848.   huart1.Init.Parity = UART_PARITY_NONE;
  849.   huart1.Init.Mode = UART_MODE_TX_RX;
  850.   huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  851.   huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  852.   if (HAL_UART_Init(&huart1) != HAL_OK)
  853.   {
  854.     Error_Handler();
  855.   }
  856.  
  857. }
  858.  
  859. /* USART2 init function */
  860. static void MX_USART2_UART_Init(void)
  861. {
  862.  
  863.   huart2.Instance = USART2;
  864.   huart2.Init.BaudRate = 115200;
  865.   huart2.Init.WordLength = UART_WORDLENGTH_8B;
  866.   huart2.Init.StopBits = UART_STOPBITS_1;
  867.   huart2.Init.Parity = UART_PARITY_NONE;
  868.   huart2.Init.Mode = UART_MODE_TX_RX;
  869.   huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  870.   huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  871.   if (HAL_UART_Init(&huart2) != HAL_OK)
  872.   {
  873.     Error_Handler();
  874.   }
  875.  
  876. }
  877.  
  878. /**
  879.   * Enable DMA controller clock
  880.   */
  881. static void MX_DMA_Init(void)
  882. {
  883.   /* DMA controller clock enable */
  884.   __HAL_RCC_DMA1_CLK_ENABLE();
  885.  
  886.   /* DMA interrupt init */
  887.   /* DMA1_Channel1_IRQn interrupt configuration */
  888.   HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
  889.   HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
  890.  
  891. }
  892.  
  893. /** Configure pins as
  894.         * Analog
  895.         * Input
  896.         * Output
  897.         * EVENT_OUT
  898.         * EXTI
  899.         * Free pins are configured automatically as Analog (this feature is enabled through
  900.         * the Code Generation settings)
  901. */
  902. static void MX_GPIO_Init(void)
  903. {
  904.  
  905.   GPIO_InitTypeDef GPIO_InitStruct;
  906.  
  907.   /* GPIO Ports Clock Enable */
  908.   __HAL_RCC_GPIOC_CLK_ENABLE();
  909.   __HAL_RCC_GPIOH_CLK_ENABLE();
  910.   __HAL_RCC_GPIOA_CLK_ENABLE();
  911.   __HAL_RCC_GPIOB_CLK_ENABLE();
  912.   __HAL_RCC_GPIOD_CLK_ENABLE();
  913.  
  914.   /*Configure GPIO pins : PC13 PC14 PC15 PC6
  915.                            PC7 PC8 PC9 PC11
  916.                            PC12 */
  917.   GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_6
  918.                           |GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_11
  919.                           |GPIO_PIN_12;
  920.   GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  921.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  922.   HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
  923.  
  924.   /*Configure GPIO pins : PH0 PH1 */
  925.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
  926.   GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  927.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  928.   HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
  929.  
  930.   /*Configure GPIO pins : PA0 PA1 PA8 PA11
  931.                            PA12 */
  932.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_8|GPIO_PIN_11
  933.                           |GPIO_PIN_12;
  934.   GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  935.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  936.   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  937.  
  938.   /*Configure GPIO pin : LED_Blink_Pin */
  939.   GPIO_InitStruct.Pin = LED_Blink_Pin;
  940.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  941.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  942.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  943.   HAL_GPIO_Init(LED_Blink_GPIO_Port, &GPIO_InitStruct);
  944.  
  945.   /*Configure GPIO pins : SPI_NSS1_Pin SPI1CD_Pin */
  946.   GPIO_InitStruct.Pin = SPI_NSS1_Pin|SPI1CD_Pin;
  947.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  948.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  949.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  950.   HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
  951.  
  952.   /*Configure GPIO pins : SPI_RESET_Pin SPI_NS_Temp_Pin SPI_NS_Temp2_Pin ENA_AUX_5V_Pin */
  953.   GPIO_InitStruct.Pin = SPI_RESET_Pin|SPI_NS_Temp_Pin|SPI_NS_Temp2_Pin|ENA_AUX_5V_Pin;
  954.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  955.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  956.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  957.   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  958.  
  959.   /*Configure GPIO pins : PB11 PB12 PB13 PB14
  960.                            PB15 PB3 PB4 PB5
  961.                            PB6 PB7 PB8 PB9 */
  962.   GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14
  963.                           |GPIO_PIN_15|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5
  964.                           |GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9;
  965.   GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  966.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  967.   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  968.  
  969.   /*Configure GPIO pin : STARTER_ON_Pin */
  970.   GPIO_InitStruct.Pin = STARTER_ON_Pin;
  971.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  972.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  973.   HAL_GPIO_Init(STARTER_ON_GPIO_Port, &GPIO_InitStruct);
  974.  
  975.   /*Configure GPIO pin : PD2 */
  976.   GPIO_InitStruct.Pin = GPIO_PIN_2;
  977.   GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  978.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  979.   HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
  980.  
  981.   /*Configure GPIO pin Output Level */
  982.   HAL_GPIO_WritePin(LED_Blink_GPIO_Port, LED_Blink_Pin, GPIO_PIN_RESET);
  983.  
  984.   /*Configure GPIO pin Output Level */
  985.   HAL_GPIO_WritePin(SPI_NSS1_GPIO_Port, SPI_NSS1_Pin, GPIO_PIN_SET);
  986.  
  987.   /*Configure GPIO pin Output Level */
  988.   HAL_GPIO_WritePin(SPI1CD_GPIO_Port, SPI1CD_Pin, GPIO_PIN_RESET);
  989.  
  990.   /*Configure GPIO pin Output Level */
  991.   HAL_GPIO_WritePin(GPIOB, SPI_RESET_Pin|SPI_NS_Temp2_Pin|ENA_AUX_5V_Pin, GPIO_PIN_RESET);
  992.  
  993.   /*Configure GPIO pin Output Level */
  994.   HAL_GPIO_WritePin(SPI_NS_Temp_GPIO_Port, SPI_NS_Temp_Pin, GPIO_PIN_SET);
  995.  
  996. }
  997.  
  998. /* USER CODE BEGIN 4 */
  999.  
  1000. /* USER CODE END 4 */
  1001.  
  1002. /**
  1003.   * @brief  This function is executed in case of error occurrence.
  1004.   * @param  None
  1005.   * @retval None
  1006.   */
  1007. void Error_Handler(void)
  1008. {
  1009.   /* USER CODE BEGIN Error_Handler */
  1010.         /* User can add his own implementation to report the HAL error return state */
  1011.         while (1)
  1012.         {
  1013.         }
  1014.   /* USER CODE END Error_Handler */
  1015. }
  1016.  
  1017. #ifdef USE_FULL_ASSERT
  1018.  
  1019. /**
  1020.    * @brief Reports the name of the source file and the source line number
  1021.    * where the assert_param error has occurred.
  1022.    * @param file: pointer to the source file name
  1023.    * @param line: assert_param error line source number
  1024.    * @retval None
  1025.    */
  1026. void assert_failed(uint8_t* file, uint32_t line)
  1027. {
  1028.   /* USER CODE BEGIN 6 */
  1029.         /* User can add his own implementation to report the file name and line number,
  1030.          ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  1031.   /* USER CODE END 6 */
  1032.  
  1033. }
  1034.  
  1035. #endif
  1036.  
  1037. /**
  1038.   * @}
  1039.   */
  1040.  
  1041. /**
  1042.   * @}
  1043. */
  1044.  
  1045. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
  1046.