Против uint32_t ничего не имею

Однако плавучка тоже имеет право на жизнь (вкупе с uint16_t или uint32_t - не важно).
Дело в том, что если времена не передаются извне или вычисляются в программе, а жёстко заданы на момент компиляции, то всю плавучку можно спрятать в compile-time (собственно, util/delay.h так и делает).
Зато просто удобно писать плавающее число.
delay_s.h
Код
#ifndef DELAY_S_H
#define DELAY_S_H
#include <util/delay.h>
static inline void delay_s(float s)
{
uint16_t i = s * 100;
if(i) do _delay_ms(10); while(--i);
}
#endif
d.c
Код
#include "delay_s.h"
void foo()
{
delay_s(3.5);
}
avr-gcc -Os -DF_CPU=8000000UL -mmcu=atmega48 d.c
Код
foo:
ldi r18,lo8(350) ; вот оно uint16_t i = s * 100 - две команды загрузки и всё
ldi r19,hi8(350)
.L2:
ldi r24,lo8(20000)
ldi r25,hi8(20000)
/* #APP */
1: sbiw r24,1
brne 1b
/* #NOAPP */
subi r18,lo8(-(-1))
sbci r19,hi8(-(-1))
brne .L2
ret
Другое дело, что это же (и тоже с плавучкой) можно сделать и через задержку в циклах с макросом SEC_TO_CYCLES(), который принимает плавающее число, множит/делит c учётом F_CPU (всё во время компиляции!) и выдаёт uint16_t или uint32_t неких попугайных циклов, принимаемых нужной функцией.
Но это достаточно вкусовой вопрос.
p.s. Сам я первое, что пишу для новой платы - это таймерное прерывание, свободно бегущий таймер и отработку таймаутов ( ну это вот if(timeout) --timeout; как в приведенном примере прерывания), иногда таких таймаутов несколько для разных задач, какие-то в тиках, какие-то в уже секундах. Но "случаи бывают всякие" и я бы не стал с порога отвергать задержки по месту и аккуратно применённый float, который заканчивает свою жизнь в compile-time.