Ungewöhnliches oder merkwürdiges Verhalten: uint8_t in for-Schleife in avr MCU

Ich lerne das Programmieren von MCU mit c

Ich verwende Atmel Studio 7, Averdude, USBasp und Atmega16a

das ist mein Code

#define F_CPU 1000000
#include <avr/io.h>
#include <util/delay.h>


int main(void) {

DDRA = 0xff;
DDRC = 0xff;

while (1) {
    for (uint8_t i = 8; i >= 0; i--) {
        PORTA = (1 << i);
        _delay_ms(100);
    }

    PORTC = 1;
    _delay_ms(1500);
}

return (0);
}

Die for-Schleife wurde nie beendet und wenn sie i=0die erste LED erreicht, PORTAbleibt sie etwa 14 Sekunden lang an und schaltet sich danach etwa zur gleichen Zeit aus, und danach beginnt die for-Schleife erneut, ohne sie zu erreichen

PORTC =1;
_delay_ms(1500);

wenn ich intstattdessen benutze uint8_t, funktioniert es gut

kann jemand erklären warum das passiert?

Ich stimme dafür, diese Frage als nicht zum Thema gehörend zu schließen, da es nicht um Elektronik geht. Scheint auf Stack Overflow zu gehören.
Seit wann sind Embedded-Programming-Fragen Off-Topic?
@BrianCarlton Wenn es geschlossen wird, werde ich es wohlwollend zu StackOverflow migrieren. Will das aber nicht erzwingen.
@brain carlton Ich dachte, weil es sich um eine eingebettete verwandte Frage handelt, würde sie zur Elektronik gehören. Ihrer Meinung nach wären alle Programmierfragen, auch wenn sie sich auf die Elektronik beziehen, auf SOF, ok, verstanden. Danke
@MuhammadNour Mach dir darüber keine allzu großen Sorgen. Die Grenze zwischen Embedded-Programming-Fragen und Plain-Programming-Fragen ist nicht klar gezogen. Im schlimmsten Fall würde Ihre Frage zu StackOverflow migriert werden. In diesem Fall dachten Sie, die Frage sei eingebettet, aber die Antwort entpuppte sich eher als weniger einfache Programmierung ( signedvs. unsigned).

Antworten (3)

Sie kommen an den Punkt, an dem der Wert von iist o.
i >= 0ist true.
Sie versuchen mit zu dekrementieren i--. Vielleicht erwarten Sie eine negative Zahl. Aber iist unsigniert, also bekommt man 255.
Es wird weiter dekrementiert, bis Sie auf Null kommen. Dann wiederholt sich alles noch einmal.

Wenn ies signiert wäre, würde die Schleife 9 Iterationen machen.

Der folgende Code hat diesen negativen Effekt nicht. Beachten Sie die strikte Ungleichung. Diese Schleife wird 8 mal durchlaufen.

for (uint8_t i = 8;  i > 0;  i--) { // strictly greater
    // [...]
}

"i >= 0" ist immer wahr, weil i vorzeichenlos ist.

Die Wunder von 0-1 = 255.

Wenn Sie i = 7, 6, ..., 0mit einer Indexvariablen ohne Vorzeichen iterieren möchten, ist das übliche Muster

for (uint8_t i = 8; i-- > 0; ) {
    PORTA = (1 << i);
    _delay_ms(100);
}

obwohl das auf den ersten Blick komisch aussieht. Einige Leute ziehen es vor, immer ansteigende Schleifen zu haben:

for (uint8_t ii = 0; ii < 8; ++ii) {
    uint8_t i = 7 - ii;
    PORTA = (1 << i);
    _delay_ms(100);
}

Sie können nicht i >= 0als Test verwenden, da vorzeichenlose Werte umlaufen; dekrementieren 0ergibt 255.

Wenn Sie über iterieren wollten i = 8, 7, ...,1, dann hatten Sie nur einen Tippfehler, und der Schleifentest hätte sein sollen i > 0.

Oder Sie könnten Folgendes tun:for (uint8_t i = 8; i > 0; ++i) PORTA = (1 << (i-1));