Тут переменных типа nStartTimerVal м.б. сколько угодно, и проверять одну засечку времени можно на несколько значений таймаута (иногда я и такое пользую

Разрядность таймерной переменной можно понятно любую, но в timer0ISR() и getTimer() необходимо обеспечить атомарность модификации и чтения переменной.
Здесь смущает только ситуация, когда uiTimer0Count переполнится: 0xffffffff -> 0x0.
При этом вычисления для текущих таймеров будут неверными.
Как этого избежать?
Оно само решается.
Допустим Вы сделали засечку в 0xFFFFFFFE, т.е. uiTimer0Count==0xFFFFFFFE, а таймаут хотите 4.
т.е. if(VerifyTimer(nStartTimerVal, 4))
и
#define VerifyTimer(s,t) ((t) <= (getTimer()-(s)))
тогда:
через 0 мс if(4 <= (0xFFFFFFFE - 0xFFFFFFFE)) или (4 <= 0) - ложь
через 1 мс if(4 <= (0xFFFFFFFF - 0xFFFFFFFE)) или (4 <= 1) - ложь
через 2 мс if(4 <= (0x00000000 - 0xFFFFFFFE)) или (4 <= 2) - ложь
через 3 мс if(4 <= (0x00000001 - 0xFFFFFFFE)) или (4 <= 3) - ложь
через 4 мс if(4 <= (0x00000002 - 0xFFFFFFFE)) или (4 <= 4) - истина
через 5 мс if(4 <= (0x00000003 - 0xFFFFFFFE)) или (4 <= 5) - истина
....
через (2^32-1)мс if(4 <= (0xFFFFFFFD - 0xFFFFFFFE)) или (4 <= 0xFFFFFFFF) - истина
через (2^32)мс if(4 <= (0xFFFFFFFE - 0xFFFFFFFE)) или (4 <= 0) - ложь
Т.е. Вы должны проверять чаще чем (пересчёт_таймера - таймаут)
Цитата
И, извиняюсь, я не знаю, что значит "обеспечить атомарность"... 
А - вспомнил - одновременное действие?

А - вспомнил - одновременное действие?
Не совсем. Скорее неделимое действие.
Представте что таймер у Вас 64-х разрядный, а процессор 32-х, и в GetTimer() непосредственно после чтения одной части (например младшей, равной 0xFFFFFFFF) происходит прерывание и вся переменная инкрементируется. Тогда стартшую часть переменной GetTimer() вернёт некорректно по отношению к младшей.
Способы обеспечения атомарности разные.
- запрет/восстановление прерываний.
- использование спец. инструкций проца (чтение-модификация-запись например для x86)
- В многопроцессорных делах ещё и lock-и межпроцессорные.
- и т.д.