|
STM32. Функция задержки, программные задержки на таймере |
|
|
|
Jun 27 2012, 19:47
|
Частый гость
 
Группа: Свой
Сообщений: 87
Регистрация: 9-12-10
Пользователь №: 61 511

|
Написал функцию задержки на базовом таймере. В одной программе работает отлично, но вызывается правда постоянно с одним и тем же значением. В другой то ли работает криво, то ли не работает вообще: Код #define APB1_FREQ 24000000 void delay_ms (uint16_t volatile ms) { TIM7->CR1 &= ~0xFF; // Сбрасываем регистр управления таймера TIM7 if (ms != 1) { // Если значение задержки НЕ равно 1, TIM7->PSC = APB1_FREQ/1000-1; // настраиваем таймер TIM7 на период 1 мс, TIM7->ARR = ms-1; // установить конечное значение счёта с учетом импульса переполнения; } else { // иначе, TIM7->PSC = 2*APB1_FREQ/1000-1; // настраиваем таймер TIM7 на период в 2 раза меньше - 0,5 мс TIM7->ARR = 1; } // установить конечное значение счёта на 1 с учетом импульса переполнения TIM7->CR1 |= (TIM_CR1_OPM | TIM_CR1_CEN); // Установить режим "одного импульса" и включить таймер TIM7 while(!(TIM7->SR & TIM_SR_UIF)); // Дождаться конца задержки TIM7->SR &= ~TIM_SR_UIF; // Сбросить флаг прерывания }; Не пойму почему не выдерживается задержка? ЗЫ. Таймер тактирован в основной программе: Код RCC->APB1ENR |= RCC_APB1ENR_TIM7EN; // Тактируем базовый таймер TIM7
|
|
|
|
|
 |
Ответов
|
Jun 27 2012, 23:45
|
Частый гость
 
Группа: Свой
Сообщений: 87
Регистрация: 9-12-10
Пользователь №: 61 511

|
Проблема решилась установкой бита ARPE в управляющем регистре сразу после его сброса (буферизирует новое значение ARR в теневом регистре до события UEV): Код TIM7->CR1 = TIM_CR1_ARPE | TIM_CR1_OPM; Но в чем косяк был до этого все равно не пойму  Вроде должно было и без него работать. Почему этот бит так важен для этой функции, на чем функцию клинило без него? Возможно спецы подскажут? Еще одно: правильно ли я понимаю принцип генерации события таймером. Допустим конечное значение счета ARR=3. Таймер будет считать от 0 до 3 и только на 4-м импульсе возникнет переполнение и будет сгенерировано событие? Или событие сгенерируется уже на 3-м?
|
|
|
|
|
Jun 28 2012, 03:51
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Короче, так. Регистр PSC обновляется только при update event. Если ARPE = 1, то ARR тоже обновляется только при update event (иначе сразу). Так что установка ARPE в 1 вам не поможет, потому что прескалер всё равно буферизован. Сделайте как я написал, и всё заработает  (Update event - происходит при переполнении или вручную, взведением бита UG в регистре EGR.)
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jun 28 2012, 11:21
|
Частый гость
 
Группа: Свой
Сообщений: 87
Регистрация: 9-12-10
Пользователь №: 61 511

|
Цитата(AHTOXA @ Jun 28 2012, 06:51)  Регистр PSC обновляется только при update event. (Update event - происходит при переполнении или вручную, взведением бита UG в регистре EGR.) Новый предделитель не будет установлен, пока не произойдет update event, даже если таймер выключен (CEN=0) ? Т.е. даже если таймер выключен, я все равно должен установить бит UG в регистре EGR, чтобы обновить значение предделителя, правильно? С учетом вышесказанного код преобразился в следующий: Код void delay_ms (uint16_t ms) { TIM7->PSC = APB1_FREQ/(((ms == 1) ? 2 : 1)*1000)-1; // Настраиваем таймер TIM7 на период 0.5 мс для задержки в 1 мс // и на период 1 мс для всех остальных значений TIM7->EGR = TIM_EGR_UG; // Сгенерировать событие для загрузки нового значения предделителя TIM7->SR &= ~TIM_SR_UIF; // Сбросить флаг прерывания TIM7->ARR = (ms == 1) ? 1 : (ms-1); // Установить конечное значение счёта с учетом импульса переполнения TIM7->CR1 = TIM_CR1_OPM | TIM_CR1_CEN; // Установить режим "одного импульса" и включить таймер TIM7 while(!(TIM7->SR & TIM_SR_UIF)); // Дождаться конца задержки TIM7->SR &= ~TIM_SR_UIF; // Сбросить флаг прерывания }; Не реализовано только это: Цитата(sgs @ Jun 28 2012, 07:36)  Есть только один тонкий момент: нельзя запускать таймер сразу после UG. Требуется несколько тактов процессора, чтобы произошла реальная загрузка счетчика. Только после этого заданный интервал отрабатывается правильно. Для этого вполне достаточно оформить загрузку в виде процедуры, а запуск делать вне этой процедуры. Не пойму что имеется в виду "оформить загрузку в виде процедуры". Сделать загрузку в виду отдельной функции? Цитата(scifi @ Jun 28 2012, 08:39)  Странный выбор таймера для задержки, если только в образовательных целях. Для этих целей лучше подходит SysTick, а ещё лучше - вот этот счётчик циклов процессора (он 32-разрядный, поэтому арифметика с ним простейшая). Почему странный выбор? Простой таймер - для простой задачи. Вот это действительно интересно, обязательно попробую с ним разобраться. Жаль есть он только в M3, да и SysTick в M0 может отсутствовать. А это "минус" для переносимости кода. Кто с этим может подсказать, из ДШ это не совсем ясно: Цитата(Влад Р. @ Jun 28 2012, 02:45)  Еще одно: правильно ли я понимаю принцип генерации события таймером. Допустим конечное значение счета ARR=3. Таймер будет считать от 0 до 3 и только на 4-м импульсе возникнет переполнение и будет сгенерировано событие? Или событие сгенерируется уже на 3-м? Иными словами, нужно ли в ARR заносить задержку на один импульс меньше желаемой или это лишнее?
Сообщение отредактировал Влад Р. - Jun 28 2012, 15:26
|
|
|
|
|
Jun 28 2012, 16:52
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(Влад Р. @ Jun 28 2012, 17:21)  Новый предделитель не будет установлен, пока не произойдет update event, даже если таймер выключен (CEN=0) ? Т.е. даже если таймер выключен, я все равно должен установить бит UG в регистре EGR, чтобы обновить значение предделителя, правильно? Да. Цитата(Влад Р. @ Jun 28 2012, 17:21)  С учетом вышесказанного код преобразился в следующий: Лучше писать в ARR до генерации события (чтобы не зависеть от значения ARPE): Код void delay_ms (uint16_t ms) { TIM7->PSC = APB1_FREQ/(((ms == 1) ? 2 : 1)*1000)-1; // Настраиваем таймер TIM7 на период 0.5 мс для задержки в 1 мс // и на период 1 мс для всех остальных значений TIM7->ARR = (ms == 1) ? 1 : (ms-1); // Установить конечное значение счёта с учетом импульса переполнения TIM7->EGR = TIM_EGR_UG; // Сгенерировать событие для загрузки нового значения предделителя TIM7->SR &= ~TIM_SR_UIF; // Сбросить флаг прерывания TIM7->CR1 = TIM_CR1_OPM | TIM_CR1_CEN; // Установить режим "одного импульса" и включить таймер TIM7 while(!(TIM7->SR & TIM_SR_UIF)); // Дождаться конца задержки TIM7->SR &= ~TIM_SR_UIF; // Сбросить флаг прерывания }; К тому же сброс флага прерывания после генерации события вполне сойдёт за паузу перез запуском таймера (хотя я лично не встречал упоминаний о её необходимости). Цитата(Влад Р. @ Jun 28 2012, 17:21)  Иными словами, нужно ли в ARR заносить задержку на один импульс меньше желаемой или это лишнее? Да, на один меньше. Для задержки на один такт нужно занести значение 0.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jun 28 2012, 17:51
|
Частый гость
 
Группа: Свой
Сообщений: 87
Регистрация: 9-12-10
Пользователь №: 61 511

|
Цитата(AHTOXA @ Jun 28 2012, 19:52)  Для задержки на один такт нужно занести значение 0. Да вроде как нельзя так делать, иначе бы я не городил вот эти конструкции: Код ((ms == 1) ? 2 : 1) Код (ms == 1) ? 1 : (ms-1) Вот фраза из описания регистра TIMx_ARR: "The counter is blocked while the auto-reload value is null" ЗЫ AHTOXA, огромное спасибо за активную помощь!
Сообщение отредактировал Влад Р. - Jun 28 2012, 17:53
|
|
|
|
|
Dec 22 2012, 06:53
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(AHTOXA @ Jun 28 2012, 21:03)  Да, это я лопухнулся  Значит, не надо уменьшать на 1. Пытаюсь досконально разобраться с базовыми таймерами. Считаю, что на 1 уменьшать надо. Практически пока не проверял. В руководстве есть картинки, где показано, как CNT меняется от 0 до 36, при этом написано, что ARR = 0x36. Значит, счетчик считает на 1 больше. Фраза "The counter is blocked while the auto-reload value is null" вызывает недоумение. Вообще, описано плохо. Пытаюсь прикинуть, как биты URS, UDIS работают в схеме таймера, и из описания понять невозможно.
|
|
|
|
Сообщений в этой теме
Влад Р. STM32. Функция задержки Jun 27 2012, 19:47 skripach Ну сделайте вы по людски, что-нибуди вроде:
Кодvo... Jun 27 2012, 20:58 Влад Р. Цитата(skripach @ Jun 27 2012, 23:58) Ну ... Jun 27 2012, 21:01 Сергей Борщ QUOTE (Влад Р. @ Jun 28 2012, 00:01) что ... Jun 27 2012, 21:21 Влад Р. Цитата(Сергей Борщ @ Jun 28 2012, 00:21) ... Jun 27 2012, 21:37 AHTOXA Попробуйте после записи значений ARR и PSC сделать... Jun 27 2012, 21:57 Влад Р. Цитата(AHTOXA @ Jun 28 2012, 00:57) Попро... Jun 27 2012, 22:20        vlad_new Нодо на 1 уменьшать. Я то же практически проверял.... Dec 22 2012, 09:07         AHTOXA Цитата(vlad_new @ Dec 22 2012, 15:07) Не ... Dec 22 2012, 17:15        HHIMERA Цитата(AHTOXA @ Dec 22 2012, 11:50) А я п... Dec 22 2012, 10:09 sgs АНТОХА написал все правильно. Есть только один тон... Jun 28 2012, 04:36 scifi Странный выбор таймера для задержки, если только в... Jun 28 2012, 05:39 ViKo Из мануала RM0041 на STM32F100
ЦитатаThe counter c... Dec 22 2012, 10:20 HHIMERA Цитата(ViKo @ Dec 22 2012, 14:20) То, что... Dec 22 2012, 10:32  ViKo Даете противоречивые показания.
Цитата(HHIMERA ... Dec 22 2012, 10:50   HHIMERA Update_event = TIM_CLK/((PSC + 1)*(ARR + 1)*(RCR +... Dec 22 2012, 11:00    ViKo Цитата(HHIMERA @ Dec 22 2012, 14:00) ...
... Dec 22 2012, 11:13   HHIMERA Цитата(ViKo @ Dec 22 2012, 13:50) По руко... Dec 22 2012, 11:20    ViKo Цитата(HHIMERA @ Dec 22 2012, 14:18) Спас... Dec 22 2012, 11:46     HHIMERA Цитата(ViKo @ Dec 22 2012, 14:28) Нихрена... Dec 22 2012, 11:58      ViKo Цитата(HHIMERA @ Dec 22 2012, 14:58) Так ... Dec 22 2012, 12:02 ViKo Сочинил задержку подлиннее. Тактовая частота подра... Dec 23 2012, 14:16 ViKo Хочу продолжить. Написать универсальную задержку, ... Dec 28 2012, 06:26 NaughtyFreak Очень наворочено
Почему правда для задержки не ... Dec 28 2012, 08:17 ViKo Цитата(NaughtyFreak @ Dec 28 2012, 11:17)... Dec 28 2012, 09:10 ViKo Типа такого, но на препроцессоре.
CODE#define FT_... Dec 28 2012, 14:07 polyname ЦитатаИ усё. в зависимости от надобности кофигурир... Dec 28 2012, 17:44 sidy Поскольку в данной теме много разбирающихся в нюан... Mar 8 2013, 19:12 Mimik Всем привет, прошу вашей помощи. Устроился на нову... Jun 10 2014, 11:08
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|