Zuerst das while (true) { ...} ?? Kann man damit die Schleife unterbrechen, oder warum gehört das so?
while(true) {...} ist eine Endlosschleife, alles was im {...}-Block ist, wird endlos wiederholt. Wenn der Ausdruck in den normalen Klammern (Abbruchbedingung) false ist wird die Schleife abgebrochen (was bei true natürlich nie der Fall sein wird).

if(...) {...} funktioniert praktisch genau gleich, wenn der Ausdruck in den normalen Klammern true ergibt, wird alles was zwischen den geschweiften Klammern steht ausgeführt.

Warum das Rufzeichen (Negation)? Kann man stattdessen nicht ein Oder nehmen? Werde das gleich mal probieren...
Wenn du das ! weglässt, ist das mit der Taste genau umgekehrt, alles was im if-Block steht, wird ausgeführt, wenn sie nicht gedrückt ist. Also negiert man den Ausdruck, um den Block nur auszuführen, wen die Taste gedrückt ist. Nein man kann hier kein Oder nehmen...

void main ging nicht, er schrieb irgendwas von 'integer benötigt'. Habe das void weggelassen und es ging...
Was für einen Compiler benutzt du, eigentlich muss void gehen, sonst kannst du int main() schreiben und dann musst du vor die letzte geschweifte Klammer noch return 0; schreiben (dadurch gibt die Funktion eine Integer Null zurück, was soviel bedeutet, wie alles fehlerfrei ausgeführt (obwohl die Stelle durch die Endlosschleife nie erreicht wird). nur main() ist auf jeden Fall ein ganz schlechter Programmierstil (selbst wenn es geht).

Ach ja, und die 500 ms klommen mir vor wie 2sek, aber das ist erstmal nebensächlich...
Das liegt wahrscheinlich daran, dass dein Programm die Frequenz, mit der der µC läuft nicht kennt, binde mal util\delay.h ein (#include <util\delay.h> in die erste Zeile schreiben). In der nächsten Zeile definierst du dann F_CPU mit dem Takt deines µCs (bei 4MHz schreibst du z.B. #define F_CPU 4000000UL).
Jetzt kannst du statt WaitMs() die Funktion _delay_ms(x) benutzen (x steht für dei Anzahl ms, die gewartet werden soll). Das müsste eigentlich funktionieren.

mfg