/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * Copyright (c) 2026 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include #include /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ #define ROWS 7 #define COLS 96 #define NUM_CHIPS 12 /* 12 x 8 bits = 96 column bits */ #define ROW_DWELL 500 /* microseconds per row — tune for flicker/ghosting */ #define UART_BUF 128 #define WIDE_COLS 512 /* pre-render buffer width */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ SPI_HandleTypeDef hspi1; UART_HandleTypeDef huart2; /* USER CODE BEGIN PV */ /* Row pin lookup — matches CubeMX GPIO labels */ typedef struct { GPIO_TypeDef *port; uint16_t pin; } RowPin; static const RowPin ROW_PINS[ROWS] = { {ROW_0_GPIO_Port, ROW_0_Pin}, /* ROW_0 — PB0 */ {ROW_1_GPIO_Port, ROW_1_Pin}, /* ROW_1 — PA0 */ {ROW_2_GPIO_Port, ROW_2_Pin}, /* ROW_2 — PA1 */ {ROW_3_GPIO_Port, ROW_3_Pin}, /* ROW_3 — PB4 */ {ROW_4_GPIO_Port, ROW_4_Pin}, /* ROW_4 — PB5 */ {ROW_5_GPIO_Port, ROW_5_Pin}, /* ROW_5 — PA11 */ {ROW_6_GPIO_Port, ROW_6_Pin}, /* ROW_6 — PA8 */ }; /* Framebuffer — fb[row][chip], each byte = 8 column bits */ static uint8_t fb[ROWS][NUM_CHIPS]; /* Pre-rendered wide scroll buffer */ static uint8_t wide[ROWS][WIDE_COLS]; static uint16_t wide_cols = 0; /* 0 = no message yet, display stays blank */ static int32_t scroll_x = 0; /* UART receive */ static uint8_t uart_rx_byte; static char uart_buf[UART_BUF]; static uint8_t uart_idx = 0; static uint8_t new_message = 0; static char message[UART_BUF] = ""; /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_SPI1_Init(void); static void MX_USART2_UART_Init(void); /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ /* 5x7 font, ASCII 32-90 Each glyph = 5 bytes (columns), bit0 = top row */ static const uint8_t FONT[][5] = { {0x00,0x00,0x00,0x00,0x00}, /* ' ' 32 */ {0x00,0x00,0x5F,0x00,0x00}, /* '!' */ {0x00,0x07,0x00,0x07,0x00}, /* '"' */ {0x14,0x7F,0x14,0x7F,0x14}, /* '#' */ {0x24,0x2A,0x7F,0x2A,0x12}, /* '$' */ {0x23,0x13,0x08,0x64,0x62}, /* '%' */ {0x36,0x49,0x55,0x22,0x50}, /* '&' */ {0x00,0x05,0x03,0x00,0x00}, /* ''' */ {0x00,0x1C,0x22,0x41,0x00}, /* '(' */ {0x00,0x41,0x22,0x1C,0x00}, /* ')' */ {0x08,0x2A,0x1C,0x2A,0x08}, /* '*' */ {0x08,0x08,0x3E,0x08,0x08}, /* '+' */ {0x00,0x50,0x30,0x00,0x00}, /* ',' */ {0x08,0x08,0x08,0x08,0x08}, /* '-' */ {0x00,0x60,0x60,0x00,0x00}, /* '.' */ {0x20,0x10,0x08,0x04,0x02}, /* '/' */ {0x3E,0x51,0x49,0x45,0x3E}, /* '0' */ {0x00,0x42,0x7F,0x40,0x00}, /* '1' */ {0x42,0x61,0x51,0x49,0x46}, /* '2' */ {0x21,0x41,0x45,0x4B,0x31}, /* '3' */ {0x18,0x14,0x12,0x7F,0x10}, /* '4' */ {0x27,0x45,0x45,0x45,0x39}, /* '5' */ {0x3C,0x4A,0x49,0x49,0x30}, /* '6' */ {0x01,0x71,0x09,0x05,0x03}, /* '7' */ {0x36,0x49,0x49,0x49,0x36}, /* '8' */ {0x06,0x49,0x49,0x29,0x1E}, /* '9' */ {0x00,0x36,0x36,0x00,0x00}, /* ':' */ {0x00,0x56,0x36,0x00,0x00}, /* ';' */ {0x00,0x08,0x14,0x22,0x41}, /* '<' */ {0x14,0x14,0x14,0x14,0x14}, /* '=' */ {0x41,0x22,0x14,0x08,0x00}, /* '>' */ {0x02,0x01,0x51,0x09,0x06}, /* '?' */ {0x32,0x49,0x79,0x41,0x3E}, /* '@' */ {0x7E,0x09,0x09,0x09,0x7E}, /* 'A' */ {0x7F,0x49,0x49,0x49,0x36}, /* 'B' */ {0x3E,0x41,0x41,0x41,0x22}, /* 'C' */ {0x7F,0x41,0x41,0x41,0x3E}, /* 'D' */ {0x7F,0x49,0x49,0x49,0x41}, /* 'E' */ {0x7F,0x09,0x09,0x09,0x01}, /* 'F' */ {0x3E,0x41,0x49,0x49,0x7A}, /* 'G' */ {0x7F,0x08,0x08,0x08,0x7F}, /* 'H' */ {0x41,0x7F,0x41,0x00,0x00}, /* 'I' */ {0x20,0x40,0x41,0x3F,0x01}, /* 'J' */ {0x7F,0x08,0x14,0x22,0x41}, /* 'K' */ {0x7F,0x40,0x40,0x40,0x40}, /* 'L' */ {0x7F,0x02,0x04,0x02,0x7F}, /* 'M' */ {0x7F,0x04,0x08,0x10,0x7F}, /* 'N' */ {0x3E,0x41,0x41,0x41,0x3E}, /* 'O' */ {0x7F,0x09,0x09,0x09,0x06}, /* 'P' */ {0x3E,0x41,0x51,0x21,0x5E}, /* 'Q' */ {0x7F,0x09,0x19,0x29,0x46}, /* 'R' */ {0x46,0x49,0x49,0x49,0x31}, /* 'S' */ {0x01,0x01,0x7F,0x01,0x01}, /* 'T' */ {0x3F,0x40,0x40,0x40,0x3F}, /* 'U' */ {0x1F,0x20,0x40,0x20,0x1F}, /* 'V' */ {0x7F,0x20,0x10,0x20,0x7F}, /* 'W' */ {0x63,0x14,0x08,0x14,0x63}, /* 'X' */ {0x03,0x04,0x78,0x04,0x03}, /* 'Y' */ {0x61,0x51,0x49,0x45,0x43}, /* 'Z' */ }; /* ── Microsecond busy-wait using DWT cycle counter ── */ static void delay_us(uint32_t us) { uint32_t start = DWT->CYCCNT; uint32_t ticks = (SystemCoreClock / 1000000U) * us; while ((DWT->CYCCNT - start) < ticks); } /* ── Turn all row pins off (HIGH = ULN2803A pulls gate low = MOSFET off) ── */ static void all_rows_off(void) { for (int i = 0; i < ROWS; i++) HAL_GPIO_WritePin(ROW_PINS[i].port, ROW_PINS[i].pin, GPIO_PIN_SET); } /* ── Send one row of column data via SPI then enable that row ── */ static void display_refresh(void) { for (int row = 0; row < ROWS; row++) { all_rows_off(); HAL_SPI_Transmit(&hspi1, fb[row], NUM_CHIPS, HAL_MAX_DELAY); /* LOW = ULN2803A releases gate = MOSFET on = row enabled */ HAL_GPIO_WritePin(ROW_PINS[row].port, ROW_PINS[row].pin, GPIO_PIN_RESET); delay_us(ROW_DWELL); } all_rows_off(); } /* ── Render message string into wide[] pixel buffer ── */ static void render_message(const char *msg) { memset(wide, 0, sizeof(wide)); uint16_t col = COLS; /* lead with one blank screen so text scrolls in */ while (*msg && col < (WIDE_COLS - 6)) { uint8_t c = (uint8_t)*msg++; /* Convert lowercase to uppercase */ if (c >= 'a' && c <= 'z') c -= 32; if (c >= 32 && c <= 90) { const uint8_t *glyph = FONT[c - 32]; for (int g = 0; g < 5 && col < WIDE_COLS; g++, col++) { for (int row = 0; row < ROWS; row++) { wide[row][col] = (glyph[g] >> row) & 1; } } } col++; /* one gap column between characters */ } wide_cols = col + COLS; /* scroll until text fully exits left edge */ scroll_x = 0; } /* ── Copy current scroll window from wide[] into fb[][] ── */ static void update_fb_from_scroll(void) { for (int row = 0; row < ROWS; row++) { memset(fb[row], 0, NUM_CHIPS); for (int col = 0; col < COLS; col++) { uint16_t src = (uint16_t)(scroll_x + col); if (src < WIDE_COLS && wide[row][src]) { int chip = col / 8; int bit = 7 - (col % 8); fb[row][chip] |= (uint8_t)(1 << bit); } } } } /* ── Arrive north star pixel map, 7 rows x 11 cols ── */ static const uint8_t STAR[7][11] = { {0,0,0,0,1,0,0,0,0,0,0}, {0,0,0,1,1,1,0,0,0,0,0}, {1,1,0,0,1,0,0,1,1,1,1}, {1,1,1,1,1,1,1,1,1,1,1}, {1,1,0,0,1,0,0,1,1,1,1}, {0,0,0,1,1,1,0,0,0,0,0}, {0,0,0,0,1,0,0,0,0,0,0}, }; /* ARRIVE — 6 chars, each 5 cols wide + 1 col gap = 36 cols total Rows 0-6, col order left to right: A R R I V E */ static const uint8_t ARRIVE_GLYPH[7][36] = { /* A R R I V E */ /* r0 */ {0,1,1,1,0,0, 0,1,1,1,0,0, 0,1,1,1,0,0, 0,1,1,1,0,0, 1,0,0,0,1,0, 1,1,1,1,1,0}, /* r1 */ {1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 0,0,1,0,0,0, 1,0,0,0,1,0, 1,0,0,0,0,0}, /* r2 */ {1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 0,0,1,0,0,0, 1,0,0,0,1,0, 1,0,0,0,0,0}, /* r3 */ {1,1,1,1,1,0, 1,1,1,1,0,0, 1,1,1,1,0,0, 0,0,1,0,0,0, 0,1,0,1,0,0, 1,1,1,1,0,0}, /* r4 */ {1,0,0,0,1,0, 1,0,1,0,0,0, 1,0,1,0,0,0, 0,0,1,0,0,0, 0,1,0,1,0,0, 1,0,0,0,0,0}, /* r5 */ {1,0,0,0,1,0, 1,0,0,1,0,0, 1,0,0,1,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 1,0,0,0,0,0}, /* r6 */ {1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 0,1,1,1,0,0, 0,0,1,0,0,0, 1,1,1,1,1,0}, }; /* ── Render logo into fb mask_col: columns < mask_col are hidden (wipe reveals right-to-left), -1 = show all ── */ static void render_logo(int star_col, int text_col, int mask_col) { memset(fb, 0, sizeof(fb)); /* Draw star */ for (int row = 0; row < 7; row++) { for (int sc = 0; sc < 11; sc++) { int col = star_col + sc; if (col >= 0 && col < COLS && STAR[row][sc]) { if (mask_col < 0 || col >= mask_col) { int chip = col / 8; int bit = 7 - (col % 8); fb[row][chip] |= (uint8_t)(1 << bit); } } } } /* Draw ARRIVE text */ for (int row = 0; row < 7; row++) { for (int tc = 0; tc < 36; tc++) { int col = text_col + tc; if (col >= 0 && col < COLS && ARRIVE_GLYPH[row][tc]) { if (mask_col < 0 || col >= mask_col) { int chip = col / 8; int bit = 7 - (col % 8); fb[row][chip] |= (uint8_t)(1 << bit); } } } } } /* ── Blank fb but keep specific rows lit (bitmask) ── */ static void render_logo_rows(int star_col, int text_col, uint8_t row_mask) { memset(fb, 0, sizeof(fb)); for (int row = 0; row < 7; row++) { if (!(row_mask & (1 << row))) continue; for (int sc = 0; sc < 11; sc++) { int col = star_col + sc; if (col >= 0 && col < COLS && STAR[row][sc]) { int chip = col / 8; int bit = 7 - (col % 8); fb[row][chip] |= (uint8_t)(1 << bit); } } for (int tc = 0; tc < 30; tc++) { int col = text_col + tc; if (col >= 0 && col < COLS && ARRIVE_GLYPH[row][tc]) { int chip = col / 8; int bit = 7 - (col % 8); fb[row][chip] |= (uint8_t)(1 << bit); } } } } /* ── Refresh for a given number of milliseconds ── */ static void refresh_for(uint32_t ms) { uint32_t t = HAL_GetTick(); while ((HAL_GetTick() - t) < ms) { display_refresh(); } } /* ── Arrive boot animation ── */ static void arrive_animation(void) { /* Logo layout — text LEFT, star RIGHT: ARRIVE = 36 cols, gap = 2, star = 11 cols → total = 49 cols centred on 96: start = (96 - 49) / 2 = 23 text_col = 23, star_col = 23 + 36 + 2 = 61 */ const int text_col = 23; const int star_col = 61; /* ── Phase 1: Star builds from centre outward ── */ /* Frame 1 — just centre cross */ memset(fb, 0, sizeof(fb)); for (int row = 0; row < 7; row++) { int col = star_col + 4; /* centre column of star */ int chip = col / 8; int bit = 7 - (col % 8); fb[row][chip] |= (uint8_t)(1 << bit); } /* horizontal bar centre */ for (int sc = 3; sc <= 5; sc++) { int col = star_col + sc; int chip = col / 8; int bit = 7 - (col % 8); fb[3][chip] |= (uint8_t)(1 << bit); } refresh_for(120); /* Frame 2 — inner star shape */ memset(fb, 0, sizeof(fb)); for (int row = 0; row < 7; row++) { for (int sc = 3; sc <= 7; sc++) { if (STAR[row][sc]) { int col = star_col + sc; int chip = col / 8; int bit = 7 - (col % 8); fb[row][chip] |= (uint8_t)(1 << bit); } } } refresh_for(120); /* Frame 3 — full star, text still hidden */ render_logo(star_col, text_col, star_col); /* mask hides everything left of star */ refresh_for(150); /* ── Phase 2: Glint pulse ── */ memset(fb, 0, sizeof(fb)); refresh_for(80); render_logo(star_col, text_col, star_col); refresh_for(80); memset(fb, 0, sizeof(fb)); refresh_for(60); render_logo(star_col, text_col, star_col); refresh_for(100); /* ── Phase 3: Wipe right-to-left — reveal ARRIVE sweeping from star leftward ── */ for (int mask = star_col; mask >= text_col - 1; mask -= 2) { render_logo(star_col, text_col, mask); refresh_for(18); } render_logo(star_col, text_col, -1); refresh_for(18); /* ── Phase 4: Hold ── */ refresh_for(2000); /* ── Phase 5: Fade out — rows extinguish top+bottom inward ── */ /* Order: 0,6 then 1,5 then 2,4 then 3 */ uint8_t row_mask = 0x7F; /* all 7 rows on */ row_mask &= ~(1 << 0); row_mask &= ~(1 << 6); render_logo_rows(star_col, text_col, row_mask); refresh_for(80); row_mask &= ~(1 << 1); row_mask &= ~(1 << 5); render_logo_rows(star_col, text_col, row_mask); refresh_for(80); row_mask &= ~(1 << 2); row_mask &= ~(1 << 4); render_logo_rows(star_col, text_col, row_mask); refresh_for(80); row_mask &= ~(1 << 3); memset(fb, 0, sizeof(fb)); refresh_for(80); /* Brief blank before scroll */ refresh_for(200); } void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if (huart->Instance == USART2) { char b = (char)uart_rx_byte; if (b == '\n' || b == '\r') { if (uart_idx > 0) { uart_buf[uart_idx] = '\0'; memcpy(message, uart_buf, uart_idx + 1); uart_idx = 0; new_message = 1; } } else if (uart_idx < UART_BUF - 1) { uart_buf[uart_idx++] = b; } /* Re-arm for next byte */ HAL_UART_Receive_IT(&huart2, &uart_rx_byte, 1); } } /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ MX_GPIO_Init(); MX_SPI1_Init(); MX_USART2_UART_Init(); /* USER CODE BEGIN 2 */ /* Enable DWT cycle counter for microsecond delays */ CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; DWT->CYCCNT = 0; DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; /* All rows off, blank display */ all_rows_off(); memset(fb, 0, sizeof(fb)); /* Start UART receive interrupt */ HAL_UART_Receive_IT(&huart2, &uart_rx_byte, 1); /* Render default message */ render_message(message); update_fb_from_scroll(); /* USER CODE END 2 */ /* USER CODE BEGIN WHILE */ /* Run boot animation */ arrive_animation(); update_fb_from_scroll(); uint32_t last_scroll = HAL_GetTick(); const uint32_t scroll_ms = 40; while (1) { if (new_message) { new_message = 0; render_message(message); } if ((HAL_GetTick() - last_scroll) >= scroll_ms) { last_scroll = HAL_GetTick(); scroll_x++; if (scroll_x >= wide_cols) { /* End of message — switch to next */ scroll_x = 0; } update_fb_from_scroll(); } display_refresh(); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST); RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV4; RCC_OscInitStruct.PLL.PLLN = 85; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) { Error_Handler(); } } /** * @brief SPI1 Initialization Function */ static void MX_SPI1_Init(void) { /* USER CODE BEGIN SPI1_Init 0 */ /* USER CODE END SPI1_Init 0 */ /* USER CODE BEGIN SPI1_Init 1 */ /* USER CODE END SPI1_Init 1 */ hspi1.Instance = SPI1; hspi1.Init.Mode = SPI_MODE_MASTER; hspi1.Init.Direction = SPI_DIRECTION_2LINES; hspi1.Init.DataSize = SPI_DATASIZE_8BIT; hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; hspi1.Init.NSS = SPI_NSS_HARD_OUTPUT; hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32; hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi1.Init.TIMode = SPI_TIMODE_DISABLE; hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi1.Init.CRCPolynomial = 7; hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE; hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE; if (HAL_SPI_Init(&hspi1) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN SPI1_Init 2 */ /* USER CODE END SPI1_Init 2 */ } /** * @brief USART2 Initialization Function */ static void MX_USART2_UART_Init(void) { /* USER CODE BEGIN USART2_Init 0 */ /* USER CODE END USART2_Init 0 */ /* USER CODE BEGIN USART2_Init 1 */ /* USER CODE END USART2_Init 1 */ huart2.Instance = USART2; huart2.Init.BaudRate = 115200; huart2.Init.WordLength = UART_WORDLENGTH_8B; huart2.Init.StopBits = UART_STOPBITS_1; huart2.Init.Parity = UART_PARITY_NONE; huart2.Init.Mode = UART_MODE_TX_RX; huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart2.Init.OverSampling = UART_OVERSAMPLING_16; huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; huart2.Init.ClockPrescaler = UART_PRESCALER_DIV1; huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; if (HAL_UART_Init(&huart2) != HAL_OK) { Error_Handler(); } if (HAL_UARTEx_SetTxFifoThreshold(&huart2, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK) { Error_Handler(); } if (HAL_UARTEx_SetRxFifoThreshold(&huart2, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK) { Error_Handler(); } if (HAL_UARTEx_DisableFifoMode(&huart2) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN USART2_Init 2 */ /* USER CODE END USART2_Init 2 */ } /** * @brief GPIO Initialization Function */ static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* USER CODE BEGIN MX_GPIO_Init_1 */ /* USER CODE END MX_GPIO_Init_1 */ __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); HAL_GPIO_WritePin(GPIOA, ROW_1_Pin|ROW_2_Pin|ROW_6_Pin|ROW_5_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOB, ROW_0_Pin|ROW_3_Pin|ROW_4_Pin|LED_Pin, GPIO_PIN_SET); GPIO_InitStruct.Pin = ROW_1_Pin|ROW_2_Pin|ROW_6_Pin|ROW_5_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = ROW_0_Pin|ROW_3_Pin|ROW_4_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_InitStruct.Pin = LED_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(LED_GPIO_Port, &GPIO_InitStruct); /* USER CODE BEGIN MX_GPIO_Init_2 */ /* USER CODE END MX_GPIO_Init_2 */ } /* USER CODE BEGIN 4 */ /* USER CODE END 4 */ /** * @brief This function is executed in case of error occurrence. */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ __disable_irq(); while (1) { } /* USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */