Vlad_G 8 22 сентября, 2022 Опубликовано 22 сентября, 2022 (изменено) · Жалоба Имеем дискавери с 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 мкс, но перед этим хотелось бы понять Изменено 22 сентября, 2022 пользователем Vlad_G Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SSerge 6 22 сентября, 2022 Опубликовано 22 сентября, 2022 · Жалоба Неправильно ты, дядя Фёдор, бутерброд ешь (с) От появления сигнала на входе до обнуления счетчика тратится время на вход в обработчик прерывания, а захват значения счетчика в CCR1 происходит аппаратно, с всегда одинаковой задержкой на несколько тактов. Измеренное время получается меньше на время входа в обработчик прерывания. TIM14->CNT лучше вообще не трогать, пусть себе считает. А время вычислять по захваченным в CCR1 значениям, текущему и предыдущему. PS. Но 0.6 мкс это 28 или 29 тактов, что-то многовато. Вход в обработчик прерывания должен быть раза в два быстрее. А 0.1 мкс у TIM3 наоборот, слишком быстро. 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Vlad_G 8 22 сентября, 2022 Опубликовано 22 сентября, 2022 · Жалоба 50 минут назад, SSerge сказал: Измеренное время получается меньше на время входа в обработчик прерывания. Этот момент я понимаю так, по фронту происходит запись в CCR1 значения из CNT и всё равно уже, сколько там времени уходит на переход в обработчик прерывания. Эта же функция, но реализованная на TIM3 и с таким же обработчиком (как что привёл в примере) проблем не вызывает. CNT я сбрасываю, поскольку сам он аппаратно не сбрасывается и считает по кругу. Может в этом дело? Его не сбрасывать, а вычислять CCR как разность двух соседних. Тогда надо обрабатывать переход через ноль, а то ерунда получится... Что ж, мысль. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 22 сентября, 2022 Опубликовано 22 сентября, 2022 · Жалоба 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 обработан. 2 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Vlad_G 8 23 сентября, 2022 Опубликовано 23 сентября, 2022 · Жалоба 16 часов назад, jcxz сказал: Не язвите, всяко бывает :о) И на простых вещах можно зациклиться... Спасибо вам jcxz и SSerge ! Да, счётчик, в отличие от TIM3, не сбрасывается при захвате и когда я его сбрасываю, он уже успел подсчитать 25 тактов. Прерывание от TIM14 (да и от TIM3) срабатывает за, примерно, 0.6 мкс, точнее от условия возникновения прерывания до выставления уровня в порту (или до первой операции). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dimka76 63 23 сентября, 2022 Опубликовано 23 сентября, 2022 · Жалоба 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 обработан. А для чего нужна переменная i0 ? А почему переменные i0 и i1 32-х битные, когда все остальные переменные 16-ти битные ? А если между сигналами захвата произойдет 2,3,4,5.... переполнений значения счетчика ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Vlad_G 8 23 сентября, 2022 Опубликовано 23 сентября, 2022 · Жалоба 1 час назад, dimka76 сказал: А для чего нужна переменная i0 ? i0 видимо случайно попала, бывает. В CubeIDE от разрядности i1 и old ничего не зависит. А вот если переменную peri сделать uint32_t, то в неё периодически-случайно записывается какое-то волшебное значение - 4 294 902 391 при подсчитанных импульсах - 630. Откуда оно .!. знает, пока не разбирался, но это и есть, видимо, переход через ноль, который и надо обрабатывать. Если же сделать uint16_t, то всё гуд. Собственно это меня не переживает, мой вопрос был в другом и он решился. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dimka76 63 23 сентября, 2022 Опубликовано 23 сентября, 2022 · Жалоба On 9/23/2022 at 12:01 PM, Vlad_G said: А вот если переменную peri сделать uint32_t, то в неё периодически-случайно записывается какое-то волшебное значение - 4 294 902 391 при подсчитанных импульсах - 630. Откуда оно .!. знает, пока не разбирался, но это и есть, видимо, переход через ноль, который и надо обрабатывать. Если же сделать uint16_t, то всё гуд. Собственно это меня не переживает, мой вопрос был в другом и он решился. Тут надо смотреть в сторону порядка приведения типов в соответствии со стандартом Си. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Vlad_G 8 23 сентября, 2022 Опубликовано 23 сентября, 2022 · Жалоба 39 минут назад, dimka76 сказал: надо смотреть в сторону Да, либо делать преобразование типов, либо без нужды не записывать 16 бит в 32 бита, особенно, когда разность может оказаться отрицательной. В общем бдить, особенно в наше время. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 23 сентября, 2022 Опубликовано 23 сентября, 2022 · Жалоба 6 часов назад, dimka76 сказал: А для чего нужна переменная i0 ? Случайно затесалась, по недогляду. 6 часов назад, dimka76 сказал: А почему переменные i0 и i1 32-х битные, когда все остальные переменные 16-ти битные ? "Остальные" - переменные хранения, они и должны быть 16-битными. По алгоритму работы, подумайте внимательнее. А i1 - операционная переменная, она должна быть основной разрядности CPU, т.е. = 32 бита, можно uint; чтобы компилятор не налепил лишних команд расширения UXT/SXT. 6 часов назад, dimka76 сказал: А если между сигналами захвата произойдет 2,3,4,5.... переполнений значения счетчика ? А при чём тут обработка пересечения 0? 2 часа назад, Vlad_G сказал: В общем бдить, особенно в наше время. Достаточно вспомнить хотя бы школьный метод сложения/вычитания в столбик: содержимое младших разрядов числа никак не зависит от старших. Так что их можно спокойно отбросить. 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dimka76 63 23 сентября, 2022 Опубликовано 23 сентября, 2022 · Жалоба On 9/23/2022 at 4:32 PM, jcxz said: Случайно затесалась, по недогляду. бывает ))) On 9/23/2022 at 4:32 PM, jcxz said: ....она должна быть основной разрядности CPU, т.е. = 32 бита.... Ясно On 9/23/2022 at 4:32 PM, jcxz said: А при чём тут обработка пересечения 0? Так это же ваше утверждение Quote Всё, переход через 0 обработан. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 23 сентября, 2022 Опубликовано 23 сентября, 2022 · Жалоба 36 минут назад, dimka76 сказал: Так это же ваше утверждение Я говорил об "обработке пересечениия 0", а вы - "о недостаточной разрядности счётчика для регистрации временнОго интервала". Между этими вещами никакой связи нет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться