Wenn Du nicht erzählst, was für Delays Du verwendest, kann man nur
raten. Ich vermute aber, dass Du die Begrenzung der _delay_ms-Funktion
überschritten hast. Die ist nämlich auf 262,14ms/F_CPU[MHz] begrenzt,
also bei 16 MHz auf maximal ca. 16,4 ms. Bei allem was länger ist kommt
Murks raus. Ohne Optimierung werden die _delay_XX-Funktionen aufgebläht
und wesentlich länger als gewünscht, so dass es durchaus nachvollziehbar
ist, dass es ohne Optimierung funktioniert (schließlich sind die Pausen
zwischen den einzelnen Zugriffen dann länger, was im Prinzip nicht
schlimm ist. Nur kürzer dürfen sie halt nicht sein).
"L" bedeutet "long" und "UL" "unsigned long". Soll dafür sorgen, dass
Berechnungen mit diesen Werten in einem Wertebereich durchgeführt
werden, der ausreichend groß ist, dass es keinen Überlauf gibt.
Standardmäßig rechnet der Compiler mit 16 Bit, und da passen 16000000
nunmal nicht rein.