Перейти к содержанию
    

Прерывание Update Event таймера 2

Доброго всем времени суток!

 

В программе используется таймер 2, в прерывании по переполнению которого корректируется значение счетчика этого таймера (TIM2->CNT). На данный момент значение выставляется фиксированным (100). Первый канал таймера настроен на выход в режиме PWM Mode 1. Так вот когда я смотрю выходной сигнал, наблюдается сильное дрожание фронтов (в пределах 10-12 тактов), хотя, как мне кажется дрожание должно быть в пределах 1-3 тактов (в зависимости от текущей команды, которая совпадает с моментом возникновения прерывания). В чем ошибка?

 

Код инициализации таймера:

    TIM_TimeBaseInitTypeDef tb2;
    TIM_OCInitTypeDef  TIM_OCInitStructure;

    //Таймер 2 --------------------------------------------
      tb2.TIM_Period = 7200;
      tb2.TIM_Prescaler = 0;
      tb2.TIM_ClockDivision = 0;
      tb2.TIM_CounterMode = TIM_CounterMode_Up;

      TIM_TimeBaseInit(TIM2, &tb2);

      // PWM1 Mode configuration: Channel1
      TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
      TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
      TIM_OCInitStructure.TIM_Pulse = 3600;
      TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

      TIM_OC1Init(TIM2, &TIM_OCInitStructure);
      TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Disable);
      TIM_ARRPreloadConfig(TIM2, DISABLE);

    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
    TIM_ClearFlag(TIM2, TIM_FLAG_Update);     
      // TIM2 enable counter
      TIM_Cmd(TIM2, ENABLE);

 

Код инициализации прерывания:

      NVIC_InitTypeDef NVIC_InitStructure;

      NVIC_InitStructure.NVIC_IRQChannel = 28;
      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
      NVIC_Init(&NVIC_InitStructure);

 

Код прерывания:

void TIM2_IRQHandler(void)
{
    TIM2->CNT = 0x0000;
                TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}

Ну и на всякий случай настройка порта:

                GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_Init(GPIOA, &GPIO_InitStructure);

 

Пробовал проделывать тоже самое на меге128 - дрожание есть, но в пределах 2-х тактов.

Еще заметил такую особенность: если в прерывании присваивать значение таймера какой-то переменной:

void TIM2_IRQHandler(void)
{
    TIM2->CNT = cnt;
    TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}

, а в основном цикле по нажатию кнопки менять значение этой переменной, то в зависимости от уровня оптимизации наюлюдается разное дрожание. Дрожание также меняется в зависимости от настройки приоритета прерывания и от количества конструкций типа if.

Так можно ли добиться какой-нибудь стабильности? Не хочется переходить на мегу128 :(

Изменено пользователем Sprite

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Поставлю вопрос по другому: какое максимальное количество тактов может занимать одна инструкция процессора (stm32f103)? Если 10-12 тактов, то вопрос закрыт, иначе буду думать, где слабое звено программы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Поставлю вопрос по другому: какое максимальное количество тактов может занимать одна инструкция процессора (stm32f103)? Если 10-12 тактов, то вопрос закрыт, иначе буду думать, где слабое звено программы.

 

Ну, я так полагаю, ... Вы не там копаете... Разберитесь сперва с тем, что вы хотите в конечном итоге получить...

Судя по приведенным фрагментам кода, Вы настраиваете таймер на переполнение при CNT=7200, при достижении счетчиком CNT=3600 произойдет махание ножкой в соответствии с режимом PWM1. По переполнению счетчика, происходит событие Update, счетчик итак начинает считать с CNT=0 и вы опять же зачем-то подсовываете в него значение 0x00, при этом, учитывая, что событие Update генерируется с задержной на несколько тактов, плюс вход в прерывание 12 тактов... , а счетчик уже начал считать... и на каком-то такте вы его снова обнулили.... вот и получается ваше дрожжжжание фронта.

В данном случае, логичней было бы изменять длительность периода таймера в регистре ARR... или значение длительности импульса в регистре совпадения CCR1.... а не пытаться изменить значение счетного регистра, да еще при этом на запущенном таймере.

В общем, не мешало бы вам почитать вдумчиво Reference Manual.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...