#include "stm32c0xx_hal.h"
#include <stdlib.h>
#include <stdbool.h>
UART_HandleTypeDef huart2;
// Настройка `_write` для использования `printf`
int _write(int file, char *ptr, int len) {
HAL_UART_Transmit(&huart2, (uint8_t *)ptr, len, HAL_MAX_DELAY);
return len;
}
// Константы
#define LED_COUNT 2
#define BUTTON_COUNT 2
// Пины для светодиодов
const uint16_t LED_Pins[LED_COUNT] = { GPIO_PIN_5, GPIO_PIN_6 }; // PA5, PA6
#define LED_GPIO_Port GPIOA
// Пины для кнопок
const uint16_t Button_Pins[BUTTON_COUNT] = { GPIO_PIN_0, GPIO_PIN_1 }; // PB0, PB1
#define Button_GPIO_Port GPIOB
// Игровые состояния
typedef enum {
GAME_INIT,
GAME_SHOW_SEQUENCE,
GAME_PLAYER_INPUT,
GAME_CHECK_RESULT,
GAME_OVER
} GameState;
// Переменные
GameState currentState = GAME_INIT;
uint8_t sequence[10]; // Последовательность светодиодов
uint8_t sequenceLength = 0; // Текущая длина последовательности
uint8_t playerIndex = 0;
// Прототипы функций
void GenerateSequence(void);
void ShowSequence(void);
uint8_t GetButtonInput(void);
void SetAllLEDs(uint8_t state);
void LightLED(uint8_t ledIndex);
void MX_GPIO_Init(void);
void MX_USART2_UART_Init(void);
// Основной цикл
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART2_UART_Init();
printf("Starting the game...\r\n");
while (1) {
switch (currentState) {
case GAME_INIT:
sequenceLength = 1; // Начальная длина последовательности
GenerateSequence();
printf("Game initialized. Sequence length: %d\r\n", sequenceLength);
currentState = GAME_SHOW_SEQUENCE;
break;
case GAME_SHOW_SEQUENCE:
printf("Showing sequence...\r\n");
ShowSequence();
playerIndex = 0;
currentState = GAME_PLAYER_INPUT;
break;
case GAME_PLAYER_INPUT:
{
printf("Waiting for player input. Player index = %d\r\n", playerIndex);
uint8_t input = GetButtonInput();
if (input != 0xFF) { // Если есть нажатие
printf("Button pressed: %d\r\n", input);
if (input == sequence[playerIndex]) {
playerIndex++;
printf("Correct! Player index = %d, sequenceLength = %d\r\n", playerIndex, sequenceLength);
if (playerIndex == sequenceLength) {
sequenceLength++;
currentState = GAME_CHECK_RESULT;
}
} else {
printf("Incorrect button! Expected: %d, got: %d\r\n", sequence[playerIndex], input);
currentState = GAME_OVER;
}
}
break;
}
case GAME_CHECK_RESULT:
printf("Checking result...\r\n");
if (sequenceLength > sizeof(sequence)) {
printf("Player wins! Sequence completed.\r\n");
currentState = GAME_OVER;
} else {
HAL_Delay(1000); // Короткая пауза перед следующей последовательностью
currentState = GAME_SHOW_SEQUENCE;
}
break;
case GAME_OVER:
printf("Game Over. Restarting...\r\n");
SetAllLEDs(1); // Все светодиоды горят 2 секунды
HAL_Delay(2000);
SetAllLEDs(0);
currentState = GAME_INIT;
break;
}
}
}
// Генерация последовательности
void GenerateSequence(void) {
for (uint8_t i = 0; i < sizeof(sequence); i++) {
sequence[i] = rand() % LED_COUNT;
}
}
// Показ последовательности
void ShowSequence(void) {
for (uint8_t i = 0; i < sequenceLength; i++) {
LightLED(sequence[i]);
HAL_Delay(500);
SetAllLEDs(0);
HAL_Delay(200);
}
}
// Получение нажатия кнопки
uint8_t GetButtonInput(void) {
for (uint8_t i = 0; i < BUTTON_COUNT; i++) {
if (HAL_GPIO_ReadPin(Button_GPIO_Port, Button_Pins[i]) == GPIO_PIN_SET) {
while (HAL_GPIO_ReadPin(Button_GPIO_Port, Button_Pins[i]) == GPIO_PIN_SET); // Ждем отпускания
return i;
}
}
return 0xFF; // Нет нажатия
}
// Управление светодиодами
void SetAllLEDs(uint8_t state) {
for (uint8_t i = 0; i < LED_COUNT; i++) {
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pins[i], state ? GPIO_PIN_SET : GPIO_PIN_RESET);
}
}
void LightLED(uint8_t ledIndex) {
SetAllLEDs(0);
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pins[ledIndex], GPIO_PIN_SET);
}
// Инициализация GPIO
void MX_GPIO_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
// Настройка светодиодов
GPIO_InitStruct.Pin = LED_Pins[0] | LED_Pins[1];
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);
// Настройка кнопок
GPIO_InitStruct.Pin = Button_Pins[0] | Button_Pins[1];
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(Button_GPIO_Port, &GPIO_InitStruct);
}
// Настройка UART
void MX_USART2_UART_Init(void) {
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;
if (HAL_UART_Init(&huart2) != HAL_OK) {
printf("UART initialization failed\r\n");
}
}
// Настройка системных часов
void SystemClock_Config(void) {
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV1;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);
}