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

Синхронизация таймеров

Здравствуйте!

 

Использую stm32f107vc.

Пытаюсь синхронизировать два таймера (TIM3 и TIM5), как включающиеся синхронно от внешнего импульса. Настроил их, как написано в RM0008 стр.386:

void TIM3(void)
{
  RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; // подача тактов на TIM3 от шины тактирования APB1

  TIM3->PSC = 70 - 1;    
  TIM3->ARR = 25000 - 1;	
  TIM3->DIER &=~ TIM_DIER_UIE;
  TIM3->CR1 |= TIM_CR1_ARPE;	// сброс по достижении максимального значения

// в мастер-режиме передаёт данные о своих Enable, как триггерный выход (MMS=001)
  TIM3->CR2 |=  TIM_CR2_MMS_0;             /*!<Bit 0 */
  TIM3->CR2 &=~ TIM_CR2_MMS_1;             /*!<Bit 1 */				 
  TIM3->CR2 &=~ TIM_CR2_MMS_2;             /*!<Bit 2 */
// в подчиненном режиме, чтобы получить входной триггер TI1 (TS=100)			
  TIM3->SMCR &=~ TIM_SMCR_TS_0;             /*!<Bit 0 */
  TIM3->SMCR &=~ TIM_SMCR_TS_1;             /*!<Bit 1 */
  TIM3->SMCR |=  TIM_SMCR_TS_2;             /*!<Bit 2 */
// в режиме триггера (SMS=110)
  TIM3->SMCR &=~ TIM_SMCR_SMS_0;            /*!<Bit 0 */
  TIM3->SMCR |=  TIM_SMCR_SMS_1;            /*!<Bit 1 */
  TIM3->SMCR |=  TIM_SMCR_SMS_2;            /*!<Bit 2 */
// установка задержки для того, чтоб таймеры очень хорошо синхронизировались (MSM=1)
  TIM3->SMCR |=  TIM_SMCR_MSM; 

  TIM3->CNT = 0; // обнулить счётчик, чтобы его значение после синхронизации равнялось 0x00
}

void TIM5 (void)
{
  RCC->APB1ENR |= 1<<3; // TIM5EN подача тактов на TIM5 от шины тактирования APB1

  TIM5->PSC = 70 - 1;   
  TIM5->ARR = 25000 - 1;	
  TIM5->DIER &=~ TIM_DIER_UIE;
  TIM5->CR1 |= TIM_CR1_ARPE;	//  сброс по достижении максимального значения
// получаем входной триггер от TIM3 (TS=001) как в Table 86			
  TIM5->SMCR |=  TIM_SMCR_TS_0;           /*!<Bit 0 */
  TIM5->SMCR &=~ TIM_SMCR_TS_1;           /*!<Bit 1 */ // TS=001
  TIM5->SMCR &=~ TIM_SMCR_TS_2;           /*!<Bit 2 */
// в режиме триггера (SMS=110)
  TIM5->SMCR &=~ TIM_SMCR_SMS_0;            /*!<Bit 0 */
  TIM5->SMCR |=  TIM_SMCR_SMS_1;            /*!<Bit 1 */
  TIM5->SMCR |=  TIM_SMCR_SMS_2;            /*!<Bit 2 */

  TIM5->CNT = 0; // обнулить счётчик, чтобы его значение после синхронизации равнялось 0x00	
}

В итоге, снимая по запросу значения регистров CNT из обоих таймеров, по USART'у получаю такие значения:

 

при TIM5->ARR = 25000 - 1; и TIM3->ARR = 25000 - 1; значения регистров CNT одинаковые (например, 0x5936 и 0x5936 или 0x728 и 0x728), и так с любыми одинаковыми значениями регистров ARR таймеров.

а при TIM5->ARR = 50000 - 1; и TIM3->ARR = 25000 - 1; значения регистров CNT, по идее, должны отличаться на 25000 (0х61A8), а реально они, например, вот такие - 0x22D4 и 0x216F или такие - 0x556D и 0xB5B0.

 

В чём может быть проблема? Может быть, что-то не так настроил?

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


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

Ответа не знаю но варианты:

1. Уберите TIM5->CR1 |= TIM_CR1_ARPE; - это совсем про другое чем вы пишете в комметариях.

Bit 7 ARPE: Auto-reload preload enable

0: TIMx_ARR register is not buffered

1: TIMx_ARR register is buffered

buffered - значит первый раз используется предыдущее значение, сохранённое в теневом регистре.

 

2. Чаще выводите CNT через UART и смотрите как они изменяются. Сначала оба нарастают от 0, потом TIM5->CNT приближается к 25000 - что дальше? Для замедления и удобства наблюдения можно увеличить PSC обоих таймеров.

 

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


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

1. Уберите TIM5->CR1 |= TIM_CR1_ARPE; - это совсем про другое чем вы пишете в комметариях.

Зачем убирать этот бит, если он отвечает за значение, до которого таймер считает, без него, как раз, гикак. А комментарий я уберу.

Да, это я перед тем как создать тему немного откорректировал свои комментарии и не заметил этих строк, поэтому вышла ошибка.

 

2. Чаще выводите CNT через UART и смотрите как они изменяются. Сначала оба нарастают от 0, потом TIM5->CNT приближается к 25000 - что дальше? Для замедления и удобства наблюдения можно увеличить PSC обоих таймеров.

Спасибо. Буду пробовать.

 

Вчера возникла идея, что проблема из-за битового поля TS регистра SMCR. Начал просто перебирать возможные значения, но только при значении TS=001 оба счётчика работают, во всех других вариантах счётчик TIM5 всё время равен 0. В общем, cегодня попробую поменять местами TIM5 и TIM3.

 

Не очень понятна эта таблица 86 (RM0008 стр.386). Из описания следует, что Slave TIM, в моём варианте, - это TIM5 (стр. 386), находим TIM3 и получаем - ITR1 (TS = 001). Вроде бы всё верно, но попробую поменять таймеры местами.

 

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


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

Зачем убирать этот бит, если он отвечает за значение, до которого таймер считает, без него, как раз, гикак. А комментарий я уберу.

В том то и дело что когда бит TIM_CR1_ARPE выствлен то таймер будет 1 раз считать до _не того_ значения.

Когда этот бит выставлен, то регистр ARR существует в двух экземплярах - видимый для процессор и теневой, с которым работает таймер. И они могут быть не равны друг другу.

Теневой становится равным тому который видимый для процессора _после_ каждого досчёта до конца. То есть первый раз будет использовано не то что туда записали, а то что там было ранее.

Смотрите рисунок 108 "Counter timing diagram, Update event when ARPE=1 (TIMx_ARR preloaded)" на странице 354 в reference manual. Там в ARR записали 0x36, но считает всё равно до 0xf5.

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


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

Спасибо. Буду разбираться.

 

Выставление бита ARPE в ноль в обоих таймерах ничего не изменяет..

 

Пока что единственное решение этого вопроса - это включить ОБА таймера по приходу внешнего сигнала, не синхронизируя их. Но очередная проблема с таймерами в STM32 останется не решённой...

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

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


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

В попытках найти ответ на свой вопрос, я получил правильный ответ от

Железнякова Дениса (www.ziblog.ru), причём ответил он втечение 20 минут.

За что я ему очень благодарен!

 

Вот сам ответ:

 

Вы используете предварительные делители у обоих таймеров. Оба

предделителя буфферизированны, т.е. просто запись значения ничего не

меняет, изменения происходят только после события обновления.

Следовательно вам необходимо добавить:

TIM4->PSC = 70 - 1;

TIM4->EGR |= TIM_EGR_UG;

Это действие:

а) сбросит их

б) установить новый модуль счета

 

И всё работает, как надо!

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


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

У меня возник вопрос. Если при достижении таймером TIM1 переполнения я хочу сбросить таймер TIM4 могу ли я написать следующим образом TIM4->CNT=0? Или же если мне нужно не сбросить а продолжить счет TIM4 с определенного значения могу ли я записать TIM4->CNT=X?

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


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

У меня возник вопрос. Если при достижении таймером TIM1 переполнения я хочу сбросить таймер TIM4 могу ли я написать следующим образом TIM4->CNT=0? Или же если мне нужно не сбросить а продолжить счет TIM4 с определенного значения могу ли я записать TIM4->CNT=X?

Насколько я понимаю, сначала нужно выключить счётчик TIM4->CR1 &=~ TIM_CR1_CEN, потом внести значение в регистр CNT, после чего счётчик включить.

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


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

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

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

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

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

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

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

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

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

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