/*
* Лабораторная работа 1: Работа с таймерами и портами ввода-вывода STM32
* Микроконтроллер: STM32F103C8 (Blue Pill)
* Framework: Arduino (stm32duino) для Wokwi
*
* ПРОСТАЯ И НАДЁЖНАЯ ВЕРСИЯ
*
* Использует прерывания таймера для генерации точного сигнала 1 кГц
*/
#include <Arduino.h>
// Определение пинов
#define LED_USER PA5 // Генерация сигнала 1 кГц
#define LED_BUILTIN PC13 // Индикатор работы
// Параметры
#define SIGNAL_FREQ_HZ 1000 // Частота сигнала 1 кГц
// Глобальные переменные
HardwareTimer *MyTim = NULL;
volatile bool ledState = false;
void setup() {
Serial.begin(115200);
Serial.println("=================================");
Serial.println(" Лабораторная работа 1 - STM32");
Serial.println("=================================");
Serial.println();
Serial.print("SYSCLK: ");
Serial.print(SystemCoreClock / 1000000);
Serial.println(" МГц");
Serial.println();
// Настройка GPIO
pinMode(LED_BUILTIN, OUTPUT);
pinMode(LED_USER, OUTPUT);
digitalWrite(LED_USER, LOW);
// Инициализация таймера для генерации сигнала
initTimer();
Serial.println("Инициализация завершена!");
Serial.print("Генерация сигнала ");
Serial.print(SIGNAL_FREQ_HZ);
Serial.println(" Гц на пине PA5");
Serial.println();
}
void loop() {
// Мигание встроенным светодиодом
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
// Информация о работе
static unsigned long lastTime = 0;
static int seconds = 0;
if (millis() - lastTime >= 1000) {
lastTime = millis();
seconds++;
Serial.print("Работа: ");
Serial.print(seconds);
Serial.print(" сек | Частота на PA5: ");
Serial.print(SIGNAL_FREQ_HZ);
Serial.println(" Гц");
}
delay(1000);
}
/**
* @brief Инициализация таймера для генерации сигнала заданной частоты
* @note Использует TIM2 с прерываниями для переключения PA5
*/
void initTimer() {
// TIM2 используется для PA5
MyTim = new HardwareTimer(TIM2);
// Для генерации меандра (50% duty cycle) нужна частота прерываний в 2 раза выше
// Частота прерываний = SIGNAL_FREQ_HZ * 2
uint32_t interruptFreq = SIGNAL_FREQ_HZ * 2;
// Настройка частоты прерываний
MyTim->setOverflow(interruptFreq, HERTZ_FORMAT);
// Привязка функции обработчика прерывания
MyTim->attachInterrupt(timerCallback);
// Запуск таймера
MyTim->resume();
Serial.println("Таймер TIM2 настроен:");
Serial.print(" Частота прерываний: ");
Serial.print(interruptFreq);
Serial.println(" Гц");
Serial.print(" Частота выходного сигнала: ");
Serial.print(SIGNAL_FREQ_HZ);
Serial.println(" Гц");
}
/**
* @brief Обработчик прерывания таймера
* @note Вызывается с частотой SIGNAL_FREQ_HZ * 2
* Переключает состояние пина PA5
*/
void timerCallback() {
// Переключение состояния пина PA5
ledState = !ledState;
digitalWrite(LED_USER, ledState);
}