Subversion Repositories EngineBay2

Rev

Rev 25 | Rev 27 | 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.         plx_sendword(PLX_MAP);
  403.         PutCharSerial(&uc1, instance);
  404.         plx_sendword((uint16_t) reading);
  405.  
  406. }
  407.  
  408. // the Oil pressi sensor is giving us a reading of
  409. // 4.5 volts for 100 PSI or  2.25 volts at the ADC input (resistive divider by 2.016)
  410. // I believe the sensor reads  4.5V at 100PSI and 0.5V at  0PSI
  411. // an observation of 1024 is 200PSI, so observation of 512 is 100 PSI.
  412.  
  413. void ProcessOilPress(int instance)
  414. {
  415. // Using ADC_Samples[2] as the MAP input
  416.         float reading = FILT_Samples[2] * ADC_Scale;
  417.         reading = reading * 2.00; // real voltage
  418.         reading = (reading - 0.5) * 512 / 4;  // this is 1023 * 100/200
  419.  
  420.         plx_sendword(PLX_FluidPressure);
  421.         PutCharSerial(&uc1, instance);
  422.         plx_sendword((uint16_t) reading);
  423.  
  424. }
  425.  
  426. void ProcessTiming(int instance)
  427. {
  428.         plx_sendword(PLX_Timing);
  429.         PutCharSerial(&uc1, instance);
  430.         plx_sendword(64 - 15); // make it negative
  431. }
  432.  
  433. /* USER CODE END 0 */
  434.  
  435. int main(void)
  436. {
  437.  
  438.   /* USER CODE BEGIN 1 */
  439.  
  440.   /* USER CODE END 1 */
  441.  
  442.   /* MCU Configuration----------------------------------------------------------*/
  443.  
  444.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  445.   HAL_Init();
  446.  
  447.   /* Configure the system clock */
  448.   SystemClock_Config();
  449.  
  450.   /* Initialize all configured peripherals */
  451.   MX_GPIO_Init();
  452.   MX_DMA_Init();
  453.   MX_ADC_Init();
  454.   MX_SPI1_Init();
  455.   MX_TIM2_Init();
  456.   MX_TIM6_Init();
  457.   MX_USART2_UART_Init();
  458.   MX_USART1_UART_Init();
  459.  
  460.   /* USER CODE BEGIN 2 */
  461.         HAL_MspInit();
  462.  
  463. // Not using HAL USART code
  464.         __HAL_RCC_USART1_CLK_ENABLE()
  465.         ; // PLX comms port
  466.         __HAL_RCC_USART2_CLK_ENABLE()
  467.         ;  // Debug comms port
  468.         /* setup the USART control blocks */
  469.         init_usart_ctl(&uc1, huart1.Instance);
  470.         init_usart_ctl(&uc2, huart2.Instance);
  471.  
  472.         EnableSerialRxInterrupt(&uc1);
  473.         EnableSerialRxInterrupt(&uc2);
  474.  
  475.         HAL_SPI_MspInit(&hspi1);
  476.  
  477.         HAL_ADC_MspInit(&hadc);
  478.  
  479.         HAL_ADC_Start_DMA(&hadc, ADC_Samples, 6);
  480.  
  481.         HAL_ADC_Start_IT(&hadc);
  482.  
  483.         HAL_TIM_Base_MspInit(&htim6);
  484.         HAL_TIM_Base_Start_IT(&htim6);
  485.  
  486. // initialise all the STMCubeMX stuff
  487.         HAL_TIM_Base_MspInit(&htim2);
  488. // Start the counter
  489.         HAL_TIM_Base_Start(&htim2);
  490. // Start the input capture and the interrupt
  491.         HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
  492.  
  493.         init_ADC_filter();
  494.  
  495.         uint32_t Ticks = HAL_GetTick() + 100;
  496.         int CalCounter = 0;
  497.  
  498.         Power_CHT_Timer = HAL_GetTick() + 1000; /* wait 10 seconds before powering up the CHT sensor */
  499.  
  500.  
  501.  
  502.  
  503.   /* USER CODE END 2 */
  504.  
  505.   /* Infinite loop */
  506.   /* USER CODE BEGIN WHILE */
  507.         while (1)
  508.         {
  509.   /* USER CODE END WHILE */
  510.  
  511.   /* USER CODE BEGIN 3 */
  512.  
  513.                 if (HAL_GetTick() > Ticks)
  514.                 {
  515.                         Ticks += 100;
  516.                         filter_ADC_samples();
  517.                         // delay to calibrate ADC
  518.                         if (CalCounter < 1000)
  519.                         {
  520.                                 CalCounter += 100;
  521.                         }
  522.  
  523.                         if (CalCounter == 900)
  524.                         {
  525.                                 CalibrateADC();
  526.                         }
  527.                 }
  528.                 /* when the starter motor is on then power down the CHT sensors as they seem to fail */
  529.  
  530.                 if (HAL_GPIO_ReadPin(STARTER_ON_GPIO_Port, STARTER_ON_Pin)
  531.                                         == GPIO_PIN_RESET )
  532.                 {
  533.                         if(Starter_Debounce < STARTER_LIMIT)
  534.                         {
  535.                                 Starter_Debounce++;
  536.                         }
  537.                 }
  538.                 else
  539.                 {
  540.                         if(Starter_Debounce > 0)
  541.                         {
  542.                                 Starter_Debounce --;
  543.                         }
  544.                 }
  545.  
  546.                 if (Starter_Debounce == STARTER_LIMIT)
  547.                 {
  548.                         EnableCHT(DISABLE);
  549.                         Power_CHT_Timer = HAL_GetTick() + 1000;
  550.                 }
  551.                 else
  552.                 /* if the Power_CHT_Timer is set then wait for it to timeout, then power up CHT */
  553.                 {
  554.                         if ((Power_CHT_Timer > 0) && (HAL_GetTick() > Power_CHT_Timer))
  555.                         {
  556.                                 EnableCHT(ENABLE);
  557.                                 Power_CHT_Timer = 0;
  558.                         }
  559.                 }
  560.  
  561.                 // check to see if we have any incoming data, copy and append if so, if no data then create our own frames.
  562.                 int c;
  563.                 char send = 0;
  564.  
  565.                 // poll the  input for a stop bit or timeout
  566.                 if (PollSerial(&uc1))
  567.                 {
  568.                         c = GetCharSerial(&uc1);
  569.                         if (c != PLX_Stop)
  570.                         {
  571.                                 PutCharSerial(&uc1, c); // echo all but the stop bit
  572.                         }
  573.                         else
  574.                         { // must be a stop character
  575.                                 send = 1; // start our sending process.
  576.                         }
  577.                 }
  578.  
  579.                 // sort out auto-sending
  580.                 if (TimerFlag)
  581.                 {
  582.                         TimerFlag = 0;
  583.                         if (NoSerialIn)
  584.                         {
  585.                                 PutCharSerial(&uc1, PLX_Start);
  586.                                 send = 1;
  587.                         }
  588.                 }
  589.                 if (send)
  590.                 {
  591.                         send = 0;
  592.  
  593.                         uint16_t val;
  594.                         val = __HAL_TIM_GET_COMPARE(&htim2,TIM_CHANNEL_1);
  595.                         PutCharSerial(&uc2, (val & 31) + 32);
  596.  
  597.                         // send the observations
  598.                         ProcessRPM(0);
  599.                         ProcessCHT(0);
  600.                         ProcessCHT(1);
  601.                         ProcessBatteryVoltage(0); // Batt 1
  602.                         ProcessBatteryVoltage(1); // Batt 2
  603.                         ProcessCPUTemperature(0); //  built in temperature sensor
  604.  
  605.                         ProcessMAP(0);
  606.                         ProcessOilPress(0);
  607.  
  608.                         PutCharSerial(&uc1, PLX_Stop);
  609.                 }
  610.         }
  611.   /* USER CODE END 3 */
  612.  
  613. }
  614.  
  615. /** System Clock Configuration
  616. */
  617. void SystemClock_Config(void)
  618. {
  619.  
  620.   RCC_OscInitTypeDef RCC_OscInitStruct;
  621.   RCC_ClkInitTypeDef RCC_ClkInitStruct;
  622.  
  623.   __HAL_RCC_PWR_CLK_ENABLE();
  624.  
  625.   __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  626.  
  627.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  628.   RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  629.   RCC_OscInitStruct.HSICalibrationValue = 16;
  630.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  631.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  632.   RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL6;
  633.   RCC_OscInitStruct.PLL.PLLDIV = RCC_PLL_DIV3;
  634.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  635.   {
  636.     Error_Handler();
  637.   }
  638.  
  639.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
  640.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  641.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  642.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  643.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  644.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
  645.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
  646.   {
  647.     Error_Handler();
  648.   }
  649.  
  650.   HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
  651.  
  652.   HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
  653.  
  654.   /* SysTick_IRQn interrupt configuration */
  655.   HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
  656. }
  657.  
  658. /* ADC init function */
  659. static void MX_ADC_Init(void)
  660. {
  661.  
  662.   ADC_ChannelConfTypeDef sConfig;
  663.  
  664.     /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
  665.     */
  666.   hadc.Instance = ADC1;
  667.   hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
  668.   hadc.Init.Resolution = ADC_RESOLUTION_12B;
  669.   hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  670.   hadc.Init.ScanConvMode = ADC_SCAN_ENABLE;
  671.   hadc.Init.EOCSelection = ADC_EOC_SEQ_CONV;
  672.   hadc.Init.LowPowerAutoWait = ADC_AUTOWAIT_DISABLE;
  673.   hadc.Init.LowPowerAutoPowerOff = ADC_AUTOPOWEROFF_DISABLE;
  674.   hadc.Init.ChannelsBank = ADC_CHANNELS_BANK_A;
  675.   hadc.Init.ContinuousConvMode = DISABLE;
  676.   hadc.Init.NbrOfConversion = 6;
  677.   hadc.Init.DiscontinuousConvMode = DISABLE;
  678.   hadc.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T6_TRGO;
  679.   hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
  680.   hadc.Init.DMAContinuousRequests = ENABLE;
  681.   if (HAL_ADC_Init(&hadc) != HAL_OK)
  682.   {
  683.     Error_Handler();
  684.   }
  685.  
  686.     /**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  687.     */
  688.   sConfig.Channel = ADC_CHANNEL_10;
  689.   sConfig.Rank = 1;
  690.   sConfig.SamplingTime = ADC_SAMPLETIME_384CYCLES;
  691.   if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  692.   {
  693.     Error_Handler();
  694.   }
  695.  
  696.     /**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  697.     */
  698.   sConfig.Channel = ADC_CHANNEL_11;
  699.   sConfig.Rank = 2;
  700.   if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  701.   {
  702.     Error_Handler();
  703.   }
  704.  
  705.     /**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  706.     */
  707.   sConfig.Channel = ADC_CHANNEL_12;
  708.   sConfig.Rank = 3;
  709.   if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  710.   {
  711.     Error_Handler();
  712.   }
  713.  
  714.     /**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  715.     */
  716.   sConfig.Channel = ADC_CHANNEL_13;
  717.   sConfig.Rank = 4;
  718.   if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  719.   {
  720.     Error_Handler();
  721.   }
  722.  
  723.     /**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  724.     */
  725.   sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
  726.   sConfig.Rank = 5;
  727.   if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  728.   {
  729.     Error_Handler();
  730.   }
  731.  
  732.     /**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  733.     */
  734.   sConfig.Channel = ADC_CHANNEL_VREFINT;
  735.   sConfig.Rank = 6;
  736.   if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  737.   {
  738.     Error_Handler();
  739.   }
  740.  
  741. }
  742.  
  743. /* SPI1 init function */
  744. static void MX_SPI1_Init(void)
  745. {
  746.  
  747.   hspi1.Instance = SPI1;
  748.   hspi1.Init.Mode = SPI_MODE_MASTER;
  749.   hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  750.   hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  751.   hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  752.   hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  753.   hspi1.Init.NSS = SPI_NSS_SOFT;
  754.   hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;
  755.   hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  756.   hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  757.   hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  758.   hspi1.Init.CRCPolynomial = 10;
  759.   if (HAL_SPI_Init(&hspi1) != HAL_OK)
  760.   {
  761.     Error_Handler();
  762.   }
  763.  
  764. }
  765.  
  766. /* TIM2 init function */
  767. static void MX_TIM2_Init(void)
  768. {
  769.  
  770.   TIM_ClockConfigTypeDef sClockSourceConfig;
  771.   TIM_MasterConfigTypeDef sMasterConfig;
  772.   TIM_IC_InitTypeDef sConfigIC;
  773.  
  774.   htim2.Instance = TIM2;
  775.   htim2.Init.Prescaler = 320;
  776.   htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  777.   htim2.Init.Period = 65535;
  778.   htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  779.   if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  780.   {
  781.     Error_Handler();
  782.   }
  783.  
  784.   sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  785.   if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  786.   {
  787.     Error_Handler();
  788.   }
  789.  
  790.   if (HAL_TIM_IC_Init(&htim2) != HAL_OK)
  791.   {
  792.     Error_Handler();
  793.   }
  794.  
  795.   sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
  796.   sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  797.   if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  798.   {
  799.     Error_Handler();
  800.   }
  801.  
  802.   sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
  803.   sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
  804.   sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
  805.   sConfigIC.ICFilter = 0;
  806.   if (HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_1) != HAL_OK)
  807.   {
  808.     Error_Handler();
  809.   }
  810.  
  811. }
  812.  
  813. /* TIM6 init function */
  814. static void MX_TIM6_Init(void)
  815. {
  816.  
  817.   TIM_MasterConfigTypeDef sMasterConfig;
  818.  
  819.   htim6.Instance = TIM6;
  820.   htim6.Init.Prescaler = 320;
  821.   htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
  822.   htim6.Init.Period = 9999;
  823.   if (HAL_TIM_Base_Init(&htim6) != HAL_OK)
  824.   {
  825.     Error_Handler();
  826.   }
  827.  
  828.   sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
  829.   sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  830.   if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK)
  831.   {
  832.     Error_Handler();
  833.   }
  834.  
  835. }
  836.  
  837. /* USART1 init function */
  838. static void MX_USART1_UART_Init(void)
  839. {
  840.  
  841.   huart1.Instance = USART1;
  842.   huart1.Init.BaudRate = 19200;
  843.   huart1.Init.WordLength = UART_WORDLENGTH_8B;
  844.   huart1.Init.StopBits = UART_STOPBITS_1;
  845.   huart1.Init.Parity = UART_PARITY_NONE;
  846.   huart1.Init.Mode = UART_MODE_TX_RX;
  847.   huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  848.   huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  849.   if (HAL_UART_Init(&huart1) != HAL_OK)
  850.   {
  851.     Error_Handler();
  852.   }
  853.  
  854. }
  855.  
  856. /* USART2 init function */
  857. static void MX_USART2_UART_Init(void)
  858. {
  859.  
  860.   huart2.Instance = USART2;
  861.   huart2.Init.BaudRate = 115200;
  862.   huart2.Init.WordLength = UART_WORDLENGTH_8B;
  863.   huart2.Init.StopBits = UART_STOPBITS_1;
  864.   huart2.Init.Parity = UART_PARITY_NONE;
  865.   huart2.Init.Mode = UART_MODE_TX_RX;
  866.   huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  867.   huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  868.   if (HAL_UART_Init(&huart2) != HAL_OK)
  869.   {
  870.     Error_Handler();
  871.   }
  872.  
  873. }
  874.  
  875. /**
  876.   * Enable DMA controller clock
  877.   */
  878. static void MX_DMA_Init(void)
  879. {
  880.   /* DMA controller clock enable */
  881.   __HAL_RCC_DMA1_CLK_ENABLE();
  882.  
  883.   /* DMA interrupt init */
  884.   /* DMA1_Channel1_IRQn interrupt configuration */
  885.   HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
  886.   HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
  887.  
  888. }
  889.  
  890. /** Configure pins as
  891.         * Analog
  892.         * Input
  893.         * Output
  894.         * EVENT_OUT
  895.         * EXTI
  896.         * Free pins are configured automatically as Analog (this feature is enabled through
  897.         * the Code Generation settings)
  898. */
  899. static void MX_GPIO_Init(void)
  900. {
  901.  
  902.   GPIO_InitTypeDef GPIO_InitStruct;
  903.  
  904.   /* GPIO Ports Clock Enable */
  905.   __HAL_RCC_GPIOC_CLK_ENABLE();
  906.   __HAL_RCC_GPIOH_CLK_ENABLE();
  907.   __HAL_RCC_GPIOA_CLK_ENABLE();
  908.   __HAL_RCC_GPIOB_CLK_ENABLE();
  909.   __HAL_RCC_GPIOD_CLK_ENABLE();
  910.  
  911.   /*Configure GPIO pins : PC13 PC14 PC15 PC6
  912.                            PC7 PC8 PC9 PC11
  913.                            PC12 */
  914.   GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_6
  915.                           |GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_11
  916.                           |GPIO_PIN_12;
  917.   GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  918.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  919.   HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
  920.  
  921.   /*Configure GPIO pins : PH0 PH1 */
  922.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
  923.   GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  924.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  925.   HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
  926.  
  927.   /*Configure GPIO pins : PA0 PA1 PA8 PA11
  928.                            PA12 */
  929.   GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_8|GPIO_PIN_11
  930.                           |GPIO_PIN_12;
  931.   GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  932.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  933.   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  934.  
  935.   /*Configure GPIO pin : LED_Blink_Pin */
  936.   GPIO_InitStruct.Pin = LED_Blink_Pin;
  937.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  938.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  939.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  940.   HAL_GPIO_Init(LED_Blink_GPIO_Port, &GPIO_InitStruct);
  941.  
  942.   /*Configure GPIO pins : SPI_NSS1_Pin SPI1CD_Pin */
  943.   GPIO_InitStruct.Pin = SPI_NSS1_Pin|SPI1CD_Pin;
  944.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  945.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  946.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  947.   HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
  948.  
  949.   /*Configure GPIO pins : SPI_RESET_Pin SPI_NS_Temp_Pin SPI_NS_Temp2_Pin ENA_AUX_5V_Pin */
  950.   GPIO_InitStruct.Pin = SPI_RESET_Pin|SPI_NS_Temp_Pin|SPI_NS_Temp2_Pin|ENA_AUX_5V_Pin;
  951.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  952.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  953.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  954.   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  955.  
  956.   /*Configure GPIO pins : PB11 PB12 PB13 PB14
  957.                            PB15 PB3 PB4 PB5
  958.                            PB6 PB7 PB8 PB9 */
  959.   GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14
  960.                           |GPIO_PIN_15|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5
  961.                           |GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9;
  962.   GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  963.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  964.   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  965.  
  966.   /*Configure GPIO pin : STARTER_ON_Pin */
  967.   GPIO_InitStruct.Pin = STARTER_ON_Pin;
  968.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  969.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  970.   HAL_GPIO_Init(STARTER_ON_GPIO_Port, &GPIO_InitStruct);
  971.  
  972.   /*Configure GPIO pin : PD2 */
  973.   GPIO_InitStruct.Pin = GPIO_PIN_2;
  974.   GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  975.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  976.   HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
  977.  
  978.   /*Configure GPIO pin Output Level */
  979.   HAL_GPIO_WritePin(LED_Blink_GPIO_Port, LED_Blink_Pin, GPIO_PIN_RESET);
  980.  
  981.   /*Configure GPIO pin Output Level */
  982.   HAL_GPIO_WritePin(SPI_NSS1_GPIO_Port, SPI_NSS1_Pin, GPIO_PIN_SET);
  983.  
  984.   /*Configure GPIO pin Output Level */
  985.   HAL_GPIO_WritePin(SPI1CD_GPIO_Port, SPI1CD_Pin, GPIO_PIN_RESET);
  986.  
  987.   /*Configure GPIO pin Output Level */
  988.   HAL_GPIO_WritePin(GPIOB, SPI_RESET_Pin|SPI_NS_Temp2_Pin|ENA_AUX_5V_Pin, GPIO_PIN_RESET);
  989.  
  990.   /*Configure GPIO pin Output Level */
  991.   HAL_GPIO_WritePin(SPI_NS_Temp_GPIO_Port, SPI_NS_Temp_Pin, GPIO_PIN_SET);
  992.  
  993. }
  994.  
  995. /* USER CODE BEGIN 4 */
  996.  
  997. /* USER CODE END 4 */
  998.  
  999. /**
  1000.   * @brief  This function is executed in case of error occurrence.
  1001.   * @param  None
  1002.   * @retval None
  1003.   */
  1004. void Error_Handler(void)
  1005. {
  1006.   /* USER CODE BEGIN Error_Handler */
  1007.         /* User can add his own implementation to report the HAL error return state */
  1008.         while (1)
  1009.         {
  1010.         }
  1011.   /* USER CODE END Error_Handler */
  1012. }
  1013.  
  1014. #ifdef USE_FULL_ASSERT
  1015.  
  1016. /**
  1017.    * @brief Reports the name of the source file and the source line number
  1018.    * where the assert_param error has occurred.
  1019.    * @param file: pointer to the source file name
  1020.    * @param line: assert_param error line source number
  1021.    * @retval None
  1022.    */
  1023. void assert_failed(uint8_t* file, uint32_t line)
  1024. {
  1025.   /* USER CODE BEGIN 6 */
  1026.         /* User can add his own implementation to report the file name and line number,
  1027.          ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  1028.   /* USER CODE END 6 */
  1029.  
  1030. }
  1031.  
  1032. #endif
  1033.  
  1034. /**
  1035.   * @}
  1036.   */
  1037.  
  1038. /**
  1039.   * @}
  1040. */
  1041.  
  1042. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
  1043.