Помогите понять таймер

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
Dmitry42
Родился
Сообщения: 7
Зарегистрирован: Сб янв 17, 2026 07:39:21

Помогите понять таймер

Сообщение Dmitry42 »

Добрый день! Я совсем новичок, опыт с МК вообще нулевой. Сижу разбираю исходный код суть которого выдать на ногу меняющуюся последовательность сигналов ( что-то вроде 100 мс высокий, 200 низкий, 500 высокий, 300 низкий и тп), в общем генерациия радиосигнала.

Этот алгоритм работает на таймере и ДМА. Таймер запускается, а затем при каждом событии таймера с помощью ДМА меняется регистр ARR чтоб поменять длительность работы таймера на следующее значение из буфера таймингов, режим работы togle переключает сигнал на ноге по достижении очередного заданного значения счетчика.

Казалось бы все просто - досчитали такты до нужного тайминга, переключили ногу на противоположную, вызвали событие чтоб ДМА подгрузило новый тайминг и считаем такты дальше, но в коде есть строка которая немного меня запутала. TIM_OC_InitStruct.CompareValue = 0;

В моем понимании эта строка добавляет к обычному событию таймера по переполнении счетчика еще одно событие при нулевом счетчике. И фактически мы имеем 2 последовательных события вызывающих ДМА - о переполнении таймера и о его нулевом значении.

Где пробел в моих знаниях и логике ? Контроллер STM32WB55

Код: Выделить всё

   // Configure DMA
    LL_DMA_InitTypeDef dma_config = {0};
    dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (TIM2->ARR);
    dma_config.MemoryOrM2MDstAddress = (uint32_t)subghz_async_tx.buffer;
    dma_config.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;
    dma_config.Mode = LL_DMA_MODE_CIRCULAR;
    dma_config.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
    dma_config.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
    dma_config.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD;
    dma_config.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD;
    dma_config.NbData = FURI_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL;
    dma_config.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP;

    // Configure TIM2
    LL_TIM_SetCounterMode(TIM2, LL_TIM_COUNTERMODE_UP);
    LL_TIM_SetClockDivision(TIM2, LL_TIM_CLOCKDIVISION_DIV1);
    LL_TIM_SetAutoReload(TIM2, 1000);
    LL_TIM_SetPrescaler(TIM2, 64 - 1);
    LL_TIM_SetClockSource(TIM2, LL_TIM_CLOCKSOURCE_INTERNAL);
    LL_TIM_DisableARRPreload(TIM2);

    // Configure TIM2 CH2
    LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0};
    TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_TOGGLE;
    TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_DISABLE;
    TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_DISABLE;
    TIM_OC_InitStruct.CompareValue = 0;
    TIM_OC_InitStruct.OCPolarity = LL_TIM_OCPOLARITY_HIGH;
    LL_TIM_OC_Init(TIM2, LL_TIM_CHANNEL_CH2, &TIM_OC_InitStruct);
    LL_TIM_OC_DisableFast(TIM2, LL_TIM_CHANNEL_CH2);
    LL_TIM_DisableMasterSlaveMode(TIM2);

    LL_TIM_EnableDMAReq_UPDATE(TIM2);
    LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH2);

    LL_TIM_SetCounter(TIM2, 0);
    LL_TIM_EnableCounter(TIM2);
Adrift
Вымогатель припоя
Сообщения: 539
Зарегистрирован: Вт окт 01, 2024 15:22:33

Re: Помогите понять таймер

Сообщение Adrift »

У вас конкретно указано LL_DMAMUX_REQ_TIM2_UP, все остальное DMA не интересует. Если нужно чтобы запрос генерился когда счетчик равен какому-то значению(задаваемому в CCRx), то выбираете LL_DMAMUX_REQ_TIM2_CHx, но не то и другое одновременно.
Dmitry42
Родился
Сообщения: 7
Зарегистрирован: Сб янв 17, 2026 07:39:21

Re: Помогите понять таймер

Сообщение Dmitry42 »

[uquote="Adrift",url="/forum/viewtopic.php?p=4780662#p4780662"]У вас конкретно указано LL_DMAMUX_REQ_TIM2_UP, все остальное DMA не интересует. Если нужно чтобы запрос генерился когда счетчик равен какому-то значению(задаваемому в CCRx), то выбираете LL_DMAMUX_REQ_TIM2_CHx, но не то и другое одновременно.[/uquote]

Спасибо за ответ. Вопрос был скорее не о том что мне надо, а об алгоритме работы - как этот код работает.

Мне кажется я в целом разобрался в итоге. У нас ДМА дергается по событию таймера, а нога переключается отдельно по событию CompareValue. Я по наивности думал событие таймера и переключения ноги - формируют одинаковые события.
А ваш ответ тоже приводит к мысли о том, что у таймера и его ноги разные события.

Еще раз спасибо!
a797945
Мучитель микросхем
Сообщения: 446
Зарегистрирован: Вс ноя 01, 2015 09:15:16
Откуда: 69.Ржев

Re: Помогите понять таймер

Сообщение a797945 »

Если б открыли RM на Ваш МК - даже без знания инглиш, видно, что ноги связаны с регистрами CCRx.
Dmitry42
Родился
Сообщения: 7
Зарегистрирован: Сб янв 17, 2026 07:39:21

Re: Помогите понять таймер

Сообщение Dmitry42 »

Я бы еще схемотехнику понимал бы )))
Абсолютный новичок с МК
jcxz
Мудрый кот
Сообщения: 1717
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: Помогите понять таймер

Сообщение jcxz »

[uquote="Dmitry42",url="/forum/viewtopic.php?p=4780667#p4780667"]Я по наивности думал событие таймера и переключения ноги - формируют одинаковые события.
А ваш ответ тоже приводит к мысли о том, что у таймера и его ноги разные события.[/uquote]Что такое "событие таймера"? Что такое "длительность работы таймера"? Как может "переключение ноги" (output видимо) формировать какое-то событие? ...
Ничего не понятно... Какой-то птичий язык....

PS: Если хотите что-то понимать в работе таймера и хотите выражаться на понятном всем языке (а не своём птичьем), начните не с "разбирания чужих исходных кодов", а с изучения RM на ваш микроконтроллер в разделе "таймеры". Тогда будете понимать, что нет понятия "событие таймера", а есть понятия "событие переполнения таймера", "событие срабатывания compare-условия таймера по одному из compare-регистров", "событие захвата таймера" и т.д. Что ноги таймера могут управляться от разных событий в зависимости от режима. Так же как и триггер-сигналы к привязанному DMA-каналу могут посылаться от разных событий таймера: переполнения, compare, etc.
Dmitry42
Родился
Сообщения: 7
Зарегистрирован: Сб янв 17, 2026 07:39:21

Re: Помогите понять таймер

Сообщение Dmitry42 »

Спасибо за совет!
Ответить

Вернуться в «ARM»