просто засъснение:
Код за потвърждение:
for (volatile int i = 0; i < 1000; i++);
Без volatile оптимизаторът (почти) винаги просто игнорира реда (и закъснението).
Зависи от тактовата честота, от натовареността, от времето на Луната ... много неща

.
Ниска прецизност. Същия ред в друга част на програмата може да доведе до друго забаяне.
---
За фиксация на точността на времето на забавне добре би било да използваме таймерX, SysTick, DWT ...
Полезен линк:
How to use Systick to achieve microsecond (μs) level delay in STM32?---
Случай от днешния ден: пренасям програмен код за DS18B20 от G030 към F411. Clock от кварц с PLL: от 64 MHz -> на 100 MHz.
DS18 не ще, и не ще, и не ще ... За анализ на времето използвах 8 входов логически анализатор. Първо: не се изпращаха коректно командите по време към DS18. С малка корекция на времето (80 за G030 -> 100 за F411) това стана ОК - командите започнаха да се декодират от датчика и той започна да връща отговор.
Код за потвърждение:
void delay_us(uint32_t us) {
volatile uint32_t i = 90 * us;
i /= 10;
while (i--);
}
Следваше: четене на върнатите данни. И грешки от четенето, и грешки, и грешки, и грешки ...
Прекочих CRC анлиза: температурата самопроизволно скчаше, през 4-10 s за кратко: показваше истинска температура, ново скачане ... до безкрайност.
Първо заподозряно: неточни времена в 1-wire проткокола. От първия път замяната на "простите закъсненията" на "закъснения от DWT" моментално поправи реакцията (без последваща корекция на методите на писане и четене).
Следва като собствен извод: никога повече "просто закъснение" за прецизни дейности. (в псевдо-код: "нищонеправене" -> изпълнявай n-пъти)

delay в μs с DWT:
Код за потвърждение:
void dwt_init(void) {
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CYCCNT = 0;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
}
void delay_us(uint32_t us) {
uint32_t cycles = (SystemCoreClock / 1000000) * us;
uint32_t start = DWT->CYCCNT;
while ((DWT->CYCCNT - start) < cycles);
}
код:
Код за потвърждение:
delay_us(64);
и резултат с лог. анализатор: