Сообщение от proba60
|
а вот это не работает
int tim=50;
delay_us (tim);
|
Потому, что delay_ms() построена так:
Имеется процедура задержки на 1 мс. В регистр Y загружается количество раз, которое будет вызываться процедура. И потом в цикле вызывается процедура задержки на 1 мс указанное количество раз.
Процедура задержки на 1 мс - это пустой цикл. Количество раз выполнения которого расчитывается на этапе компиляции в зависимости от тактовой частоты.
Код:
|
_delay_ms:
adiw r26,0
breq __delay_ms1
__delay_ms0:
__DELAY_USW 0x7D0
wdr
sbiw r26,1
brne __delay_ms0
__delay_ms1:
ret |
__DELAY_USW - это как раз макрос пустого цикла, который выполняется 1 мкс.
А 0x7D0 - это количество итераций, равное CLK / 4000.
Функция
delay_us() - это всего один цикл. На самом деле всё тот же макрос
__DELAY_USW. Параметр которого расчитывается на этапе компиляции.
Если хотите - делайте свой аналог
delay_us.
Например:
Код:
|
i = 1;
do {i--;} while(i); |
Одна итерация цикла выполнится за 6 тактов.
Общее время выполнения на 2 такта больше.
Соответственно при тактовой частоте 1 Мгц минимальная задержка 8 мкс.
При таком подходе нужно смотреть ассемблерный листинг. Потому, что количество тактов на 1 итерацию цикла может существенно измениться. Например, если компилятор разместит перемнную i в регистрах X-Z количество тактов может стать 4.
И наоборот, при нехватке регистров количество тактов может возрасти до 14 и более (за счёт размещения переменной в памяти).