#include "stm32c0xx.h"
#include <stdlib.h>
#include <stdbool.h>
// Определение пинов
#define USER_BUTTON_PIN GPIO_PIN_13
#define USER_BUTTON_PORT GPIOC
#define LED_PINS (GPIO_PIN_3 | GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_9)
#define LED_PORT GPIOA
#define BUTTON_PINS (GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6)
#define BUTTON_PORT GPIOB
// Состояния игры
typedef enum {
GAME_IDLE,
GAME_WAITING,
GAME_RUNNING,
GAME_FINISHED,
GAME_FALSE_START
} GameState;
volatile GameState gameState = GAME_IDLE;
volatile uint32_t randomDelay = 0;
volatile uint32_t timerCount = 0;
volatile uint8_t winner = 0;
volatile bool buttonPressed[4] = {false, false, false, false};
// Прототипы функций
void SystemClock_Config(void);
void GPIO_Init(void);
void SysTick_Init(void);
void EXTI_Init(void);
void delay(uint32_t ms);
uint32_t getRandomDelay(uint32_t min, uint32_t max);
void startRound(void);
void endRound(uint8_t player);
void falseStart(uint8_t player);
// Объявляем weak-символы для обработчиков прерываний
__attribute__((weak)) void SysTick_Handler(void);
__attribute__((weak)) void EXTI4_15_IRQHandler(void);
// Наши обработчики событий
void OnSysTick(void) {
timerCount++;
if (gameState == GAME_WAITING && timerCount >= randomDelay) {
gameState = GAME_RUNNING;
HAL_GPIO_WritePin(LED_PORT, LED_PINS, GPIO_PIN_SET);
}
}
void OnEXTI4_15(void) {
// Проверка кнопки игрока 1 (PB3)
if (EXTI->RPR1 & GPIO_PIN_3) {
EXTI->RPR1 = GPIO_PIN_3;
if (gameState == GAME_RUNNING) {
endRound(1);
} else if (gameState == GAME_WAITING) {
falseStart(1);
}
}
// Проверка кнопки игрока 2 (PB4)
if (EXTI->RPR1 & GPIO_PIN_4) {
EXTI->RPR1 = GPIO_PIN_4;
if (gameState == GAME_RUNNING) {
endRound(2);
} else if (gameState == GAME_WAITING) {
falseStart(2);
}
}
// Проверка кнопки игрока 3 (PB5)
if (EXTI->RPR1 & GPIO_PIN_5) {
EXTI->RPR1 = GPIO_PIN_5;
if (gameState == GAME_RUNNING) {
endRound(3);
} else if (gameState == GAME_WAITING) {
falseStart(3);
}
}
// Проверка кнопки игрока 4 (PB6)
if (EXTI->RPR1 & GPIO_PIN_6) {
EXTI->RPR1 = GPIO_PIN_6;
if (gameState == GAME_RUNNING) {
endRound(4);
} else if (gameState == GAME_WAITING) {
falseStart(4);
}
}
// Проверка USER_BUTTON (PC13)
if (EXTI->RPR1 & USER_BUTTON_PIN) {
EXTI->RPR1 = USER_BUTTON_PIN;
if (gameState == GAME_IDLE || gameState == GAME_FINISHED || gameState == GAME_FALSE_START) {
startRound();
}
}
}
// Переопределение weak-обработчиков
void SysTick_Handler(void) {
OnSysTick();
}
void EXTI4_15_IRQHandler(void) {
OnEXTI4_15();
}
int main(void) {
HAL_Init();
SystemClock_Config();
GPIO_Init();
SysTick_Init();
EXTI_Init();
while (1) {
if (gameState == GAME_FALSE_START) {
HAL_GPIO_TogglePin(LED_PORT, GPIO_PIN_3 << (winner - 1));
delay(100);
}
}
}
// Остальные функции остаются без изменений
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;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
while(1);
}
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_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) {
while(1);
}
}
void GPIO_Init(void) {
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = LED_PINS;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct);
GPIO_InitStruct.Pin = BUTTON_PINS;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(BUTTON_PORT, &GPIO_InitStruct);
GPIO_InitStruct.Pin = USER_BUTTON_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(USER_BUTTON_PORT, &GPIO_InitStruct);
}
void SysTick_Init(void) {
SysTick_Config(SystemCoreClock / 1000);
}
void EXTI_Init(void) {
// Настройка прерываний для кнопок игроков (PB3-PB6)
EXTI->EXTICR[0] |= (0x01 << (8 * 3)); // PB3
EXTI->EXTICR[0] |= (0x01 << (8 * 4)); // PB4
EXTI->EXTICR[1] |= (0x01 << (8 * (5-4))); // PB5
EXTI->EXTICR[1] |= (0x01 << (8 * (6-4))); // PB6
// Настройка прерываний для USER_BUTTON (PC13)
EXTI->EXTICR[3] |= (0x02 << (8 * (13-12)));
// Включение прерываний по фронту
EXTI->RTSR1 |= (GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | USER_BUTTON_PIN);
// Разрешение прерываний
EXTI->IMR1 |= (GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | USER_BUTTON_PIN);
// Настройка приоритета прерывания
NVIC_SetPriority(EXTI4_15_IRQn, 0);
NVIC_EnableIRQ(EXTI4_15_IRQn);
}
void delay(uint32_t ms) {
uint32_t start = timerCount;
while ((timerCount - start) < ms);
}
uint32_t getRandomDelay(uint32_t min, uint32_t max) {
return min + (rand() % (max - min + 1));
}
void startRound(void) {
HAL_GPIO_WritePin(LED_PORT, LED_PINS, GPIO_PIN_RESET);
randomDelay = getRandomDelay(5000, 10000);
timerCount = 0;
for (int i = 0; i < 4; i++) {
buttonPressed[i] = false;
}
gameState = GAME_WAITING;
winner = 0;
}
void endRound(uint8_t player) {
if (gameState == GAME_RUNNING && !buttonPressed[player-1]) {
buttonPressed[player-1] = true;
bool firstPress = true;
for (int i = 0; i < 4; i++) {
if (i != (player-1) && buttonPressed[i]) {
firstPress = false;
break;
}
}
if (firstPress) {
gameState = GAME_FINISHED;
winner = player;
HAL_GPIO_WritePin(LED_PORT, LED_PINS, GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED_PORT, GPIO_PIN_3 << (player-1), GPIO_PIN_SET);
}
}
}
void falseStart(uint8_t player) {
gameState = GAME_FALSE_START;
winner = player;
HAL_GPIO_WritePin(LED_PORT, LED_PINS, GPIO_PIN_RESET);
}