www.mikrocontroller.net

Forum: Compiler & IDEs Source-Code an andere Stelle -> funktioniert nicht mehr.


Autor: Wolfgang K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Habe ein sehr komisches Problem, dass mich zur Verzweiflung bringt.

Folgenden Auszug aus dem Sourcecode für die Ansteuerung eines Pins:

if (variable_a == ON)  PORTD |= (1 << PD4);
if (variable_a == OFF)  PORTD &= ~(1 << PD4);

if (variable_b == ON)  PORTD |= (1 << PD5);
if (variable_b == OFF)  PORTD &= ~(1 << PD5);

Der Source-Code von variable_a funktioniert, der von b aber nicht.
Tausche ich nun die Zeilen untereinander aus ist es genau umgekehrt, 
variable_b funktioniert und a nicht mehr... warum?


Hier mein Memory Usage:

AVR Memory Usage:
-----------------
Device: atmega8

Program:    5144 bytes (62.8% Full)
(.text + .data + .bootloader)

Data:        125 bytes (12.2% Full)
(.data + .bss + .noinit)


Die Optimierung ist auf s gestellt.

Was ist das Problem? Compiler?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wolfgang K. wrote:

> Was ist das Problem? Compiler?

Mit 99.9% Wahrscheinlichkeit sitzt das Problem vor dem
Bildschirm :-)

Zeig mal den ganzen Code.

Autor: Wolfgang K. (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
:-) Das dachte ich am Anfang auch, aber habe alles durchgesehen, da die 
Programmteile dieser Ausgänge genau gleich sind. Es ist aber alles 
komplett gleich (bis auf variablenname, usw. ;-))

Der Source-Code hat um die 900 Zeilen, darum schreibe ich noch dazu, wo 
das Problem auftritt:

Im Unterprogramm Ausgang_setzen() werden die Pins angesteuert, je 
nachdem welchen Zustand die zugehörige Variable hat. Komplett einfach 
gehalten. Der Zustand der zugehörigen Variablen in der if-Abfrage ist 
korrekt (0 oder 1), d.h. das funktioniert alles. Es funktionieren alle 
Ausgänge einwandfrei, bis auf den für den Motorraum (Zeile 478 und 479).
Tausche ich nun die beiden Zeilen für den Motorraum (Zeile 478 und 479) 
mit z.b. den Frontsystem-Zeilen (Zeile 465 und 466) aus, funktioniert 
der Motorraum-Ausgang, dafür aber ein anderer von diesen auf einmal 
nicht mehr.

Darum bin ich mir sicher, dass kein Programmfehler vorhanden ist, da der 
Ausgang, der vorher nicht funktioniert hat, auf einmal funktioniert, 
wenn man seine Code-Zeilen wo anders hinverschiebt, wo es aber keinen 
Einfluss darauf hat.


PLEASE HELP!...

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Troll: 900 Zeilen Code in einer C-Datei... Was ist da schief gelaufen? 
;) ;)

Autor: Wolfgang K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
dachte am anfang das programm wird nicht so gross, hab es dann aber 
immer weiter ausgebaut und mir ist es egal, wenn alles in einer datei 
ist, und nicht auf mehrere aufgeteilt.

Autor: Wolfgang K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wenn du es gekürzt haben willlst:

-) alles mit lcd funktioniert einwandfrei
-) schalter einlesen funktioniert
-) menüs funktionieren

eigentlich funktioniert ALLES einwandfrei, bis auf die Ausgabe durch die 
Variable Motorraum.
Werden die Ausgaben in einer anderen Reihenfolge getätigt, funktioniert 
eine andere nicht, aber Motorraum dafür...

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wolfgang K. wrote:

> dachte am anfang das programm wird nicht so gross, hab es dann aber
> immer weiter ausgebaut und mir ist es egal, wenn alles in einer datei
> ist, und nicht auf mehrere aufgeteilt.

Dir ja, aber nicht denen, die den Kram nun reviewen sollen, weil du
nicht mehr wirklich durchblickst...  Compilieren lässt es sich auch
nicht, weil noch allerlei anderer Kram ringsrum fehlt.

Aber eigentlich ist die Sache recht eindeutig:
        if (Fussraum == ON)             PORTD |= (1 << PD0);
        if (Fussraum == OFF)            PORTD &= ~(1 << PD0);
        if (Fussraum == BLNK)
        if (Fussraum == GLOW)
        if (Fussraum == RPM1)
        if (Fussraum == RPM2)

        if (Motorraum == ON)            PORTD |= (1 << PD1);
        if (Motorraum == OFF)           PORTD &= ~(1 << PD1);

Guck dir mal die Zeilen vor deiner ,,Problemzeile'' an, dann sollte
dir der Seifensieder aufgehen.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jörg Wunsch wrote:

> Guck dir mal die Zeilen vor deiner ,,Problemzeile'' an, dann sollte
> dir der Seifensieder aufgehen.

Hehe, böser Fehler ;-)

MFG
Falk

Autor: Wolfgang K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alles klar!!! ;-))

Hab einfach alle Zustände hingeschrieben und wollte sie nacheinander 
hinzufügen... :-))))

Danke Jörg!!!

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tja, mit einem Editor, der automatisch das Einrückungsniveau selbst
ermittelt, wär dir das nicht passiert...

Autor: Marian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich als Anfänger sehe das Problem immer noch nicht :). Kann mir das 
einer genau erklären oder genauer drauf zeigen?

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Marian (Gast)

>Ich als Anfänger sehe das Problem immer noch nicht :). Kann mir das
>einer genau erklären oder genauer drauf zeigen?

Ja.

        if (Fussraum == ON)             PORTD |= (1 << PD0);
        if (Fussraum == OFF)            PORTD &= ~(1 << PD0);
        if (Fussraum == BLNK)
        if (Fussraum == GLOW)
        if (Fussraum == RPM1)
        if (Fussraum == RPM2)

        if (Motorraum == ON)            PORTD |= (1 << PD1);
        if (Motorraum == OFF)           PORTD &= ~(1 << PD1);

Die vier if() ohne Anweiusung dahinter (welche später einfügt werden 
sollten) sind ja nicht einfach weg, sondern werden schön brav 
ausgeführt. Allerdings kommt dann eine GANZ anderes Struktur raus. 
Nämlich die (umgeschriene mit Einrückung un Klammern, verkettete If() 
Anweisungen)
        if (Fussraum == ON)             PORTD |= (1 << PD0);
        if (Fussraum == OFF)            PORTD &= ~(1 << PD0);
        if (Fussraum == BLNK) {
          if (Fussraum == GLOW) {
            if (Fussraum == RPM1) {
              if (Fussraum == RPM2) {

                if (Motorraum == ON)            PORTD |= (1 << PD1);
              }
            }
          }
        } 
        if (Motorraum == OFF)           PORTD &= ~(1 << PD1);

Böse Falle. Mit Pascal wär das nicht passiert ;-)

MfG
Falk

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wäre übrigens auch nicht passiert, wenn man das ,,Gerippe'' einfach
komplett durchgezogen hätte:
        if (Fussraum == ON)             PORTD |= (1 << PD0);
        if (Fussraum == OFF)            PORTD &= ~(1 << PD0);
        if (Fussraum == BLNK)           ;
        if (Fussraum == GLOW)           ;
        if (Fussraum == RPM1)           ;
        if (Fussraum == RPM2)           ;

        if (Motorraum == ON)            PORTD |= (1 << PD1);
        if (Motorraum == OFF)           PORTD &= ~(1 << PD1);

Ich vermute, dass es Wolfang auch nicht nochmal passiert. ;-)

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ah da drüben winkt gerade "Hr. Switch-Case" mit seinem Zaunpfahl..

Autor: Martin Thomas (mthomas) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es schadet nicht, zumindest eine Kurzfassung der "MISRA roules" (MISRA 
Guidelines for the Use of the C Language in Vehicle Based Software) 
durchzulesen, z.B. MisraC.pdf von iar.com. Einige der Regeln sind 
vielleicht etwas übertrieben aber viele simple Fehler kann man durch 
Beachtung des Regelsatzes vermeiden. Oben wurde z.b. Rule 59 nicht 
beachtet: "The statements forming the body of an if, else if, else, 
while, do … while or for statement shall always be enclosed in braces." 
Bei Anwendung der Regel hätte man das gesehen, was Falk Brunner gezeigt 
hat und die Fehlerursache wäre deutlich offensichtlicher geworden. 
(Nähkästchen: Ja - ich beachtet die Regeln auch nicht immer wenn nicht 
grade explizit verlangt aber das hat sich auch schon gelegentlich 
gerächt und längeres "Codeanstarren" oder Debug-Sitzungen eingebracht.)

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Jörg

>>        if (Fussraum == BLNK)           ;

vieleicht doch besser so

        if (Fussraum == BLNK)           { }

Sonst kommt man leicht zu einem

        if (Fussraum == BLNK)           ;
         { MachMalWas(); }


Ist immer wieder nett sowas zu debuggen ;)

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja, ich war schon davon ausgegangen, dass nach jedem dieser "if"s
ohnehin nur ein einfacher Ausdruck (im Sinne des ,,Bitwackelns'')
stehen soll.  Dafür finde ich wiederum, dass die Übersichtlichkeit
insgesamt am Ende besser ist, als wenn man stur der MISRA-Regel
folgt.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich leg noch mal ein schönes Macro drauf ;)

#define SPI_WAIT()    while(!(SPI_STATUS_REGISTER & ( 1<<SPIF ))); 
spi_back_byte=SPI_DATA_REGISTER;


        if (Fussraum == BLNK)           SPI_WAIT();

oder doch besser ?

        if (Fussraum == BLNK)           { SPI_WAIT(); }

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was kann ich denn dafür, dass du wie Funktionen aussehene Makros
so schreibst, dass sie sich doch nicht wie Funktionen benehmen?

Jedes Kind :) weiß doch, dass man den Makro so schreibt:
#define SPI_WAIT()    do { while(!(SPI_STATUS_REGISTER & ( 1<<SPIF ))); } while (0)

(Kein Spaß.  Verquerer Konstrukt, aber der Makro tut danach, was man
von ihm erwartet.)

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Was kann ich denn dafür, dass du wie Funktionen aussehene Makros
>so schreibst, dass sie sich doch nicht wie Funktionen benehmen?

Natürlich gar nichts.

Das hier gehört eigentlich in EINE Zeile:

>#define SPI_WAIT()    while(!(SPI_STATUS_REGISTER & ( 1<<SPIF ))); 
>spi_back_byte=SPI_DATA_REGISTER;

Das sollte nur mal verdeutlichen was einen erwarten kann
wenn man keine {} hinter if oder for setzt. Bei Macros kann
das tödlich sein.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>>Das hier gehört eigentlich in EINE Zeile:

>>#define SPI_WAIT()    while(!(SPI_STATUS_REGISTER & ( 1<<SPIF )));
>>spi_back_byte=SPI_DATA_REGISTER;

Kleiner Nachtrag:  Das tut auch was ich möchte OHNE
diesen merkwürdigen Konstrukt. Man muss halt nur Klammern setzen.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
holger wrote:

> Kleiner Nachtrag:  Das tut auch was ich möchte OHNE
> diesen merkwürdigen Konstrukt. Man muss halt nur Klammern setzen.

Das widerspricht aber dem `principle of least astonishment'.  Der
Implementierer des Makros (und nur der) weiß, dass sich sein Makro
nicht wirklich so verhält, wie er auf den ersten Blick aussieht
(nämlich wie eine Funktion).  Folglich sehe ich denjenigen in der
Pflicht, sich um die Vermeidung entsprechender Seiteneffekte zu
kümmern, statt diese Verpflichtung auf den Benutzer des Makros zu
übertragen (was du mit deiner zwanghaften Verpflichtung, nach einem
if ein Paar Klammern zu setzen, letztlich machst).

Klar ist der Anweder in der Regel gut beraten, wenn er die Klammern
setzt, aber da es die Sprache nicht vorschreibt, dass sie gesetzt
werden müssen, gehört es halt genauso gut zur ,,Unfallverhütung'',
dass man die Makros selbst ,,idiotensicher'' macht.  (In diese
Kategorie fällt auch mit, dass ein Makro all seine benutzten
Makro-Argumente selbst klammert.)

Alternativ kannst du deinen Makro ja auch mit einer inline-Funktion
realisieren, wenn dir der do...while(0)-Hack nicht gefällt.

Autor: Marian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Falk Brunner: Danke, die 4 if Anweisungen habe ich natürlich völlig 
ignoriert :). Finde den Fehler sehr interessant, da lohnt es sich doch 
ein paar Klammern mehr zu setzen um solche Dinger ungeschehen zu machen.

Autor: Wolfgang K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann hat mein problem schon mal jemand anderem auch geholfen... :-)

Aus fehlern lernt man und macht sie nicht mehr.

mfg

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jörg Wunsch wrote:
> ...
> Folglich sehe ich denjenigen in der
> Pflicht, sich um die Vermeidung entsprechender Seiteneffekte zu
> kümmern, statt diese Verpflichtung auf den Benutzer des Makros zu
> übertragen (was du mit deiner zwanghaften Verpflichtung, nach einem
> if ein Paar Klammern zu setzen, letztlich machst).
> ...

Das sehe ich genau so wie du. (Immerhin bist du hier der erfahrene 
Programmierer)

In meiner T6963c-Library habe ich auch ein paar Makros in die 
Header-Datei gepackt um zwei Funktionsaufrufe quasi zu bündeln. Dort 
habe ich ebenfalls das do{}while(0); Konstrukt benutzt.

Also: Auch wenn man weiß, dass man immer schön Klammern setzt, und genau 
deswegen das Makro schlampig designt, dann kommen die bösen Fehler 
spätestens dann, wenn nen Anfänger (oder Ahnungsloser ;)) sich den Mist 
kopiert und bei sich einbaut. Absolut Gemeingefährlich.

PS: Zum Glück hatte ich zum Zeitpunkt der T6963c Library schon was von 
dem do{}while(0);-Hack gehört. Sonst hätte ich es zu diesem Zeitpunkt 
auch nicht besser gewusst *räusper... ;)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.