Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Формирование задержки
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
aspID
На данном этапе некритично, но интересно, как можно формировать задержки длительностью в единицы мкс.

На данный момент используется:
Код
#define _delay_us(x) __delay_cycles(x*F_CPU/1000000)


на частоте
Код
#define F_CPU 3686400UL
просто исполняю следующий код и смотрю за сигналом
Код
  DDRD |= (1 << PD6);
  while (1)
  {
    PORTD |= ( 1 << PD6 );
    _delay_us(5);
    PORTD &= ~( 1 << PD6 );
    _delay_us(1);
  }

на уровне десятков мкс работает нормально, 5 мкс растягиваются до 5,4 мкс а 1 мкс - до 1,85 мкс

Если работать через прерывания таймера - думается мне, обработка не даст большей выгоды. Или я не прав? Как вариант, конечно, увеличивать частоту кварца...
zltigo
Цитата(aspID @ Sep 11 2007, 13:47) *
Если работать через прерывания таймера - думается мне

Если есть таймер, безусловно надо пользоваться им и не маяться дурью с программыми задержками. Только прерывания никчему - просто ожидание в цикле достижения таймером нужного значения. Систематическая погрешность на вызов функции и 'startup' по любому будет присутствовать....

P.S.
Только причем здесь IAR??? Выбирая ветку форума надо подумать...
aspID
Цитата(zltigo @ Sep 11 2007, 17:57) *
Если есть таймер, безусловно надо пользоваться им и не маяться дурью с программыми задержками. Только прерывания никчему - просто ожидание в цикле достижения таймером нужного значения.

А какже время на установку регистров и обработку значений таймера? На единицах микросекунд оно уже будет давать свой "осадок"... unsure.gif

Цитата
Только причем здесь IAR??? Выбирая ветку форума надо подумать...

Подумал и пришел к выводу, что непосредственно к МК AVR оно имеет равное отношение как и к IAR. Стареет логика? Sorry, просьба переместить...
alexander55
Цитата(aspID @ Sep 11 2007, 15:06) *
А какже время на установку регистров и обработку значений таймера? На единицах микросекунд оно уже будет давать свой "осадок"... unsure.gif
Подумал и пришел к выводу, что непосредственно к МК AVR оно имеет равное отношение как и к IAR. Стареет логика? Sorry, просьба переместить...

Судя по первому сообщению, Вы работаете с AVR. задайте вопрос там.
Коротко.
Прерывание при малых задержках бред.
Насчет точности абстрактный пример.
Прибор имеет 100 делений класс 5, т.е 5 %.
При полной шкале, 100 делений - ошибка 5%, т.е. 5 делений.
При 50 -10%, т.е. 5 делений.
При 10 -50%, т.е. 5 делений.
При 5 -100%, т.е. 5 делений.
При 1 -500%, т.е. 5 делений.
Мораль - измерение малых величин некорректно.
aspID
Цитата
Мораль - измерение малых величин некорректно

Хотите сказать, что наны вообще нереально использовать? Или кварца в 3,6864МГц для микросекунд мало??

Цитата
Прерывание при малых задержках бред.

Это все-таки к чему? К тому, что следует перейти на таймер или все же оставаться на макросе?

Просто с конкретным случаем - "использование макроса" я проверил работу, а со случаем "использование таймера" не заморачивался. Наверняка не я первый, не я последний задался этим вопросом...
bodja74
Мораль очень проста smile.gif
1 микросекунда - это почти 4 такта ядра,а точнее 3.6864 smile.gif при частоте 3,6864МГц
Возможно четыре NOP спасут отца русской демократии ,если устроит такая точность smile.gif
AndreyKeil
На вашем месте я бы сделал так:


#define F_CPU 0.277778 //это равно 1/3.686400
//while (1) {
// PORTD|= (1 << 6);

XX0: SBI 0x12, 0x06
// __delay_cycles(5/F_CPU);
LDI R16, 5
XX1: DEC R16
BRNE XX1
RJMP XX2
// PORTD&= ~(1 << 6);
XX2: CBI 0x12, 0x06
// __delay_cycles(1/F_CPU-3); //...-3 это поправка(количество циклов)
RJMP XX0
}

В симуляторе получилось 5,15 и 1,09 мкс. smile.gif

А если хотите получить точно 5 и 1 мкс то надо взять кварц кратный 1МГц (допустим 10МГц).
Ну и ещё как вариант, использовать ассемблер.
SasaVitebsk
Мораль такова что IAR максимально точно генерит задержку, но, естественно, она должна быть кратна целому числу тактов процессора. Так как не существует команды выполняющейся за пол такта. Соответственно 5мкс/1/3.6864 = 5*3.6864 = 18.432 что соответствует 18 тактам. 18/3.6864=4.88мкс

Вероятно вы вставили операцию работы с портом с двух сторон чтобы замерить это это добавило ещё 2 такта 20/3.6864 = 5.425мкс - что полностью соотносится с увиденным
ReAl
Цитата(SasaVitebsk @ Sep 11 2007, 19:07) *
Мораль такова что IAR максимально точно генерит задержку, но, естественно, она должна быть кратна целому числу тактов процессора. Так как не существует команды выполняющейся за пол такта. Соответственно 5мкс/1/3.6864 = 5*3.6864 = 18.432 что соответствует 18 тактам. 18/3.6864=4.88мкс
Вероятно вы вставили операцию работы с портом с двух сторон чтобы замерить это это добавило ещё 2 такта 20/3.6864 = 5.425мкс - что полностью соотносится с увиденным

А учитывая то, что задержка почти наверняка генерируется при помощи чего-то подобного
Код
    ldi r16, some_constant
L1:
    dec r16
    brne L1

время вообще кратно не одному, а трём целым тактам (тут с 18-ю просто повезло).
Для 1мкс some_constant = 1, три такта на этом "цикле", два такта на rjmp к началу while(1) и два такта на sbi, в которое превратилось PORTD |= ( 1 << PD6 ); - итого семь тактов, 1,9мкс - так что всё на месте.
SasaVitebsk
Цитата(ReAl @ Sep 11 2007, 21:48) *
А учитывая то, что задержка почти наверняка генерируется при помощи чего-то подобного
Код
    ldi r16, some_constant
L1:
    dec r16
    brne L1

время вообще кратно не одному, а трём целым тактам (тут с 18-ю просто повезло).
Для 1мкс some_constant = 1, три такта на этом "цикле", два такта на rjmp к началу while(1) и два такта на sbi, в которое превратилось PORTD |= ( 1 << PD6 ); - итого семь тактов, 1,9мкс - так что всё на месте.


Нет. Задержка генерируется точно согласно алгоритму и выравнивается с точностью до такта.

То есть если вы закажите 2 такта, то будет
rjmp pc+1
если 3
rjmp pc+1
nop
если значительное, то вызов процедуры с заданием параметра + выравнивание недостающих тактов.
defunct
Цитата
Это все-таки к чему? К тому, что следует перейти на таймер или все же оставаться на макросе?

К тому что на практике в МК не нужны короткие задержки.
Использовать таймер для более менее нормальных задержек (от единиц ms с тактовой >8Mhz).

Там где нельзя отказаться от коротких задержек - надо правильно подбирать чип и кварц - не megaXXX на 3.68Mhz, а tinyXXX на 16.000Mhz, 20.000Mhz. чтоб микросекунда получалась целым числом тактов, и чтоб тактов в микросекунде получалось как можно больше. Программу писать не на Си, а на asm. Как правило, там где могут понадобиться очень короткие задержки, там будет очень короткая и тупая программа (за очень редким исключением).
aspID
Большое спасибо отозвавшимся. Намотал на ус :-)
Измерял время с помощью осциллографа, а кварц "некратный" был выбран "кратным" для возможности работы с USART на 115200. smile.gif

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