Subversion Repositories DashDisplay

Rev

Rev 38 | Rev 47 | 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) 2018 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 "ap_math.h"
  38. #include "serial.h"
  39. #include "SSD1306.h"
  40. #include "Font.h"
  41. #include "dials.h"
  42. #include "switches.h"
  43. #include <math.h>
  44. #include "plx.h"
  45. #include "displayinfo.h"
  46. #include "small_printf.h"
  47. #include "nvram.h"
  48.  
  49. /* USER CODE END Includes */
  50.  
  51. /* Private variables ---------------------------------------------------------*/
  52. SPI_HandleTypeDef hspi1;
  53.  
  54. TIM_HandleTypeDef htim3;
  55. TIM_HandleTypeDef htim9;
  56.  
  57. UART_HandleTypeDef huart1;
  58. UART_HandleTypeDef huart2;
  59. UART_HandleTypeDef huart3;
  60.  
  61. /* USER CODE BEGIN PV */
  62. /* Private variables ---------------------------------------------------------*/
  63. #define MAXRDG 32
  64.  
  65. /* timeout when the ignition is switched off */
  66. #define IGNITION_OFF_TIMEOUT 30000UL
  67.  
  68. int OldObservation[2] =
  69. { -1, -1 }; // illegal initial value
  70. int OldObservationIndex[2] =
  71. { -1, -1 }; // if more than one sensor this will be printed
  72. int16_t dial0[2] =
  73. { 0, 0 };
  74. int16_t dial1[2] =
  75. { -1, -1 };
  76.  
  77. uint16_t dial_timer[2] =
  78. { 0, 0 };
  79.  
  80. static const int DialTimeout = 50; // about 20 seconds after twiddle, save the dial position.
  81.  
  82. uint16_t dial_nvram[2] __attribute__((section(".NVRAM_Data")));
  83.  
  84. union
  85. {
  86.         PLX_SensorInfo Sensor[MAXRDG];
  87.         char Bytes[MAXRDG * sizeof(PLX_SensorInfo)];
  88. } Data;
  89. int Max[MAXRDG];
  90. int Min[MAXRDG];
  91. int PLXItems;
  92.  
  93. uint32_t Latch_Timer = IGNITION_OFF_TIMEOUT;
  94.  
  95. /* USER CODE END PV */
  96.  
  97. /* Private function prototypes -----------------------------------------------*/
  98. void SystemClock_Config(void);
  99. void Error_Handler(void);
  100. static void MX_GPIO_Init(void);
  101. static void MX_SPI1_Init(void);
  102. static void MX_USART1_UART_Init(void);
  103. static void MX_USART2_UART_Init(void);
  104. static void MX_USART3_UART_Init(void);
  105. static void MX_TIM3_Init(void);
  106. static void MX_TIM9_Init(void);
  107.  
  108. /* USER CODE BEGIN PFP */
  109. /* Private function prototypes -----------------------------------------------*/
  110.  
  111. /* USER CODE END PFP */
  112.  
  113. /* USER CODE BEGIN 0 */
  114. /* dummy function */
  115. void _init(void)
  116. {
  117.  
  118. }
  119. // the dial is the switch number we are using.
  120. // suppress is the ItemIndex we wish to suppress on this display
  121. int DisplayCurrent(int dial, int suppress)
  122. {
  123.         char buff[10];
  124.         int i;
  125.         int rc;
  126.         select_display(dial); // pick the display we are using
  127.         int ItemIndex = dial_pos[dial] % PLXItems;
  128.  
  129. #if 0
  130.         // wrap around count if dial too far to the right
  131.         if (ItemIndex >= PLXItems)
  132.         {
  133.                 dial_pos[dial] = 0;
  134.                 ItemIndex = 0;
  135.         }
  136.         if (ItemIndex < 0)
  137.         {
  138.                 ItemIndex = PLXItems - 1;
  139.                 dial_pos[dial] = (PLXItems - 1) * 4;
  140.         }
  141. #endif
  142.         // check for item suppression
  143.         if (ItemIndex == suppress)
  144.         {
  145.                 dial1[dial] = -1;
  146.                 OldObservation[dial] = -1;
  147.                 OldObservationIndex[dial] = -1;
  148.  
  149.                 clearDisplay();
  150.                 display();
  151.                 return -1; // we suppressed this display
  152.         }
  153.         // do not try to convert if no items in buffer
  154.         if (PLXItems > 0)
  155.         {
  156.                 int DataVal = ConvPLX(Data.Sensor[ItemIndex].ReadingH,
  157.                                 Data.Sensor[ItemIndex].ReadingL); // data reading
  158.                 int Observation = ConvPLX(Data.Sensor[ItemIndex].AddrH,
  159.                                 Data.Sensor[ItemIndex].AddrL);
  160.                 int ObservationIndex = ConvPLX(0, Data.Sensor[ItemIndex].Instance);
  161.                 // now to convert the readings and format strings
  162.                 // find out limits
  163.                 char * msg;
  164.                 int len;
  165.  
  166.                 // if the user presses the dial then reset min/max to current value
  167.                 if (push_pos[dial] == 1)
  168.                 {
  169.                         Max[ItemIndex] = DataVal;
  170.                         Min[ItemIndex] = DataVal; // 12 bit max value
  171.                 }
  172.  
  173.                 if (Observation < PLX_MAX_OBS)
  174.                 {
  175.                         if (Observation != OldObservation[dial]
  176.                                         || ObservationIndex != OldObservationIndex[dial])
  177.                         {
  178.  
  179.                                 dial_timer[dial] = DialTimeout;
  180.  
  181.                                 dial1[dial] = -1;
  182.                                 clearDisplay();
  183.                                 dial_draw_scale(DisplayInfo[Observation].Low,
  184.                                                 DisplayInfo[Observation].High, 12, 1,
  185.                                                 DisplayInfo[Observation].TickScale);
  186.  
  187.                                 msg = DisplayInfo[Observation].name;
  188.                                 len = 7;
  189.                                 int len1 = ObservationIndex > 0 ? len - 1 : len;
  190.                                 for (i = 0; i < len1 && msg[i]; i++)
  191.                                 {
  192.                                         buff[i] = msg[i];
  193.                                 }
  194.                                 if (ObservationIndex > 0 && i < len)
  195.                                 {
  196.                                         buff[i++] = ObservationIndex + '1';
  197.                                 }
  198.  
  199.                                 print_large_string(buff, 64 - i * 4, 48, i); // this prints spaces for \0 at end of string
  200.  
  201.                                 // print suffix if present.
  202.                                 font_gotoxy(15, 4);
  203.                                 int i = 0;
  204.                                 while (DisplayInfo[Observation].suffix[i])
  205.                                 {
  206.                                         font_putchar(DisplayInfo[Observation].suffix[i++]);
  207.                                 }
  208.  
  209.                                 OldObservation[dial] = Observation;
  210.                                 OldObservationIndex[dial] = ObservationIndex;
  211.                                 //
  212.                                 display();
  213.  
  214.                         }
  215.                         else
  216.                         {
  217.                                 // check for timer timeout on consistent timer
  218.                                 if (dial_timer[dial])
  219.                                 {
  220.                                         dial_timer[dial]--;
  221.  
  222.                                         if (dial_timer[dial] == 0)
  223.                                         {
  224.                                                 uint16_t curr_val = dial_pos[dial];
  225.  
  226.                                                 uint32_t addr = (uint32_t) (&dial_nvram[dial]);
  227.                                             WriteUint16NVRAM(addr, curr_val );
  228.  
  229.                                         }
  230.                                 }
  231.                         }
  232.  
  233.                 }
  234.  
  235.                 double max_rdg;
  236.                 double min_rdg;
  237.                 double cur_rdg;
  238.                 int int_rdg;
  239.                 int int_max;
  240.                 int int_min;
  241.  
  242.                 max_rdg = ConveriMFDRaw2Data(Observation,
  243.                                 DisplayInfo[Observation].Units, Max[ItemIndex]);
  244.                 min_rdg = ConveriMFDRaw2Data(Observation,
  245.                                 DisplayInfo[Observation].Units, Min[ItemIndex]);
  246.                 cur_rdg = ConveriMFDRaw2Data(Observation,
  247.                                 DisplayInfo[Observation].Units, DataVal);
  248.  
  249.                 int dp_pos;  // where to print the decimal place
  250.                 float scale = 1.0;
  251.                 switch (DisplayInfo[Observation].DP)
  252.                 {
  253.                 case 0:
  254.                         scale = 1.0;
  255.                         dp_pos = 100;
  256.                         break;
  257.                 case 1:
  258.                         scale = 10.0;
  259.                         dp_pos = 1;
  260.                         break;
  261.                 case 2:
  262.                         scale = 100.0;
  263.                         dp_pos = 2;
  264.                         break;
  265.                 }
  266.                 int_rdg = (int) (cur_rdg * scale);
  267.                 int_max = (int) (max_rdg * scale);
  268.                 int_min = (int) (min_rdg * scale);
  269.  
  270.                 cur_rdg -= DisplayInfo[Observation].Low;
  271.                 cur_rdg =
  272.                                 100 * cur_rdg
  273.                                                 / (DisplayInfo[Observation].High
  274.                                                                 - DisplayInfo[Observation].Low);
  275.  
  276.                 dial0[dial] = (int) cur_rdg;
  277.  
  278.                 /* old needle un-draw */
  279.                 if (dial1[dial] >= 0)
  280.                 {
  281.                         dial_draw_needle(dial1[dial]);
  282.                 }
  283.                 dial_draw_needle(dial0[dial]);
  284.                 // print value overlaid by needle
  285.                 // this is actual reading
  286.                 print_digits(30, 30, 5, dp_pos, int_rdg);
  287.                 font_gotoxy(0, 0);
  288.                 font_digits(5, dp_pos, int_min);
  289.  
  290.                 font_gotoxy(0, 1);
  291.                 font_puts("Min");
  292.  
  293.                 font_gotoxy(15, 0);
  294.                 font_digits(5, dp_pos, int_max);
  295.                 font_gotoxy(18, 1);
  296.                 font_puts("Max");
  297.  
  298.                 dial1[dial] = dial0[dial];
  299.  
  300.                 display();
  301.  
  302.         }
  303. return ItemIndex;
  304. }
  305. /* USER CODE END 0 */
  306.  
  307. int main(void)
  308. {
  309.  
  310.   /* USER CODE BEGIN 1 */
  311.  
  312. GPIO_InitTypeDef GPIO_InitStruct;
  313.  
  314. __HAL_RCC_SPI1_CLK_ENABLE()
  315. ;
  316. __HAL_RCC_USART1_CLK_ENABLE()
  317. ; // PLX main port
  318. __HAL_RCC_USART2_CLK_ENABLE()
  319. ; // debug port
  320. __HAL_RCC_USART3_CLK_ENABLE ()
  321. ; // Bluetooth port
  322.  
  323. __HAL_RCC_TIM3_CLK_ENABLE();
  324.  
  325. __HAL_RCC_TIM9_CLK_ENABLE();
  326.   /* USER CODE END 1 */
  327.  
  328.   /* MCU Configuration----------------------------------------------------------*/
  329.  
  330.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  331.   HAL_Init();
  332.  
  333.   /* Configure the system clock */
  334.   SystemClock_Config();
  335.  
  336.   /* Initialize all configured peripherals */
  337.   MX_GPIO_Init();
  338.   MX_SPI1_Init();
  339.   MX_USART1_UART_Init();
  340.   MX_USART2_UART_Init();
  341.   MX_USART3_UART_Init();
  342.   MX_TIM3_Init();
  343.   MX_TIM9_Init();
  344.  
  345.   /* USER CODE BEGIN 2 */
  346.  
  347. /* Turn on USART1 IRQ */
  348. HAL_NVIC_SetPriority(USART1_IRQn, 2, 0);
  349. HAL_NVIC_EnableIRQ(USART1_IRQn);
  350.  
  351. /* Turn on USART2 IRQ  */
  352. HAL_NVIC_SetPriority(USART2_IRQn, 4, 0);
  353. HAL_NVIC_EnableIRQ(USART2_IRQn);
  354.  
  355. /* turn on USART3 IRQ */
  356. HAL_NVIC_SetPriority(USART3_IRQn, 4, 0);
  357. HAL_NVIC_EnableIRQ(USART3_IRQn);
  358.  
  359. /* setup the USART control blocks */
  360. init_usart_ctl(&uc1, huart1.Instance);
  361. init_usart_ctl(&uc2, huart2.Instance);
  362. init_usart_ctl(&uc3, huart3.Instance);
  363.  
  364. EnableSerialRxInterrupt(&uc1);
  365. EnableSerialRxInterrupt(&uc2);
  366. EnableSerialRxInterrupt(&uc3);
  367.  
  368. HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL);
  369.  
  370. HAL_TIM_Encoder_Start(&htim9, TIM_CHANNEL_ALL);
  371.  
  372. InitSwitches();
  373.  
  374. int i;
  375. uint16_t rc;
  376. for (i = 0; i < 2; i++)
  377. {
  378.         dial_pos[i] = dial_nvram[i];
  379. }
  380.  
  381. ap_init(); // set up the approximate math library
  382.  
  383. int disp;
  384.  
  385. ssd1306_begin(1, 0);
  386. dial_origin(64, 60);
  387. dial_size(60);
  388.  
  389. /* reset the display timeout, latch on power from accessories */
  390. Latch_Timer = IGNITION_OFF_TIMEOUT;
  391. HAL_GPIO_WritePin(POWER_LATCH_GPIO_Port, POWER_LATCH_Pin, GPIO_PIN_RESET);
  392.  
  393. for (disp = 0; disp < 2; disp++)
  394. {
  395.         select_display(disp);
  396.         clearDisplay();
  397.         dim(0);
  398.         //font_puts(
  399.         //              "Hello world !!\rThis text is a test of the text rendering library in a 5*7 font");
  400.  
  401.         dial_draw_scale(0, 10, 12, 5, 1);
  402.         char buffer[] = "Display  ";
  403.         buffer[8] = disp + '1';
  404.         print_large_string(buffer, 20, 30, 9);
  405.  
  406.         display();
  407.  
  408. }
  409.  
  410.   /* USER CODE END 2 */
  411.  
  412.   /* Infinite loop */
  413.   /* USER CODE BEGIN WHILE */
  414. uint32_t Ticks = HAL_GetTick() + 100;
  415.  
  416. /* while ignition is on, keep resetting power latch timer */
  417. if (HAL_GPIO_ReadPin(IGNITION_GPIO_Port, IGNITION_Pin) == GPIO_PIN_RESET)
  418. {
  419.         Latch_Timer = HAL_GetTick() + IGNITION_OFF_TIMEOUT;
  420. }
  421. else
  422. {
  423.         /* if the ignition has been off for a while, then turn off power */
  424.         if (HAL_GetTick() > Latch_Timer)
  425.         {
  426.                 HAL_GPIO_WritePin(POWER_LATCH_GPIO_Port, POWER_LATCH_Pin,
  427.                                 GPIO_PIN_RESET);
  428.         }
  429. }
  430.  
  431. uint32_t timeout = 0;  //
  432. // PLX decoder protocols
  433. char PLXPacket = 0;
  434. for (i = 0; i < MAXRDG; i++)
  435. {
  436.         Max[i] = 0;
  437.         Min[i] = 0xFFF; // 12 bit max value
  438. }
  439.  
  440. int PLXPtr = 0;
  441.  
  442. while (1)
  443. {
  444. // poll switche
  445.         HandleSwitches();
  446. // Handle the bluetooth pairing function by pressing both buttons.
  447.         if ((push_pos[0] == 1) && (push_pos[1] == 1))
  448.         {
  449.                 HAL_GPIO_WritePin(BT_BUTTON_GPIO_Port, BT_BUTTON_Pin, GPIO_PIN_SET);
  450.         }
  451.         else
  452.         {
  453.                 HAL_GPIO_WritePin(BT_BUTTON_GPIO_Port, BT_BUTTON_Pin, GPIO_PIN_RESET);
  454.  
  455.         }
  456.  
  457.         uint16_t cc = SerialCharsReceived(&uc1);
  458.         int chr;
  459.         if (cc == 0)
  460.         {
  461.                 timeout++;
  462.                 if (timeout % 1000 == 0)
  463.                 {
  464.                         const char msg[] = "No data\r\n";
  465.                         char * p = msg;
  466.                         while(*p)
  467.                         {
  468.                                 PutCharSerial(&uc2,*p++);
  469.                         }
  470.  
  471.                 }
  472.  
  473.                 if (timeout > 60000)
  474.                 {
  475.                         // do turn off screen
  476.                 }
  477.  
  478.         }
  479.         for (chr = 0; chr < cc; chr++)
  480.         {
  481.                 char c = GetCharSerial(&uc1);
  482.                 timeout = 0;
  483.  
  484.                 if (c == PLX_Start) // at any time if the start byte appears, reset the pointers
  485.                 {
  486.                         PLXPtr = 0;    // reset the pointer
  487.                         PLXPacket = 1;
  488.                 }
  489.                 else if (c == PLX_Stop)
  490.                 {
  491.                         if (PLXPacket)
  492.                         {
  493.                                 // we can now decode the selected parameter
  494.                                 PLXItems = PLXPtr / sizeof(PLX_SensorInfo); // total
  495.                                 // saturate the rotary switch position
  496.  
  497.                                 int DataVal;
  498.                                 // process min/max
  499.                                 for (i = 0; i < PLXItems; i++)
  500.                                 {
  501.                                         // Send item to BT
  502.                                         uint16_t addr = ConvPLX(Data.Sensor[i].AddrH,
  503.                                                         Data.Sensor[i].AddrL);
  504.                                         uint8_t inst = Data.Sensor[i].Instance;
  505.                                         uint16_t reading = ConvPLX(Data.Sensor[i].ReadingH,
  506.                                                         Data.Sensor[i].ReadingL);
  507.  
  508.                                         char outbuff[100];
  509.                                         int cnt = small_sprintf(outbuff, "%d,%d,%d\n\r", addr, inst,
  510.                                                         reading);
  511.                                         int ck=0;
  512.                                         while(outbuff[ck] && ck < 100)
  513.  
  514.                                         {
  515.                                                 PutCharSerial(&uc2, outbuff[ck++]);
  516.                                         }
  517.                                         DataVal = ConvPLX(Data.Sensor[i].ReadingH,
  518.                                                         Data.Sensor[i].ReadingL);
  519.                                         if (DataVal > Max[i])
  520.                                         {
  521.                                                 Max[i] = DataVal;
  522.                                         }
  523.                                         if (DataVal < Min[i])
  524.                                         {
  525.                                                 Min[i] = DataVal;
  526.                                         }
  527.                                 }
  528.  
  529.                                 // now to display the information
  530.                                 int suppress = DisplayCurrent(0, -1);
  531.                                 DisplayCurrent(1, suppress);
  532.                         }
  533.                         PLXPtr = 0;
  534.                         PLXPacket = 0;
  535.                 }
  536.                 else if (c > PLX_Stop) // illegal char, restart reading
  537.                 {
  538.                         PLXPacket = 0;
  539.                         PLXPtr = 0;
  540.                 }
  541.                 else if (PLXPtr < sizeof(Data.Bytes))
  542.                 {
  543.                         Data.Bytes[PLXPtr++] = c;
  544.                 }
  545.         }
  546.  
  547.         HAL_Delay(1);
  548. }
  549.   /* USER CODE END WHILE */
  550.  
  551.   /* USER CODE BEGIN 3 */
  552.  
  553.   /* USER CODE END 3 */
  554.  
  555. }
  556.  
  557. /** System Clock Configuration
  558. */
  559. void SystemClock_Config(void)
  560. {
  561.  
  562.   RCC_OscInitTypeDef RCC_OscInitStruct;
  563.   RCC_ClkInitTypeDef RCC_ClkInitStruct;
  564.  
  565.   __HAL_RCC_PWR_CLK_ENABLE();
  566.  
  567.   __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  568.  
  569.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  570.   RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;
  571.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  572.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  573.   RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL12;
  574.   RCC_OscInitStruct.PLL.PLLDIV = RCC_PLL_DIV3;
  575.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  576.   {
  577.     Error_Handler();
  578.   }
  579.  
  580.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
  581.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  582.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  583.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  584.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  585.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
  586.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
  587.   {
  588.     Error_Handler();
  589.   }
  590.  
  591.   HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
  592.  
  593.   HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
  594.  
  595.   /* SysTick_IRQn interrupt configuration */
  596.   HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
  597. }
  598.  
  599. /* SPI1 init function */
  600. static void MX_SPI1_Init(void)
  601. {
  602.  
  603.   hspi1.Instance = SPI1;
  604.   hspi1.Init.Mode = SPI_MODE_MASTER;
  605.   hspi1.Init.Direction = SPI_DIRECTION_1LINE;
  606.   hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  607.   hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;
  608.   hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  609.   hspi1.Init.NSS = SPI_NSS_SOFT;
  610.   hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
  611.   hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  612.   hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  613.   hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  614.   hspi1.Init.CRCPolynomial = 10;
  615.   if (HAL_SPI_Init(&hspi1) != HAL_OK)
  616.   {
  617.     Error_Handler();
  618.   }
  619.  
  620. }
  621.  
  622. /* TIM3 init function */
  623. static void MX_TIM3_Init(void)
  624. {
  625.  
  626.   TIM_Encoder_InitTypeDef sConfig;
  627.   TIM_MasterConfigTypeDef sMasterConfig;
  628.  
  629.   htim3.Instance = TIM3;
  630.   htim3.Init.Prescaler = 0;
  631.   htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  632.   htim3.Init.Period = 0xffff;
  633.   htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV4;
  634.   sConfig.EncoderMode = TIM_ENCODERMODE_TI1;
  635.   sConfig.IC1Polarity = TIM_ICPOLARITY_FALLING;
  636.   sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
  637.   sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
  638.   sConfig.IC1Filter = 15;
  639.   sConfig.IC2Polarity = TIM_ICPOLARITY_FALLING;
  640.   sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
  641.   sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
  642.   sConfig.IC2Filter = 15;
  643.   if (HAL_TIM_Encoder_Init(&htim3, &sConfig) != HAL_OK)
  644.   {
  645.     Error_Handler();
  646.   }
  647.  
  648.   sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  649.   sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  650.   if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
  651.   {
  652.     Error_Handler();
  653.   }
  654.  
  655. }
  656.  
  657. /* TIM9 init function */
  658. static void MX_TIM9_Init(void)
  659. {
  660.  
  661.   TIM_Encoder_InitTypeDef sConfig;
  662.   TIM_MasterConfigTypeDef sMasterConfig;
  663.  
  664.   htim9.Instance = TIM9;
  665.   htim9.Init.Prescaler = 0;
  666.   htim9.Init.CounterMode = TIM_COUNTERMODE_UP;
  667.   htim9.Init.Period = 0xffff;
  668.   htim9.Init.ClockDivision = TIM_CLOCKDIVISION_DIV4;
  669.   sConfig.EncoderMode = TIM_ENCODERMODE_TI1;
  670.   sConfig.IC1Polarity = TIM_ICPOLARITY_FALLING;
  671.   sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
  672.   sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
  673.   sConfig.IC1Filter = 15;
  674.   sConfig.IC2Polarity = TIM_ICPOLARITY_FALLING;
  675.   sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
  676.   sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
  677.   sConfig.IC2Filter = 15;
  678.   if (HAL_TIM_Encoder_Init(&htim9, &sConfig) != HAL_OK)
  679.   {
  680.     Error_Handler();
  681.   }
  682.  
  683.   sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  684.   sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  685.   if (HAL_TIMEx_MasterConfigSynchronization(&htim9, &sMasterConfig) != HAL_OK)
  686.   {
  687.     Error_Handler();
  688.   }
  689.  
  690. }
  691.  
  692. /* USART1 init function */
  693. static void MX_USART1_UART_Init(void)
  694. {
  695.  
  696.   huart1.Instance = USART1;
  697.   huart1.Init.BaudRate = 19200;
  698.   huart1.Init.WordLength = UART_WORDLENGTH_8B;
  699.   huart1.Init.StopBits = UART_STOPBITS_1;
  700.   huart1.Init.Parity = UART_PARITY_NONE;
  701.   huart1.Init.Mode = UART_MODE_TX_RX;
  702.   huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  703.   huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  704.   if (HAL_UART_Init(&huart1) != HAL_OK)
  705.   {
  706.     Error_Handler();
  707.   }
  708.  
  709. }
  710.  
  711. /* USART2 init function */
  712. static void MX_USART2_UART_Init(void)
  713. {
  714.  
  715.   huart2.Instance = USART2;
  716.   huart2.Init.BaudRate = 115200;
  717.   huart2.Init.WordLength = UART_WORDLENGTH_8B;
  718.   huart2.Init.StopBits = UART_STOPBITS_1;
  719.   huart2.Init.Parity = UART_PARITY_NONE;
  720.   huart2.Init.Mode = UART_MODE_TX_RX;
  721.   huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  722.   huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  723.   if (HAL_UART_Init(&huart2) != HAL_OK)
  724.   {
  725.     Error_Handler();
  726.   }
  727.  
  728. }
  729.  
  730. /* USART3 init function */
  731. static void MX_USART3_UART_Init(void)
  732. {
  733.  
  734.   huart3.Instance = USART3;
  735.   huart3.Init.BaudRate = 19200;
  736.   huart3.Init.WordLength = UART_WORDLENGTH_8B;
  737.   huart3.Init.StopBits = UART_STOPBITS_2;
  738.   huart3.Init.Parity = UART_PARITY_NONE;
  739.   huart3.Init.Mode = UART_MODE_TX_RX;
  740.   huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  741.   huart3.Init.OverSampling = UART_OVERSAMPLING_16;
  742.   if (HAL_UART_Init(&huart3) != HAL_OK)
  743.   {
  744.     Error_Handler();
  745.   }
  746.  
  747. }
  748.  
  749. /** Configure pins as
  750.         * Analog
  751.         * Input
  752.         * Output
  753.         * EVENT_OUT
  754.         * EXTI
  755. */
  756. static void MX_GPIO_Init(void)
  757. {
  758.  
  759.   GPIO_InitTypeDef GPIO_InitStruct;
  760.  
  761.   /* GPIO Ports Clock Enable */
  762.   __HAL_RCC_GPIOH_CLK_ENABLE();
  763.   __HAL_RCC_GPIOA_CLK_ENABLE();
  764.   __HAL_RCC_GPIOC_CLK_ENABLE();
  765.   __HAL_RCC_GPIOB_CLK_ENABLE();
  766.  
  767.   /*Configure GPIO pin Output Level */
  768.   HAL_GPIO_WritePin(GPIOA, SPI_NSS1_Pin|SPI1CD_Pin|BT_BUTTON_Pin, GPIO_PIN_RESET);
  769.  
  770.   /*Configure GPIO pin Output Level */
  771.   HAL_GPIO_WritePin(GPIOC, SPI_RESET_Pin|SPI_NSS2_Pin|POWER_LATCH_Pin|USB_PWR_Pin, GPIO_PIN_RESET);
  772.  
  773.   /*Configure GPIO pins : SPI_NSS1_Pin SPI1CD_Pin */
  774.   GPIO_InitStruct.Pin = SPI_NSS1_Pin|SPI1CD_Pin;
  775.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  776.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  777.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  778.   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  779.  
  780.   /*Configure GPIO pins : SPI_RESET_Pin SPI_NSS2_Pin POWER_LATCH_Pin USB_PWR_Pin */
  781.   GPIO_InitStruct.Pin = SPI_RESET_Pin|SPI_NSS2_Pin|POWER_LATCH_Pin|USB_PWR_Pin;
  782.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  783.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  784.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  785.   HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
  786.  
  787.   /*Configure GPIO pins : SW1_PUSH_Pin SW2_PUSH_Pin */
  788.   GPIO_InitStruct.Pin = SW1_PUSH_Pin|SW2_PUSH_Pin;
  789.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  790.   GPIO_InitStruct.Pull = GPIO_PULLUP;
  791.   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  792.  
  793.   /*Configure GPIO pin : IGNITION_Pin */
  794.   GPIO_InitStruct.Pin = IGNITION_Pin;
  795.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  796.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  797.   HAL_GPIO_Init(IGNITION_GPIO_Port, &GPIO_InitStruct);
  798.  
  799.   /*Configure GPIO pin : BT_BUTTON_Pin */
  800.   GPIO_InitStruct.Pin = BT_BUTTON_Pin;
  801.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
  802.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  803.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  804.   HAL_GPIO_Init(BT_BUTTON_GPIO_Port, &GPIO_InitStruct);
  805.  
  806. }
  807.  
  808. /* USER CODE BEGIN 4 */
  809.  
  810. /* USER CODE END 4 */
  811.  
  812. /**
  813.   * @brief  This function is executed in case of error occurrence.
  814.   * @param  None
  815.   * @retval None
  816.   */
  817. void Error_Handler(void)
  818. {
  819.   /* USER CODE BEGIN Error_Handler */
  820. /* User can add his own implementation to report the HAL error return state */
  821. while (1)
  822. {
  823. }
  824.   /* USER CODE END Error_Handler */
  825. }
  826.  
  827. #ifdef USE_FULL_ASSERT
  828.  
  829. /**
  830.    * @brief Reports the name of the source file and the source line number
  831.    * where the assert_param error has occurred.
  832.    * @param file: pointer to the source file name
  833.    * @param line: assert_param error line source number
  834.    * @retval None
  835.    */
  836. void assert_failed(uint8_t* file, uint32_t line)
  837. {
  838.   /* USER CODE BEGIN 6 */
  839. /* User can add his own implementation to report the file name and line number,
  840.  ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  841.   /* USER CODE END 6 */
  842.  
  843. }
  844.  
  845. #endif
  846.  
  847. /**
  848.   * @}
  849.   */
  850.  
  851. /**
  852.   * @}
  853. */
  854.  
  855. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
  856.