TIMER32
Сброс флагов
Описание
Сброс флагов IC_INT_CHx, OC_INT_CHx, UDF_INT и OVF_INT происходит в конце
счёта таймера, во время которого была запись в регистр INT_CLEAR.
По этой причине возможен повторный вход в обработчик прерываний при низкой частоте
счёта таймера.
Рисунок 1. Повторная установка флага IC_INT_CHx, захват сигнала IC_CHx_IN по фронту
Обход
Отключение прерывания по захвату и повторное включение в основном цикле после того как флаг был очищен
#include "mik32_hal.h"
#include "mik32_hal_timer32.h"
#include "mik32_hal_irq.h"
TIMER32_HandleTypeDef htimer32;
TIMER32_CHANNEL_HandleTypeDef htimer32_channel;
void SystemClock_Config(void);
static void Timer32_Init(void);
int main()
{
__HAL_PCC_EPIC_CLK_ENABLE();
Timer32_Init();
HAL_Timer32_Value_Clear(&htimer32);
HAL_Timer32_Capture_Start_IT(&htimer32, &htimer32_channel);
HAL_EPIC_MaskLevelSet(HAL_EPIC_TIMER32_2_MASK);
HAL_IRQ_EnableInterrupts();
while (1)
{
/* Разрешить прерывание после того как флаг был сброшен. */
if ((htimer32.Instance->INT_FLAGS & TIMER32_INT_IC_M(htimer32_channel.ChannelIndex)) == 0)
{
htimer32.Instance->INT_MASK |= TIMER32_INT_IC_M(htimer32_channel.ChannelIndex);
}
}
}
static void Timer32_Init(void)
{
htimer32.Instance = TIMER32_2;
htimer32.Top = 6;
htimer32.Clock.Source = TIMER32_SOURCE_PRESCALER;
htimer32.Clock.Prescaler = 32000000;
htimer32.CountMode = TIMER32_COUNTMODE_FORWARD;
HAL_Timer32_Init(&htimer32);
htimer32_channel.TimerInstance = htimer32.Instance;
htimer32_channel.ChannelIndex = TIMER32_CHANNEL_0;
htimer32_channel.PWM_Invert = TIMER32_CHANNEL_NON_INVERTED_PWM;
htimer32_channel.Mode = TIMER32_CHANNEL_MODE_CAPTURE;
htimer32_channel.CaptureEdge = TIMER32_CHANNEL_CAPTUREEDGE_RISING;
htimer32_channel.OCR = 0;
htimer32_channel.Noise = TIMER32_CHANNEL_FILTER_OFF;
HAL_Timer32_Channel_Init(&htimer32_channel);
}
__attribute__((noinline, interrupt, section(".trap_text"))) void raw_trap_handler()
{
uint32_t interrupt_status = HAL_Timer32_InterruptFlags_Get(&htimer32);
uint32_t interrupt_mask = htimer32.Instance->INT_MASK;
if ((interrupt_status & TIMER32_INT_IC_M(htimer32_channel.ChannelIndex)) & interrupt_mask)
{
// Очистить флаг и отключить прерывание по захвату.
htimer32.Instance->INT_MASK &= ~TIMER32_INT_IC_M(htimer32_channel.ChannelIndex);
htimer32.Instance->INT_CLEAR = TIMER32_INT_IC_M(htimer32_channel.ChannelIndex);
}
}