Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Функция задержки
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
алексей500
А не подскажите, как реализовать функцию задержки в микросекундах, ну или в тактах, без таймера и прерываний? Нашёл на форуме вот такое:



Код
volatile unsigned int x = us * 12;

while(--x);




Только это был ответ на:

Цитата
Никто не поделиться кодом, который делает задежку в микросекундах без таймеров, а так просто с помощью нупов или циклом для частоты 48 Мгц???



А для произвольной частоты это можно организовать? Пишу в IAR. Контроллер AT91SAM7A3.
Заранее спасибо.
SSerge
Уже сделано. У IAR есть встроенная (intrinsic) функция
__delay_cycles(unsigned long int);
Сергей Борщ
Цитата(SSerge @ Jun 20 2010, 04:01) *
Уже сделано. У IAR есть встроенная (intrinsic) функция
__delay_cycles(unsigned long int);
Нету такой функции в IAR для ARM. Потому что время исполнения одной команды и участка кода рассчитать гораздо сложнее, чем на AVR, исходя из настроек всяких кешей, ускорителей флеши да и просто из места расположения команды (внутренее/внешнее ОЗУ / внутренняя/внешняя флеш).
алексей500 - возьмите осциллограф, подергайте ногой перед и после такого цикла и подберите. Рассчитать его точно невозможно по указанным выше причинам. Да еще и результат компиляции такого цикла может быть разным для разных уровней оптимизации и разных версий компилятора.
алексей500
Ок, спасибо, попробуем.
defunct
Цитата(Сергей Борщ @ Jun 20 2010, 10:36) *
Да еще и результат компиляции такого цикла может быть разным для разных уровней оптимизации и разных версий компилятора.

Если в системе есть тикающий таймер, который работает на частоте проца, то совсем нечего делать.
delay_us( ) сведется к
{
unsigned StartTime = *TIMER_CURR;
while( *TIMER_CURR - StartTime < n);
}

Если нет, то ассемблер ведь имеется.... а значит все не так уж скверно.
Пишем и размещаем где угодно

Код
__asm void delay_cycles(unsigned n)
{
do_wait
    DEC      r0
    BNE      do_wait
    BX       lr
}


Затем калибруем для получения "delay_us".
Как сделать. Ну напр так, при инициализации:

1. запустить таймер с частотой PCLK (где PCLK - при возможности сделать равной MCLK - частоте проца)
2. выполнить 1000 раз delay_cycles( n ), где n - число больше 0 но не больше чем частота MCLK / Mhz / 3
3. прочитать таймер, получить число тактов "Ticks" начиная со старта теста.
4. посчитать реальное время Tmks (в микросекундах) затраченное на 1000 пусков delay_cycles( n ), как Ticks * 10^6 / PCLK.
5. раcсчитать реальное Ncycles с которым необходимо запускать delay_cycles( Ncycles) чтобы получить задержку в 1us, по простой пропорции:

Ncycles = n * 1000 / Tmks

6. Проверить точность Ncycles (проходом с п.1 по п.4)
7. ну и подкрутить delay_cycles() парочкой NOP'ов если потребуется.
aspID
Позвольте подниму эту тему из далекого забытого прошлого...

До недавнего времени для создания задержек пользовался макроподстановками (кстати, найденными здесь же)

Код
#ifndef F_CPU
# warning "F_CPU not defined for delay.h, using 1MHz"
# warning "To define F_CPU go Proj->Opt->C/C++->Defined symbols"
# define F_CPU 1000000UL
#endif

#define _delay_ns(x) __delay_cycles(x*F_CPU/1000000000)
#define _delay_us(x) __delay_cycles(x*F_CPU/1000000)
#define _delay_ms(x) __delay_cycles(x*F_CPU/1000)
#define _delay_s(x) __delay_cycles(x*F_CPU)


Но внимательно изучая на досуге IAR C/C++ Compiler Reference Guide нашел там следующее:
Цитата
Description Makes the compiler generate code that takes the given amount of cycles to perform, that
is, it inserts a time delay that lasts the specified number of cycles.
The specified value must be a constant integer expression and not an expression that is
evaluated at runtime
.

Вот я и позадумался... а правильно ли так использовать?
Сергей Борщ
Если в качестве x вы подставляете константу, то и все выражение может быть вычисленно на этапе компиляции и компилятор может вставить код задержки на нужное количество циклов. Если в качестве x вы подставите переменную - компилятор выругается и компилировать откажется.
aspID
Цитата(Сергей Борщ @ May 22 2012, 16:35) *
Если в качестве x вы подставляете константу, то и все выражение может быть вычисленно на этапе компиляции и компилятор может вставить код задержки на нужное количество циклов. Если в качестве x вы подставите переменную - компилятор выругается и компилировать откажется.

Понял, спасибо.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.