Subversion Repositories canSerial

Rev

Rev 4 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /* USER CODE BEGIN Header */
  2.  
  3. /**
  4.  ******************************************************************************
  5.  * @file           : main.c
  6.  * @brief          : Main program body
  7.  ******************************************************************************
  8.  * @attention
  9.  *
  10.  * <h2><center>&copy; Copyright (c) 2022 STMicroelectronics.
  11.  * All rights reserved.</center></h2>
  12.  *
  13.  * This software component is licensed by ST under BSD 3-Clause license,
  14.  * the "License"; You may not use this file except in compliance with the
  15.  * License. You may obtain a copy of the License at:
  16.  *                        opensource.org/licenses/BSD-3-Clause
  17.  *
  18.  ******************************************************************************
  19.  */
  20. /** @note
  21.  * Reference : implementation created from reversing code in:
  22.  * https://github.com/canboat/canboat/tree/master/ikonvert-serial
  23.  */
  24.  
  25. /* USER CODE END Header */
  26. /* Includes ------------------------------------------------------------------*/
  27. #include "main.h"
  28.  
  29. /* Private includes ----------------------------------------------------------*/
  30. /* USER CODE BEGIN Includes */
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33.  
  34. #include "display.h"
  35.  
  36. #include "string.h"
  37. #include "base64.h"
  38. #include "libSerial/serial.H"
  39. #include "libSerial/serialUtils.H"
  40. #include "libSmallPrintf/small_printf.h"
  41.  
  42. /* USER CODE END Includes */
  43.  
  44. /* Private typedef -----------------------------------------------------------*/
  45. /* USER CODE BEGIN PTD */
  46.  
  47. typedef enum
  48. {
  49.   FAIL,
  50.   REJECT,
  51.   ACCEPT,
  52.   COMPLETE
  53. } appendStatus;
  54.  
  55. typedef struct
  56. {
  57.   uint8_t payloadBuffer[233];
  58.   uint32_t payloadId;
  59.   uint8_t payloadRemaining;  // number of bytes remaining
  60.   uint8_t payloadTotal;      // number total number of bytes
  61.   uint8_t payloadOffset;     // byte offset
  62.   uint8_t payloadNextSeq;    // next sequence frame expected
  63.   uint32_t payloadTimestamp; // timestamp of reception
  64.   appendStatus status;
  65. } contextType;
  66.  
  67. /* USER CODE END PTD */
  68.  
  69. /* Private define ------------------------------------------------------------*/
  70. /* USER CODE BEGIN PD */
  71. /* USER CODE END PD */
  72.  
  73. /* Private macro -------------------------------------------------------------*/
  74. /* USER CODE BEGIN PM */
  75. #define False (0)
  76. #define True (1)
  77. /* USER CODE END PM */
  78.  
  79. /* Private variables ---------------------------------------------------------*/
  80. CAN_HandleTypeDef hcan;
  81.  
  82. SPI_HandleTypeDef hspi1;
  83.  
  84. UART_HandleTypeDef huart1;
  85.  
  86. /* USER CODE BEGIN PV */
  87.  
  88. /* USER CODE END PV */
  89.  
  90. /* Private function prototypes -----------------------------------------------*/
  91. void SystemClock_Config(void);
  92. static void MX_GPIO_Init(void);
  93. static void MX_CAN_Init(void);
  94. static void MX_USART1_UART_Init(void);
  95. static void MX_SPI1_Init(void);
  96. /* USER CODE BEGIN PFP */
  97.  
  98. /* USER CODE END PFP */
  99.  
  100. /* Private user code ---------------------------------------------------------*/
  101. /* USER CODE BEGIN 0 */
  102.  
  103. #define CONTEXTS 6
  104. contextType contexts[CONTEXTS];
  105.  
  106. CAN_TxHeaderTypeDef TxHeader;
  107. CAN_RxHeaderTypeDef RxHeader;
  108.  
  109. uint8_t TxData[8];
  110. uint8_t RxData[8];
  111.  
  112. // Storage for the data
  113.  
  114. uint32_t TxMailbox;
  115.  
  116. char const version[] = "$PDGY,Mike_James_Converter_#00001_Mode:15\r\n";
  117. char const keepawake[] = "$PDGY,000000,1,,4,%ld.%03ld,,,\r\n";
  118. char const commandHdr[] = "$PDGY,";
  119.  
  120. // Allocation of serial buffer sizes and storage
  121. #define TX_BUFFER_SIZE 512
  122. #define RX_BUFFER_SIZE 16
  123. uint8_t tx_buffer[TX_BUFFER_SIZE];
  124. uint8_t rx_buffer[RX_BUFFER_SIZE];
  125.  
  126. // reset a search context
  127. void resetContext(contextType *c)
  128. {
  129.   c->payloadRemaining = 0; // number of bytes remaining
  130.   c->payloadTotal = 0;     // number total number of bytes
  131.   c->payloadOffset = 0;
  132.   c->payloadNextSeq = 0;
  133.   c->payloadTimestamp = 0;
  134.   c->status = FAIL;
  135.   c->payloadId = 0;
  136. }
  137.  
  138. uint8_t singleFrame(uint32_t pgn)
  139. {
  140.  
  141.   switch (pgn)
  142.   {
  143.   case 129029:
  144.   case 129038:
  145.   case 126996:
  146.   case 127489:
  147.     return False;
  148.   default:
  149.     break;
  150.   }
  151.  
  152.   if (pgn >= 130816 && pgn <= 131071)
  153.     return False;
  154.   if (pgn >= 65536 && pgn <= 126975)
  155.     return False;
  156.   return True;
  157. }
  158.  
  159. // called from CAN frame callback
  160. appendStatus append(contextType *c, CAN_RxHeaderTypeDef *packet)
  161. {
  162.   uint32_t extId = RxHeader.ExtId;
  163.  
  164.   if (c->payloadId != 0 && c->payloadId != extId)
  165.     return REJECT;
  166.   uint8_t newId = c->payloadId == 0; // set a flag if this is a newly discovered frame
  167.   c->payloadId = extId;
  168.  
  169.   uint32_t pgn = (c->payloadId >> 8) & ((1 << 18) - 1);
  170.   uint8_t pf = (pgn >> 8) & 0xFF;
  171.  
  172.   if (pf < 240)
  173.   {
  174.     // process PS if in PDU1 , address is low byte
  175.     pgn = pgn & 0x3FF00;
  176.   }
  177.  
  178.   uint8_t packetLen = RxHeader.DLC;
  179.  
  180.   if (singleFrame(pgn))
  181.   {
  182.     c->payloadTimestamp = HAL_GetTick();
  183.     memcpy(c->payloadBuffer, RxData, packetLen);
  184.     c->payloadRemaining = 0;
  185.     c->payloadTotal = packetLen;
  186.     c->status = COMPLETE;
  187.     return c->status; // successfully filled frame
  188.   }
  189.   else
  190.   {
  191.     // sort out fastpacket new ID
  192.     if (newId)
  193.     {
  194.       if ((RxData[0] & 0x1f) != 0)
  195.       {
  196.         resetContext(c);
  197.         return FAIL;
  198.       }
  199.       c->payloadTimestamp = HAL_GetTick();
  200.       c->payloadNextSeq = RxData[0] + 1;
  201.       c->payloadId = extId;
  202.       c->payloadRemaining = RxData[1];
  203.       c->payloadTotal = RxData[1];
  204.       // no data , return
  205.       if (c->payloadTotal == 0)
  206.       {
  207.         resetContext(c);
  208.         return FAIL;
  209.       }
  210.       uint8_t numBytes = packetLen - 2;
  211.       memcpy(c->payloadBuffer, RxData + 2, numBytes);
  212.  
  213.       // CAN frame can be longer than remaining bytes, do not make payloadRemaining wrap around !
  214.       if (numBytes < c->payloadRemaining)
  215.         c->payloadRemaining -= numBytes;
  216.       else
  217.         c->payloadRemaining = 0;
  218.       c->payloadOffset = numBytes;
  219.     }
  220.     else
  221.     {
  222.       if (RxData[0] != c->payloadNextSeq)
  223.       {
  224.         resetContext(c);
  225.         return FAIL;
  226.       }
  227.       // predict next payload sequence
  228.       c->payloadNextSeq++;
  229.       uint8_t numBytes = packetLen - 1;
  230.       memcpy(c->payloadBuffer + c->payloadOffset, RxData + 1, numBytes);
  231.       c->payloadRemaining -= numBytes;
  232.       c->payloadOffset += numBytes;
  233.     }
  234.   }
  235.  
  236.   appendStatus stat = (c->payloadRemaining != 0) ? ACCEPT : COMPLETE;
  237.   c->status = stat;
  238.   return stat;
  239. }
  240.  
  241. void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
  242. {
  243.   HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
  244.   HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, RxData);
  245.  
  246.   int i;
  247.   for (i = 0; i < CONTEXTS; ++i)
  248.   {
  249.     contextType *ctx = &contexts[i];
  250.     appendStatus stat = append(ctx, &RxHeader);
  251.     if (stat == ACCEPT || stat == COMPLETE)
  252.       break; // accepted data, stop loop
  253.   }
  254. }
  255.  
  256. void heartBeat()
  257. {
  258.   char lineBuff[80];
  259.   uint32_t timestamp = HAL_GetTick();
  260.   size_t pos = small_sprintf(lineBuff, keepawake,
  261.                              timestamp / 1000, // seconds
  262.                              timestamp % 1000  // milliseconds
  263.   );
  264.   HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
  265.   if (pos < SerialTransmitSpace(&uc1))
  266.   {
  267.     __disable_irq();
  268.     sendString(&uc1, (char *)lineBuff, pos);
  269.     __enable_irq();
  270.   }
  271. }
  272.  
  273. // utility function to set up the filter mask
  274. void CAN_FilterMaskEXT(CAN_FilterTypeDef *filter_, uint32_t id_, uint32_t mask_)
  275. {
  276.   filter_->FilterIdHigh = id_ >> 13;
  277.   filter_->FilterIdLow = ((id_ & 0x1FFF) << 3) | CAN_ID_EXT;
  278.   filter_->FilterMaskIdHigh = mask_ >> 13;
  279.   filter_->FilterMaskIdLow = ((mask_ & 0x1FFF) << 3) | CAN_ID_EXT;
  280. }
  281.  
  282. void processCmd(char *buff, int len)
  283. {
  284.   buff[len] = 0; // terminate in case of error
  285.                  /// expect $PDGY,pgn,dst,payloadBase64
  286.   const char tokens[] = ",";
  287.  
  288.   char *s = strtok(buff, tokens);
  289.   if (strcmp(s, "$PDGY") != 0)
  290.     return;
  291.  
  292.   char *pgnStr = strtok(NULL, tokens);
  293.   if (!pgnStr)
  294.     return;
  295.   char *dstStr = strtok(NULL, tokens);
  296.   if (!dstStr)
  297.     return;
  298.   char *payloadStr = strtok(NULL, tokens);
  299.   if (!payloadStr)
  300.     return;
  301.  
  302.   // decode string into lineBuff from base64
  303.   uint8_t  frameData[8];
  304.   size_t bytes = 0;
  305.   base64_decode(payloadStr, strlen(payloadStr), (char *) frameData, &bytes);
  306.  
  307.   int pgn = atoi(pgnStr);
  308.  
  309.  // int dst = atoi(dstStr);
  310.  
  311.   CAN_TxHeaderTypeDef Header;
  312.   Header.ExtId = pgn;
  313.   Header.DLC = bytes < 8 ? bytes : 8;
  314.   Header.IDE = 0;
  315.   Header.RTR = 0;
  316.  
  317.   uint32_t usedMailbox;
  318.   HAL_StatusTypeDef status = HAL_CAN_AddTxMessage(&hcan, &Header,
  319.                                                   (uint8_t *)frameData, &usedMailbox);
  320.  
  321.   if (status == HAL_OK)
  322.   {
  323.      char lineBuff[100];
  324.  int pos = small_sprintf(lineBuff, "$PDGY,ACK,%s\r\n", buff);
  325.     if (pos < SerialTransmitSpace(&uc1))
  326.     {
  327.       __disable_irq();
  328.       sendString(&uc1, (char *)lineBuff, pos);
  329.       __enable_irq();
  330.     }
  331.   }
  332. }
  333.  
  334. /* USER CODE END 0 */
  335.  
  336. /**
  337.  * @brief  The application entry point.
  338.  * @retval int
  339.  */
  340. int main(void)
  341. {
  342.   /* USER CODE BEGIN 1 */
  343.  
  344.   /* USER CODE END 1 */
  345.  
  346.   /* MCU Configuration--------------------------------------------------------*/
  347.  
  348.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  349.   HAL_Init();
  350.  
  351.   /* USER CODE BEGIN Init */
  352.  
  353.   /* USER CODE END Init */
  354.  
  355.   /* Configure the system clock */
  356.   SystemClock_Config();
  357.  
  358.   /* USER CODE BEGIN SysInit */
  359.   cc_init();
  360.  
  361.   /* USER CODE END SysInit */
  362.  
  363.   /* Initialize all configured peripherals */
  364.   MX_GPIO_Init();
  365.   MX_CAN_Init();
  366.   MX_USART1_UART_Init();
  367.   MX_SPI1_Init();
  368.   /* USER CODE BEGIN 2 */
  369.  
  370.   HAL_CAN_Start(&hcan);
  371.  
  372.   init_usart_ctl(&uc1, &huart1,
  373.                  tx_buffer,
  374.                  rx_buffer,
  375.                  TX_BUFFER_SIZE,
  376.                  RX_BUFFER_SIZE);
  377.  
  378.   EnableSerialRxInterrupt(&uc1);
  379.  
  380.   // Activate the notification
  381.   HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING);
  382.  
  383.   // send out a version string on the serial port
  384.   sendString(&uc1, (char *)version, sizeof(version));
  385.  
  386.   uint32_t sendTime = HAL_GetTick() + 1000;
  387.   char cmdBuff[100];
  388.  
  389.   // serial utils library command editor
  390.   editBuffer cmdEdit;
  391.  
  392.   initReadLine(&cmdEdit, cmdBuff, 100, READLINES_CR);
  393.  
  394.   for (int i = 0; i < CONTEXTS; ++i)
  395.     resetContext(&contexts[i]);
  396.  
  397.   /* USER CODE END 2 */
  398.  
  399.   /* Infinite loop */
  400.   /* USER CODE BEGIN WHILE */
  401.   while (1)
  402.   {
  403.     /* USER CODE END WHILE */
  404.  
  405.     /* USER CODE BEGIN 3 */
  406.  
  407.     editBufferReturn ret = readLine(&uc1, &cmdEdit);
  408.  
  409.     if (ret == EDIT_CR)
  410.     {
  411.       processCmd(cmdBuff, charCount(&cmdEdit));
  412.       resetInput(&cmdEdit);
  413.     }
  414.  
  415.     if (HAL_GetTick() > sendTime)
  416.     {
  417.       sendTime += 1000;
  418.       heartBeat();
  419.       cc_display(2);
  420.     }
  421.  
  422.     for (int i = 0; i < CONTEXTS; ++i)
  423.     {
  424.       contextType *ctx = &contexts[i];
  425.       /// check for too old
  426.       //   if (ctx->status == ACCEPT && ctx->payloadTimestamp < old)
  427.       //   {
  428.       //     resetContext(ctx);
  429.       //     continue;
  430.       //   }
  431.  
  432.       if (ctx->status == COMPLETE)
  433.       {
  434.         __disable_irq();
  435.  
  436.         uint8_t prio = (ctx->payloadId >> 26) & 0x7;
  437.         uint8_t src = ctx->payloadId & 0xFF;
  438.         uint8_t dst = 255;
  439.         // mask out the PGN field as 18 bits.
  440.         uint32_t pgn = (ctx->payloadId >> 8) & ((1 << 18) - 1);
  441.         uint8_t pf = (pgn >> 8) & 0xFF;
  442.  
  443.         if (pf < 240)
  444.         {
  445.           // process PS if in PDU1 , address is low byte
  446.           dst = pgn & 0xFF;
  447.           pgn = pgn & 0x3FF00;
  448.         }
  449.  
  450.         char lineBuff[300];
  451.         size_t pos = small_sprintf(lineBuff, "!PDGY,%ld,%d,%d,%d,%ld.%03ld,",
  452.                                    pgn,  // PGN
  453.                                    prio, // priority
  454.                                    src,  // source address
  455.                                    dst,  // destination address
  456.  
  457.                                    ctx->payloadTimestamp / 1000, // milliseconds
  458.                                    ctx->payloadTimestamp % 1000);
  459.  
  460.         size_t base64_len;
  461.         base64_encode(ctx->payloadBuffer,
  462.                       ctx->payloadTotal,
  463.                       lineBuff + pos,
  464.                       &base64_len);
  465.  
  466.         pos += base64_len;
  467.         lineBuff[pos++] = '\r';
  468.         lineBuff[pos++] = '\n';
  469.         __enable_irq();
  470.  
  471.         // skip sending if this would overrun the buffer
  472.         if (pos < SerialTransmitSpace(&uc1))
  473.           sendString(&uc1, lineBuff, pos);
  474.         __disable_irq();
  475.  
  476.         resetContext(ctx);
  477.         __enable_irq();
  478.       }
  479.     }
  480.   }
  481.   /* USER CODE END 3 */
  482. }
  483.  
  484. /**
  485.  * @brief System Clock Configuration
  486.  * @retval None
  487.  */
  488. void SystemClock_Config(void)
  489. {
  490.   RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  491.   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  492.  
  493.   /** Initializes the RCC Oscillators according to the specified parameters
  494.    * in the RCC_OscInitTypeDef structure.
  495.    */
  496.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  497.   RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  498.   RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  499.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  500.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2;
  501.   RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL16;
  502.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  503.   {
  504.     Error_Handler();
  505.   }
  506.  
  507.   /** Initializes the CPU, AHB and APB buses clocks
  508.    */
  509.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
  510.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  511.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  512.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  513.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
  514.  
  515.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  516.   {
  517.     Error_Handler();
  518.   }
  519. }
  520.  
  521. /**
  522.  * @brief CAN Initialization Function
  523.  * @param None
  524.  * @retval None
  525.  */
  526. static void MX_CAN_Init(void)
  527. {
  528.  
  529.   /* USER CODE BEGIN CAN_Init 0 */
  530.  
  531.   /* USER CODE END CAN_Init 0 */
  532.  
  533.   /* USER CODE BEGIN CAN_Init 1 */
  534.  
  535.   /* USER CODE END CAN_Init 1 */
  536.   hcan.Instance = CAN1;
  537.   hcan.Init.Prescaler = 16;
  538.   hcan.Init.Mode = CAN_MODE_NORMAL;
  539.   hcan.Init.SyncJumpWidth = CAN_SJW_2TQ;
  540.   hcan.Init.TimeSeg1 = CAN_BS1_3TQ;
  541.   hcan.Init.TimeSeg2 = CAN_BS2_4TQ;
  542.   hcan.Init.TimeTriggeredMode = DISABLE;
  543.   hcan.Init.AutoBusOff = DISABLE;
  544.   hcan.Init.AutoWakeUp = DISABLE;
  545.   hcan.Init.AutoRetransmission = ENABLE;
  546.   hcan.Init.ReceiveFifoLocked = DISABLE;
  547.   hcan.Init.TransmitFifoPriority = DISABLE;
  548.   if (HAL_CAN_Init(&hcan) != HAL_OK)
  549.   {
  550.     Error_Handler();
  551.   }
  552.   /* USER CODE BEGIN CAN_Init 2 */
  553.   /* USER CODE BEGIN CAN_Init 2 */
  554.  
  555.   // allow absolutely everything into filter
  556.   CAN_FilterTypeDef filterConfig;
  557.   filterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
  558.   filterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
  559.   filterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;
  560.   filterConfig.FilterActivation = CAN_FILTER_ENABLE;
  561.   filterConfig.FilterBank = 0;
  562.  
  563.   CAN_FilterMaskEXT(&filterConfig, 0, 0);
  564.  
  565.   HAL_CAN_ConfigFilter(&hcan, &filterConfig);
  566.  
  567.   /* USER CODE END CAN_Init 2 */
  568. }
  569.  
  570. /**
  571.  * @brief SPI1 Initialization Function
  572.  * @param None
  573.  * @retval None
  574.  */
  575. static void MX_SPI1_Init(void)
  576. {
  577.  
  578.   /* USER CODE BEGIN SPI1_Init 0 */
  579.  
  580.   /* USER CODE END SPI1_Init 0 */
  581.  
  582.   /* USER CODE BEGIN SPI1_Init 1 */
  583.  
  584.   /* USER CODE END SPI1_Init 1 */
  585.   /* SPI1 parameter configuration*/
  586.   hspi1.Instance = SPI1;
  587.   hspi1.Init.Mode = SPI_MODE_MASTER;
  588.   hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  589.   hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  590.   hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  591.   hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  592.   hspi1.Init.NSS = SPI_NSS_SOFT;
  593.   hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
  594.   hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  595.   hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  596.   hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  597.   hspi1.Init.CRCPolynomial = 10;
  598.   if (HAL_SPI_Init(&hspi1) != HAL_OK)
  599.   {
  600.     Error_Handler();
  601.   }
  602.   /* USER CODE BEGIN SPI1_Init 2 */
  603.  
  604.   /* USER CODE END SPI1_Init 2 */
  605. }
  606.  
  607. /**
  608.  * @brief USART1 Initialization Function
  609.  * @param None
  610.  * @retval None
  611.  */
  612. static void MX_USART1_UART_Init(void)
  613. {
  614.  
  615.   /* USER CODE BEGIN USART1_Init 0 */
  616.  
  617.   /* USER CODE END USART1_Init 0 */
  618.  
  619.   /* USER CODE BEGIN USART1_Init 1 */
  620.  
  621.   /* USER CODE END USART1_Init 1 */
  622.   huart1.Instance = USART1;
  623.   huart1.Init.BaudRate = 460800;
  624.   huart1.Init.WordLength = UART_WORDLENGTH_8B;
  625.   huart1.Init.StopBits = UART_STOPBITS_1;
  626.   huart1.Init.Parity = UART_PARITY_NONE;
  627.   huart1.Init.Mode = UART_MODE_TX_RX;
  628.   huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  629.   huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  630.   if (HAL_UART_Init(&huart1) != HAL_OK)
  631.   {
  632.     Error_Handler();
  633.   }
  634.   /* USER CODE BEGIN USART1_Init 2 */
  635.  
  636.   /* USER CODE END USART1_Init 2 */
  637. }
  638.  
  639. /**
  640.  * @brief GPIO Initialization Function
  641.  * @param None
  642.  * @retval None
  643.  */
  644. static void MX_GPIO_Init(void)
  645. {
  646.   GPIO_InitTypeDef GPIO_InitStruct = {0};
  647.   /* USER CODE BEGIN MX_GPIO_Init_1 */
  648.   /* USER CODE END MX_GPIO_Init_1 */
  649.  
  650.   /* GPIO Ports Clock Enable */
  651.   __HAL_RCC_GPIOC_CLK_ENABLE();
  652.   __HAL_RCC_GPIOD_CLK_ENABLE();
  653.   __HAL_RCC_GPIOA_CLK_ENABLE();
  654.  
  655.   /*Configure GPIO pin Output Level */
  656.   HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
  657.  
  658.   /*Configure GPIO pin Output Level */
  659.   HAL_GPIO_WritePin(GPIOA, SPI1_CS_Pin | SPI1_CD_Pin | SPI1_RESET_Pin, GPIO_PIN_RESET);
  660.  
  661.   /*Configure GPIO pin : LED_Pin */
  662.   GPIO_InitStruct.Pin = LED_Pin;
  663.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  664.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  665.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  666.   HAL_GPIO_Init(LED_GPIO_Port, &GPIO_InitStruct);
  667.  
  668.   /*Configure GPIO pins : SPI1_CS_Pin SPI1_CD_Pin SPI1_RESET_Pin */
  669.   GPIO_InitStruct.Pin = SPI1_CS_Pin | SPI1_CD_Pin | SPI1_RESET_Pin;
  670.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  671.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  672.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  673.   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  674.  
  675.   /* USER CODE BEGIN MX_GPIO_Init_2 */
  676.   /* USER CODE END MX_GPIO_Init_2 */
  677. }
  678.  
  679. /* USER CODE BEGIN 4 */
  680.  
  681. /* USER CODE END 4 */
  682.  
  683. /**
  684.  * @brief  This function is executed in case of error occurrence.
  685.  * @retval None
  686.  */
  687. void Error_Handler(void)
  688. {
  689.   /* USER CODE BEGIN Error_Handler_Debug */
  690.   /* User can add his own implementation to report the HAL error return state */
  691.  
  692.   /* USER CODE END Error_Handler_Debug */
  693. }
  694.  
  695. #ifdef USE_FULL_ASSERT
  696. /**
  697.  * @brief  Reports the name of the source file and the source line number
  698.  *         where the assert_param error has occurred.
  699.  * @param  file: pointer to the source file name
  700.  * @param  line: assert_param error line source number
  701.  * @retval None
  702.  */
  703. void assert_failed(uint8_t *file, uint32_t line)
  704. {
  705.   /* USER CODE BEGIN 6 */
  706.   /* User can add his own implementation to report the file name and line number,
  707.      tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  708.   /* USER CODE END 6 */
  709. }
  710. #endif /* USE_FULL_ASSERT */
  711.