реклама на сайте
подробности

 
 
> Функция формирования задержки
Sprite
сообщение Feb 15 2012, 15:35
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 173
Регистрация: 11-05-08
Пользователь №: 37 414



Доброго всем времени суток!
Работаю на stm32f103ve в keil'е. Хочу сформировать функцию задержки. Особая точность не нужна - в пределах 1мкс вполне достаточно. Делаю так:
Настраиваю таймер:
Код
    TIM5->ARR = 0xFFFF;            
    TIM5->PSC = 71;                //72МГцчастота шины/72 = 1Мгц тик таймера
    TIM5->CR1 = 0x0001;            //Запускаю таймер

В функции задаю значение задержки в ARR и опрашиваю флаг:
Код
void Delay(u16 time)            
{
    TIM5->CNT = 0x0000;
    TIM5->ARR = time-1;
    while(!(TIM5->SR & 0x0001))
    {
        __nop();
    }    
    TIM5->SR&= ~0x0001;
}


Вобщем этот код работает только когда я вставляю его в основной цикл. Проверяю так:
Код
GPIOE->BSRR|= GPIO_Pin_2; //Установить ногу
Delay(10);                             //Задержка 10мкс.
GPIOE->BRR|= GPIO_Pin_2;   //Сбросить ногу


Если я использую этот код в обработчике нажатия кнопки, то пауза куда-то исчезает и вместо положенных 10 мкс на осцилографе наблюдается 1,2мкс.
Есть подозрение, что компилятор каким-то образом оптимизирует код, исключая цикл - другого объяснения у меня нет. Уровень оптимизации - O0 (пробовал O1, O2-результат тот же). Пробовал также объявлять параметр фукции time как volatile - не помогло. Уже ветает шальная мысль написать функцию задержки на asm sad.gif Есть ли у кого какие соображения? Может есть директивы компилятора типа:
Код
отключить оптимизацию
...
код
...
включить оптимизацию
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
esaulenka
сообщение Feb 22 2012, 10:00
Сообщение #2


Профессионал
*****

Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877



В очередной раз порекламирую другой подход к использованию таймера:

Код
typedef        uint32_t                TTimer;
#define        TIMER_COUNTER            LPC_TMR32B0->TC
#define        START_TIMER(tmr)        tmr    = TIMER_COUNTER
#define        TIMER_VALUE(tmr)        (TIMER_COUNTER - tmr)
#define        WAIT_TIMEOUT(tmr,val)    while (!(val <= TIMER_VALUE (tmr)))

__inline void delay_us (TTimer val)
{
    START_TIMER  (TTimer Tmr);    
    WAIT_TIMEOUT (Tmr, val);
}
__inline void delay_ms (TTimer val)
{
    delay_us (val * 1000);
}


Используется 32-битный таймер в LPC. Таймер настраивается на частоту 1 МГц и ни разу не сбрасывается.
Никто не мешает при этом на тот же таймер вешать какие-то другие прерывания.

Для таймеров STM надо поменять typedef TTimer на 16-битный, чтобы эта переменная переполнялась вместе с таймером.


--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
Go to the top of the page
 
+Quote Post
ViKo
сообщение Feb 29 2012, 12:54
Сообщение #3


Универсальный солдатик
******

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



Цитата(esaulenka @ Feb 22 2012, 13:00) *
typedef uint32_t TTimer;
#define TIMER_COUNTER LPC_TMR32B0->TC
#define START_TIMER(tmr) tmr = TIMER_COUNTER
#define TIMER_VALUE(tmr) (TIMER_COUNTER - tmr)
#define WAIT_TIMEOUT(tmr,val) while (!(val <= TIMER_VALUE (tmr)))
__inline void delay_us (TTimer val)
{
START_TIMER (TTimer Tmr);
WAIT_TIMEOUT (Tmr, val);
}

Допустим, TC вот-вот переполнится. Мы запоминаем его значение в переменной tmr, и потом ждем на время, пока (TC - tmr) < val. Когда TC переходит в 0, (TC - tmr) превращается в большое число, и ваша функция рапортует о таймауте, которого на самом деле еще нет.
А для STM32 с 16-битовыми счетчиками это еще более вероятно.
Нужно проверять на равенство, а не на превышение. Но в этом случае нельзя проскочить это равенство, значит, нельзя проверять изредка. То есть, не получится, к примеру, задать несколько задержек на одном таймере, и проверять их по мере необходимости.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Feb 29 2012, 14:50
Сообщение #4


фанат дивана
******

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



Цитата(ViKo @ Feb 29 2012, 18:54) *
Допустим, TC вот-вот переполнится. Мы запоминаем его значение в переменной tmr, и потом ждем на время, пока (TC - tmr) < val. Когда TC переходит в 0, (TC - tmr) превращается в большое число, и ваша функция рапортует о таймауте, которого на самом деле еще нет.
А для STM32 с 16-битовыми счетчиками это еще более вероятно.
Нужно проверять на равенство, а не на превышение. Но в этом случае нельзя проскочить это равенство, значит, нельзя проверять изредка. То есть, не получится, к примеру, задать несколько задержек на одном таймере, и проверять их по мере необходимости.
Нормально там всё.
Допустим, мы хотим проспать 20 тактов (val).
1. Засекаем время начала ожидания: tmr = TMR;
2. Потом начинаем в цикле (или изредка, как угодно) вычислять беззнаковую разность TMR-tmr, которая будет монотонно расти от 0 до 0xFFFF (в случае 16-битного таймера), и сравнивать её с val.
3. Как только значение разности станет больше чем val - готово.
Главное - не прозевать 0xFFFF тиков таймераsm.gif


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- Sprite   Функция формирования задержки   Feb 15 2012, 15:35
- - Сергей Борщ   QUOTE (Sprite @ Feb 15 2012, 17:35) Пробо...   Feb 15 2012, 17:46
|- - Sprite   Цитата(Сергей Борщ @ Feb 16 2012, 00:46) ...   Feb 16 2012, 02:34
|- - ViKo   Цитата(Сергей Борщ @ Feb 15 2012, 20:46) ...   Feb 20 2012, 08:38
|- - AHTOXA   Цитата(ViKo @ Feb 20 2012, 14:38) А еще у...   Feb 20 2012, 09:36
|- - ViKo   Цитата(AHTOXA @ Feb 20 2012, 12:36) Оно: ...   Feb 20 2012, 09:51
- - ukpyr   Код inline void _delay_loops(U32 loops) { ...   Feb 20 2012, 08:48
- - ViKo   Для ukpyr А вас прерывания и наличие буфера команд...   Feb 20 2012, 09:09
- - ViKo   Подправил код, перенес сброс запроса перед запуско...   Feb 21 2012, 08:31
|- - ViKo   Цитата(AHTOXA @ Feb 29 2012, 17:50) Норма...   Feb 29 2012, 19:01
- - ukpyr   ЦитатаА вас прерывания и наличие буфера команд не ...   Feb 22 2012, 10:06
- - esaulenka   Проверил в кейловском симуляторе. Всё нормально ра...   Mar 2 2012, 16:39


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 22:53
Рейтинг@Mail.ru


Страница сгенерированна за 0.01411 секунд с 7
ELECTRONIX ©2004-2016