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

Захват TIM14

Имеем дискавери с STM32F030R8, тактовая частота установлена 48 МГц (по факту очень близко).

Пытаюсь раскочегарить Захват внешнего сигнала таймером TIM14 (период, по фронту, РА4). Всё бы ничего, но недосчитывает порядка 0,6 мкс. Недосчёт примерно одинаковый для периода от 7 мкс до 30 мкс. Если тоже самое проделать на таймере TIM3 работает адекватно - погрешность 0,1 мкс, фактически на толщину линии маркера осциллографа. Вот сижу и думаю - дело к пятнице идёт и уже не соображается? Или может особенность TIM14. Можно перейти на другой таймер, но хотелось бы этот - потом перейду на 030F4 там портов в обрез.

Настройки TIM14:

	GPIOA->MODER |= GPIO_MODER_MODER4_1;					//альтернативная функция РA4
	GPIOA->AFR[0] |= (0x04 << GPIO_AFRL_AFSEL4_Pos);		//AF4 для TIM14 CH1
	//GPIOA->OTYPER &= ~GPIO_OTYPER_OT_4;						//РA4 пушпул
	//GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR4;				//высокая скорость

	RCC->APB1ENR |= RCC_APB1ENR_TIM14EN;					//включили модуль TIM14

//********** Настраиваем TIM14 на захват по фронту
//********** CCR1 - период
//********** ставим прерывание по CCR1
	//TIM14->CCMR1 |= TIM_CCMR1_CC1S_0 | TIM_CCMR1_IC1F_0 | TIM_CCMR1_IC1F_1;
	TIM14->CCMR1 |= TIM_CCMR1_CC1S_0 ;						//TIM14_CH1 вход

	//TIM14->CCMR1 |= 16;
	//TIM14->CCMR1 |= 32;
	//TIM14->CCMR1 |= 64;
	//TIM14->CCMR1 |= 128;
	TIM14->CCMR1 |= TIM_CCMR1_IC1F_0 | TIM_CCMR1_IC1F_1;

	//TIM14->CCER |= 2;
	//TIM14->CCER |= 8;
	TIM14->CCER |= TIM_CCER_CC1E;							//захват периода

	TIM14->SR &= ~TIM_SR_UIF;								//сброс общего флага прерывания
	TIM14->SR &= ~TIM_SR_CC1IF;								//сброс флага захват канал 1
	TIM14->DIER |= TIM_DIER_CC1IE;							//прерывание захват канал 1
	NVIC_EnableIRQ(TIM14_IRQn);								//разрешение глобального прерывания от TIM14
	NVIC_SetPriority(TIM14_IRQn,0);

	TIM14->CR1 |= TIM_CR1_CEN;								//включили счетчик

Прерывание TIM14

void TIM14_IRQHandler(void)
{
	TIM14->CNT = 0;
	peri = TIM14->CCR1;

	TIM14->SR = 0;
	//TIM14->SR &= ~TIM_SR_CC1IF;							//сброс флага прерывания
	//TIM14->SR &= ~TIM_SR_UIF;								//сброс флага прерывания
}

Может у кого чего было похожее? Можно, конечно, прибавить эти 0,6 мкс, но перед этим хотелось бы понять

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

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


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

Неправильно ты, дядя Фёдор, бутерброд ешь (с)

От появления сигнала на входе до обнуления счетчика тратится время на вход в обработчик прерывания, а захват значения счетчика в CCR1 происходит аппаратно, с всегда одинаковой задержкой на несколько тактов. Измеренное время получается меньше на время входа в обработчик прерывания.

 

TIM14->CNT лучше вообще не трогать, пусть себе считает. А время вычислять по захваченным в CCR1 значениям, текущему и предыдущему.

 

PS. Но 0.6 мкс это 28 или 29 тактов, что-то многовато. Вход в обработчик прерывания должен быть раза в два быстрее. А 0.1 мкс у TIM3 наоборот, слишком быстро.

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


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

50 минут назад, SSerge сказал:

Измеренное время получается меньше на время входа в обработчик прерывания.

Этот момент я понимаю так, по фронту происходит запись в CCR1 значения из CNT и всё равно уже, сколько там времени уходит на переход в обработчик прерывания. Эта же функция, но реализованная на TIM3 и с таким же обработчиком (как что привёл в примере) проблем не вызывает. 

CNT я сбрасываю, поскольку сам он аппаратно не сбрасывается и считает по кругу. Может в этом дело? Его не сбрасывать, а вычислять CCR как разность двух соседних. Тогда надо обрабатывать переход через ноль, а то ерунда получится...

Что ж, мысль.

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


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

18 минут назад, Vlad_G сказал:

Его не сбрасывать, а вычислять CCR как разность двух соседних. Тогда надо обрабатывать переход через ноль, а то ерунда получится...

Неужто это такая сложная операция, что даже говорить об этом стоит?

u16 peri;
void TIM14_IRQHandler(void)
{
  static u16 old;
  TIM14->SR = 0;
  u32 i0, i1 = TIM14->CCR1;
  peri = i1 - old;
  old = i1;
}

Всё, переход через 0 обработан.:mega_shok:

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


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

16 часов назад, jcxz сказал:

:mega_shok:

Не язвите, всяко бывает :о)  И на простых вещах можно зациклиться...

Спасибо вам jcxz и SSerge ! Да, счётчик, в отличие от TIM3, не сбрасывается при захвате и когда я его сбрасываю, он уже успел подсчитать 25 тактов. Прерывание от TIM14 (да и от TIM3) срабатывает за, примерно, 0.6 мкс, точнее от условия возникновения прерывания до выставления уровня в порту (или до первой операции).

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


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

On 9/22/2022 at 5:06 PM, jcxz said:

Неужто это такая сложная операция, что даже говорить об этом стоит?

u16 peri;
void TIM14_IRQHandler(void)
{
  static u16 old;
  TIM14->SR = 0;
  u32 i0, i1 = TIM14->CCR1;
  peri = i1 - old;
  old = i1;
}

Всё, переход через 0 обработан.:mega_shok:

А для чего нужна переменная i0 ?

А почему переменные i0 и i1 32-х битные, когда все остальные переменные 16-ти битные ?

А если между сигналами захвата произойдет 2,3,4,5....  переполнений значения счетчика ?

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


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

1 час назад, dimka76 сказал:

А для чего нужна переменная i0 ?

i0 видимо случайно попала, бывает.

В CubeIDE от разрядности i1 и old ничего не зависит.

А вот если переменную peri сделать uint32_t, то в неё периодически-случайно записывается какое-то волшебное значение - 4 294 902 391 при подсчитанных импульсах - 630. Откуда оно .!. знает, пока не разбирался, но это и есть, видимо, переход через ноль, который и надо обрабатывать. Если же сделать uint16_t, то всё гуд. Собственно это меня не переживает, мой вопрос был в другом и он решился.

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


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

On 9/23/2022 at 12:01 PM, Vlad_G said:

А вот если переменную peri сделать uint32_t, то в неё периодически-случайно записывается какое-то волшебное значение - 4 294 902 391 при подсчитанных импульсах - 630. Откуда оно .!. знает, пока не разбирался, но это и есть, видимо, переход через ноль, который и надо обрабатывать. Если же сделать uint16_t, то всё гуд. Собственно это меня не переживает, мой вопрос был в другом и он решился.

Тут надо смотреть в сторону порядка приведения типов в соответствии со стандартом Си.

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


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

39 минут назад, dimka76 сказал:

надо смотреть в сторону

Да, либо делать преобразование типов, либо без нужды не записывать 16 бит в 32 бита, особенно, когда разность может оказаться отрицательной.

В общем бдить, особенно в наше время.

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


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

6 часов назад, dimka76 сказал:

А для чего нужна переменная i0 ?

Случайно затесалась, по недогляду.  :secret:

6 часов назад, dimka76 сказал:

А почему переменные i0 и i1 32-х битные, когда все остальные переменные 16-ти битные ?

"Остальные" - переменные хранения, они и должны быть 16-битными. По алгоритму работы, подумайте внимательнее. А i1 - операционная переменная, она должна быть основной разрядности CPU, т.е. = 32 бита, можно uint; чтобы компилятор не налепил лишних команд расширения UXT/SXT.

6 часов назад, dimka76 сказал:

А если между сигналами захвата произойдет 2,3,4,5....  переполнений значения счетчика ?

А при чём тут обработка пересечения 0?

2 часа назад, Vlad_G сказал:

В общем бдить, особенно в наше время.

Достаточно вспомнить хотя бы школьный метод сложения/вычитания в столбик: содержимое младших разрядов числа никак не зависит от старших. Так что их можно спокойно отбросить.

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


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

On 9/23/2022 at 4:32 PM, jcxz said:

Случайно затесалась, по недогляду.  :secret:

бывает )))

On 9/23/2022 at 4:32 PM, jcxz said:

....она должна быть основной разрядности CPU, т.е. = 32 бита....

Ясно 

On 9/23/2022 at 4:32 PM, jcxz said:

А при чём тут обработка пересечения 0?

Так это же ваше утверждение :wink:

Quote

Всё, переход через 0 обработан.

 

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


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

36 минут назад, dimka76 сказал:

Так это же ваше утверждение :wink:

Я говорил об "обработке пересечениия 0", а вы - "о недостаточной разрядности счётчика для регистрации временнОго интервала". Между этими вещами никакой связи нет.

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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