Загрузка данных


Погнали. Zadanie 2 — Input Capture. Здесь мы будем измерять, сколько микросекунд сигнал находится в состоянии HIGH.

По заданию нужно:

* Измерять импульсы длительностью до 10 секунд.
* Использовать аппаратный Input Capture.
* Выводить результат через semihosting.
* Учесть, что printf() работает медленнее, чем приходят импульсы.

Сделаем максимально простой рабочий вариант для STM32F411, TIM2 + TIM5.

1. Настраиваем CubeIDE (.ioc)

Наш PWM из первого задания остаётся на TIM2_CH1. Его выход нужно соединить проводом со входом Input Capture.

Соединяем PA0 и PA2 проводом. Это пример, если TIM2_CH1 действительно настроен на PA0.

В .ioc:

TIM5:

* Clock Source → Internal Clock
* Channel 3 → Input Capture direct mode
* Prescaler → 47
* Counter Period → 4294967295
* Input Capture Polarity → Both Edges (если доступно)
* NVIC Settings → TIM5 global interrupt → Enabled

При частоте таймера 48 MHz счётчик будет увеличиваться раз в 1 мкс. TIM5 — 32-битный таймер, поэтому он подходит для измерения до 10 секунд.

Важно: если CubeIDE не позволяет выбрать Both Edges, ниже покажу альтернативу. Для STM32F411 такой вариант зависит от возможностей конкретного канала и HAL.

2. Переменные

В main.c, внутри /* USER CODE BEGIN PV */:

volatile uint32_t start = 0;
volatile uint32_t czas = 0;
volatile int gotowe = 0;
volatile int poprzedni = 0;

Объяснение:

* start — когда начался импульс.
* czas — сколько длился HIGH.
* gotowe — флаг, что измерение завершено.
* poprzedni — запоминаем предыдущий уровень сигнала.

3. Запускаем Input Capture

В /* USER CODE BEGIN 2 */:

HAL_TIM_IC_Start_IT(&htim5, TIM_CHANNEL_3);

RU: Запускаем TIM5, который будет запоминать значение счётчика при изменении сигнала.

PL: Uruchamiamy Input Capture z przerwaniami, żeby mierzyć czas trwania impulsu.

4. Самое главное — callback

В /* USER CODE BEGIN 4 */:

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == TIM5 &&
        htim->Channel == HAL_TIM_ACTIVE_CHANNEL_3)
    {
        uint32_t teraz =
            HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_3);
        int stan = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_2);
        if (stan == GPIO_PIN_SET)
        {
            start = teraz;
        }
        else
        {
            czas = teraz - start;
            gotowe = 1;
        }
    }
}

RU: Когда приходит передний фронт, сохраняем время начала. Когда приходит задний фронт, вычитаем начало из конца и получаем длительность импульса.

PL: Przy zboczu narastającym zapisujemy początek impulsu, a przy zboczu opadającym obliczamy różnicę wartości licznika.

Здесь уровень PA2 используется для определения фронта. Для надёжного измерения лучше аппаратно разделить захват переднего и заднего фронтов на два канала либо переключать полярность захвата; чтение GPIO внутри callback может ошибиться на коротких импульсах.

5. Вывод результата

В основной while(1):

if (gotowe)
{
    gotowe = 0;
    printf("Czas HIGH: %lu us\n",
           (unsigned long)czas);
}

Но есть важная проблема: printf() через semihosting медленный. Пока он печатает, новые измерения могут перезаписать czas.

Для быстрого первого теста такой вариант подойдёт, но для выполнения требования преподавателя нужен буфер результатов или счётчик пропущенных измерений.

6. Как проверить

В первом задании поставь:

Czestotliwosc: 1000
Wypelnienie: 25

Ожидаемый результат:

T=\frac{1}{1000}=1000\ \mu sT_{HIGH}=1000\cdot0.25=250\ \mu s

В консоли должно быть примерно:

Czas HIGH: 250 us

Если у тебя настроен PWM на другом пине или канале, нужно изменить соединение.

Что сказать преподавателю

Wykorzystuję timer TIM5 z funkcją Input Capture. Timer pracuje z częstotliwością 1 MHz, więc jeden takt odpowiada jednej mikrosekundzie. Zapisuję wartość licznika na początku i na końcu impulsu, a następnie obliczam różnicę i wyświetlam wynik przez semihosting.

Сейчас один важный вопрос: в первом задании у тебя PWM в итоге работает на TIM2 Channel 1 (PA0) или на Channel 2 (PA1)? От этого зависит, какие именно пины нужно соединить для Z2.