Forum: Mikrocontroller und Digitale Elektronik Unterprogramm klappt nicht


von Michael (Gast)


Lesenswert?

Moin

Ich möchte Änderungen an einem ATmega-Port per "griffigem" Unterprogramm 
Namen machen, statt das krytisch im Programm.

So hatte ich mir das gedacht:
1
void Backlight_an(void)     { PORTD |=  (1<<PD4); } // Port PD4 high
2
void Backlight_aus(void)    { PORTD &= ~(1<<PD4); } // Port PD4 low
3
void Backlight_wechsel(void){ PORTD ^=  (1<<PD4); } // Port PD4 high<>low

Aber wenn ich im Programm die Zeilen aufrufe
1
Backlight_an;
passiert nichts. Trage ich dagegen im Programm die Zeile
1
PORTD |= (1<<PD4);
ein, dann funktionierts.

Wo liegt mein Fehler? Es soll doch nur das jeweilige Unterprogramm 
aufgerufen werden und dort die Zuweisung zum Port-D angepaßt werden, das 
kann doch nicht so schwierig sein...

Gruß
Michael

von Martin (Gast)


Lesenswert?

Warum verwendest du nicht einfach Makros?

Beispielsweise
1
#define Backlight_an    PORTD|=_BV(PD4)

von Kali (Gast)


Lesenswert?

>passiert nichts.
Was heisst das? Gibt es Compilerfehlermeldungen?

Deine Codestücke sind schon syntaktisch nicht korrekt und sollten eine 
Fehlermeldung geben. Bitte lies ein C-Buch.

Eine Funktion wie die gezeigte muss mit:
1
Backlight_an ();

aufgerufen werden.

Wenn auch bedeutend und im Widersruch zu Deiner Beschreibung ist 
andererseits auch nur diese Kleinigkeit falsch.

von Stefan E. (sternst)


Lesenswert?

Kali schrieb:
> Deine Codestücke sind schon syntaktisch nicht korrekt und sollten eine
> Fehlermeldung geben.

Doch, sind sie.

Aber eine Warnung "statement without effect" sollte eigentlich kommen.

von Michael (Gast)


Lesenswert?

Stefan Ernst schrieb:
> Aber eine Warnung "statement without effect" sollte eigentlich kommen.

Ja, die Meldung kommt. Hatte ich übersehen.

von Michael (Gast)


Lesenswert?

Kali schrieb:
> Eine Funktion wie die gezeigte muss mit:
> Backlight_an ();

Ja das wars. Danke

von Kali (Gast)


Lesenswert?

@ Stefan Ernst

>> Deine Codestücke sind schon syntaktisch nicht korrekt und sollten eine
>> Fehlermeldung geben.

>Doch, sind sie.

Nein. Mit dieser Syntax ist kein Funktionsaufruf ausgedrückt.

Kurz mal vor dem schreiben, denken!

von Dominik H. (dominikh)


Lesenswert?

Kali schrieb:
> @ Stefan Ernst
>
>>> Deine Codestücke sind schon syntaktisch nicht korrekt und sollten eine
>>> Fehlermeldung geben.
>
>>Doch, sind sie.
>
> Nein. Mit dieser Syntax ist kein Funktionsaufruf ausgedrückt.

Dann ist sie semantisch nicht korrekt. Syntaktisch ist es perfektes C.

> Kurz mal vor dem schreiben, denken!

von Oliver J. (skriptkiddy)


Lesenswert?

Michael schrieb:
> Backlight_an;

Das ist kein Funktionsaufruf. Der Comnpiler sollte dir etwas zu dieser 
Zeile mitgeteilt haben.


Backlight_an(); müsste es heißen


Gruß Skriptkiddy

von Stefan E. (sternst)


Lesenswert?

Kali schrieb:
> Nein. Mit dieser Syntax ist kein Funktionsaufruf ausgedrückt.

Hab ich ja auch gar nicht behauptet.
Es ist aber eine syntaktisch korrekte Zeile (macht nur nicht das 
beabsichtigte), damit ist dein
> syntaktisch nicht korrekt und sollten eine
> Fehlermeldung geben.
falsch.

Kali schrieb:
> Kurz mal vor dem schreiben, denken!

Dito.

von Kali (Gast)


Lesenswert?

@ Stefan Ernst

Ich möchte zunchst diese Formulierung:
"Kurz mal vor dem schreiben, denken!"
mit dem Ausdruck des Bedauerns zurücknehmen.

von Kali (Gast)


Lesenswert?

@ Stefan Ernst

>Hab ich ja auch gar nicht behauptet.

Hast Du wohl. Die Ausgangsfrage war ja, warum eine Funktion nicht 
ausgeführt wird, obwohl der TO annahm, dass er syntaktisch korrekt einen 
Aufruf formuliert hat. Das aber hast er nicht getan.

Der Knackpunkt ist hier, das einer bestimmten Zeichenfolge (Syntax) eine 
bestimmte Bedeutung (in diesem Sinne also Semantik) unterstellt wurde. 
Eine nicht so zu deutende Formulierung ist syntaktisch nicht korrekt, 
denn sie kann nicht wie beabsichtigt gedeutet werden. Sie hat eine 
andere Bedeutung.

von Klaus W. (mfgkw)


Lesenswert?

Kali schrieb:
> @ Stefan Ernst
>
>>> Deine Codestücke sind schon syntaktisch nicht korrekt und sollten eine
>>> Fehlermeldung geben.
>
>>Doch, sind sie.
>
> Nein. Mit dieser Syntax ist kein Funktionsaufruf ausgedrückt.

"Syntaktisch korrekt" und "Funktionsaufruf findet statt" sind zwei
Aussagen, die nicht besonders viel gemeinsam haben.
Es kann durchaus syntaktisch korrekt sein, und trotzdem kein Aufruf 
stattfinden.

Genau das ist hier der Fall.

von Klaus W. (mfgkw)


Lesenswert?

Kali schrieb:
> Der Knackpunkt ist hier, das einer bestimmten Zeichenfolge (Syntax) eine
> bestimmte Bedeutung (in diesem Sinne also Semantik) unterstellt wurde.
> Eine nicht so zu deutende Formulierung ist syntaktisch nicht korrekt,
> denn sie kann nicht wie beabsichtigt gedeutet werden. Sie hat eine
> andere Bedeutung.

?

Eine andere (Be-) Deutung ist doch eben nicht Syntax, sondern Semantik.

von Kali (Gast)


Lesenswert?

@ Klaus Wachtler

>> Nein. Mit dieser Syntax ist kein Funktionsaufruf ausgedrückt.

>"Syntaktisch korrekt" und "Funktionsaufruf findet statt" sind zwei
Aussagen, die nicht besonders viel gemeinsam haben.

Nun, Du hast das vielleicht anders gemeint: Genau genommen, sind auch 
"Funktionsaufruf ausgedrückt" und  "Funktionsaufruf findet statt" zwei 
verschiedene Dinge.

"Syntaktisch korrekt" und "Funktionsaufruf ausgedrückt" haben da schon 
eher etwas gemeinsam.

Ich denke, schon dadurch, dass oben drüber steht "Syntax eines 
C-Programmes", enthält die Beschreibung dieser Syntax eine Bedeutung. 
Dies kann man herunter auf jeden Ausdruck anwenden der für sich genommen 
eine Bedeutung hat. D.h. es gibt Zeichenfolgen, die einen 
Funktionsaufruf ausdrücken und solche die das nicht tun.
Das führt zu dem weiteren Gedanken, das so etwas wie eine "reine Syntax" 
in diesem Zusammenhang nicht existiert.

von Stefan E. (sternst)


Lesenswert?

Kali schrieb:
> Der Knackpunkt ist hier, das einer bestimmten Zeichenfolge (Syntax) eine
> bestimmte Bedeutung (in diesem Sinne also Semantik) unterstellt wurde.
> Eine nicht so zu deutende Formulierung ist syntaktisch nicht korrekt,
> denn sie kann nicht wie beabsichtigt gedeutet werden. Sie hat eine
> andere Bedeutung.

Interessanter Versuch, sich rauszuwinden. ;-)
Jetzt finde ich es aber sehr spannend von dir zu erfahren, wie du da nun 
auch noch das "sollten eine Fehlermeldung geben" mit einbaust.

von Kali (Gast)


Lesenswert?

>Eine andere (Be-) Deutung ist doch eben nicht Syntax, sondern Semantik.

Ich meine, das schon in der Syntax eine Deutung enthalten ist.
Es scheint mir, als wenn allein die Tatsache, das es keine alternative 
Syntax für einen Funktionsaufruf gibt, darauf hindeutet, das man die 
Syntax nicht losgelöst von der Bedeutung betrachten kann. (Insofern ist 
C allerdings ein zwar häufiger aber ein Sonderfall).
Das man als Compilerbauer konstruktiv die Syntaxerkennung von der 
Übersetzung trennt ist nicht so aufzufassen, das dies auch "tatsächlich" 
eine Unabhängigkeit von Syntax und Semantik bedeutet.

von Kali (Gast)


Lesenswert?

@ Stefan Ernst

>Interessanter Versuch, sich rauszuwinden. ;-)
Danke. ;-)


>Jetzt finde ich es aber sehr spannend von dir zu erfahren, wie du da nun
>auch noch das "sollten eine Fehlermeldung geben" mit einbaust.

Da hast Du mich jetzt erwischt. Es ist zwar völlig willkürlich ob man 
solch einen Fall nun als Fehler oder als eine warnwürdige Situation 
auffasst. Auch für letzteres gibt es sicherlich Argumente. Aber auch 
nach meiner Kenntnis würde das bei den Compilern die ich kenne, eine 
Warnung geben.

von Klaus W. (mfgkw)


Lesenswert?

Kali schrieb:
> Ich meine, das schon in der Syntax eine Deutung enthalten ist.

Ob sie enthalten ist oder daneben steht, ist jetzt vielleicht etwas 
philosophisch.
Aber in  jedem Fall heißt der Teil mit der Bedeutung dann "Semantik", 
und nicht mehr  "Syntax".

---

Warum erinnert mich diese Argumentation an meinen Bruder?
Der hat mich bei einer unser diversen Auseinandersetzungen mal ins Bein 
gebissen.
Vor den Eltern mit dem Zahnabdruck konfrontiert, war seine Ausrede: er 
hätte gerade zufällig gegähnt, ich wäre ihm reingelaufen.

von Kali (Gast)


Lesenswert?

@ Klaus Wachtler

>Ob sie enthalten ist oder daneben steht, ist jetzt vielleicht etwas
>philosophisch.

Da stimme ich zu. Ohnehin, ist nach "den Regeln des Handwerks" die Sache 
klar. Ein Parser würde den Code des TO als syntaktisch korrekt erkennen. 
(Das als auch Antwort auf Deinen Vergleich mit Deinem Bruder). Meine 
Einlassung, das es sich syntaktisch nicht um einen Funktionsaufruf 
handelt, ist demnach die nachträgliche Rechtfertigung meiner unklaren 
Formulierung.

Interessant finde ich das aber schon: Diese Trennung von Syntax und 
Semantik ist eigentlich erstmal nur eine rein konstruktive (beim Bau 
eines Compilers). Aber "philosophisch" betrachtet ist diese Trennung 
nicht vorhanden. Mein Beispiel: "... , das es keine alternative
Syntax für einen Funktionsaufruf gibt," scheint mir dafür ein Beleg zu 
sein.
Denn wenn es keine alternative Syntax dafür gibt, so hat dieser Teil der 
Syntax auch eine "Bedeutung".

von Klaus W. (mfgkw)


Lesenswert?

Kali schrieb:
> Aber "philosophisch" betrachtet ist diese Trennung
> nicht vorhanden. Mein Beispiel: "... , das es keine alternative
> Syntax für einen Funktionsaufruf gibt," scheint mir dafür ein Beleg zu
> sein.

Die Syntax hat mit einem Funktionsaufruf nichts zu tun.

Bei der Syntax geht es darum, wie man Zeichen kombinieren kann.
Ob sich daraus ein Sinn ergibt, und wenn ja welcher, hat dann nichts 
mehr mit Syntax zu tun.

Bei C konkret geht es bei Syntax darum, welche Zeichenfolgen zulässig 
sind und wie sie zu Token zusammengefasst werden.

Erst wenn die Token (z.B. ein Name anstatt Zeichenfolgen, oder Klammern 
nicht mehr als Zeichen, sondern als Symbol) auf dem Tisch liegen, wird 
überlegt, ob der Name für eine Variable steht, eine Funktion etc, und ob 
die Klammern zu einem Rechenausdruck gehören, zu einem Cast, zu einer 
Funktionsdeklaration, einem Funktionsaufruf, oder ob sie völliger 
Blödsinn sind.
Das hat aber dann schon nichts mehr mit Syntax zu tun.

Aus http://de.wikipedia.org/wiki/Syntax:
> Unter der Syntax einer formalen Sprache (formale Syntax)
>  – wie etwa Programmiersprachen in der Informatik oder
> Kalküle in der Logik – versteht man ein System von Regeln,
> nach denen erlaubte Konstruktionen bzw. wohlgeformte Ausdrücke
> aus einem grundlegenden Zeichenvorrat (dem Alphabet) gebildet
> werden[6] – wobei von der inhaltlichen Bedeutung der Zeichen>
> abgesehen wird bzw. werden kann.

Ansonsten wäre ja die Semantik arbeitslos.

von Kali (Gast)


Lesenswert?

>> Aber "philosophisch" betrachtet ist diese Trennung
>> nicht vorhanden. Mein Beispiel: "... , das es keine alternative
>> Syntax für einen Funktionsaufruf gibt," scheint mir dafür ein Beleg zu
>> sein.
>Die Syntax hat mit einem Funktionsaufruf nichts zu tun.

>Bei der Syntax geht es darum, wie man Zeichen kombinieren kann.

Dem kann ich zustimmen. Ich wollte nicht sagen, das man aus der 
Darstellung der Syntax alleine auf die Semantik schliessen kann, dass 
also meine Aussage: 'Aber "philosophisch" betrachtet ist diese Trennung 
nicht vorhanden.' einfach nur seine Umkehrung, d.h. dass die Semantik 
aus der Syntax ableitbar ist, bedeuten soll. Das ist sicherlich nicht 
richtig.

Es geht mir darum, das zwischen Syntax und Semantik gewisse 
Wechselbeziehungen bestehen.

>Ob sich daraus ein Sinn ergibt, und wenn ja welcher, hat dann nichts
>mehr mit Syntax zu tun.

Man spezifiziert doch eine Syntax mit einer bestimmten Absicht. Diese 
Absicht bezieht sich auf die Menge der Bedeutungen die man mit 
Ausdrücken die der Syntax entsprechen, mitteilen können will.

Wenn ich z.B. einem Namen, zwei verschiedene Bedeutungen geben will muss 
ich in der Syntax einen Unterschied einbauen, so das seine Bedeutungen 
unterscheidbar sind, was aber nicht gleichbedeutend damit ist, dass die 
Bedeutung inhaltlich aus diesem Unterschied ableitbar ist.

Dein Satz:
>Die Syntax hat mit einem Funktionsaufruf nichts zu tun.
ist so gesehen, nicht vollständig korrekt.
Die Syntax sagt zwar nichts darüber aus, ob ein Name nun als 
Funktionsaufruf oder als ein Zeiger auf die Funktion zu verstehen ist. 
Aber es muss einen Unterschied im Kontext geben, damit man das eine vom 
anderen unterscheiden kann.

Insofern (und in anderer Hinsicht) wirkt sich die Semantik auf die 
Syntax aus.

von Klaus W. (mfgkw)


Lesenswert?

Kali schrieb:
> Dein Satz:
>>Die Syntax hat mit einem Funktionsaufruf nichts zu tun.
> ist so gesehen, nicht vollständig korrekt.

Aber nur so gesehen; richtig gesehen ist mein Satz korrekt :-)

> Die Syntax sagt zwar nichts darüber aus, ob ein Name nun als
> Funktionsaufruf oder als ein Zeiger auf die Funktion zu verstehen ist.
> Aber es muss einen Unterschied im Kontext geben, damit man das eine vom
> anderen unterscheiden kann.

Man könnte eineSprache so konstruieren, daß man einem Namen ansieht, 
wozu er gut ist.
In C ist das aber nicht so.

Natürlich sollte sich aus dem Kontext ergeben, was gemeint ist.
Bei C aber eben nicht aus der Syntax, sondern erst aus der Semantik.

Du kannst dich winden wie du willst, aber die Syntax hat nichts mit der 
Bedeutung der Token zu tun.
Ewiges Leugnen ändert auch nichts an den Tatsachen, und einen C-Compiler 
kannst du auch nicht mit endlosen Debatten zum Übersetzen bewegen.
Magst du nicht einfach mal nachlesen, was Syntax ist? Das würde 
vielleicht die Diskussion etwas erleichtern.

Kali schrieb:
> Es geht mir darum, das zwischen Syntax und Semantik gewisse
> Wechselbeziehungen bestehen.

Warum nicht?
Das ist doch lange kein Grund, die beiden zu vermischen.

von Kali (Gast)


Lesenswert?

>Natürlich sollte sich aus dem Kontext ergeben, was gemeint ist.
>Bei C aber eben nicht aus der Syntax, sondern erst aus der Semantik.

Das habe ich auch garnicht behauptet.
Ich schrieb z.B.
>Die Syntax sagt zwar nichts darüber aus, ob ein Name nun als
>Funktionsaufruf oder als ein Zeiger auf die Funktion zu verstehen ist.

>Ewiges Leugnen ändert auch nichts an den Tatsachen, und einen C-Compiler
>kannst du auch nicht mit endlosen Debatten zum Übersetzen bewegen.
>Magst du nicht einfach mal nachlesen, was Syntax ist?

Hm. Wieso leugnen? Was leugnen? Keine Ahnung was Du da in den falschen 
Hals bekommen hast. Schade.

von Kali (Gast)


Lesenswert?

Seltsam. Was soll auf einmal dieser Tonfall?

Abgesehen davon:
>Natürlich sollte sich aus dem Kontext ergeben, was gemeint ist.
ist der Kontext Teil der Syntax.

Na gut. Wirklich schade.

von Thomas E. (thomase)


Lesenswert?

Michael schrieb:
> Ja das wars. Danke
Es funktioniert zwar, aber du bist auf dem besten Weg, dir einen 
grauenhaften Programmierstil anzugewöhnen.

Deswegen:

Kali schrieb:
> Bitte lies ein C-Buch.

Und zwar von Anfang an. Wenn das Kapitel mit den Pointern kommt, kannst 
du es erstmal beiseite legen, aber bis dahin arbeite das gewissenhaft 
durch.

Michael schrieb:
> Unterprogramm

In C gibt es keine Unterprogramme!

Sowas macht man nicht:

Michael schrieb:
> void Backlight_an(void)     { PORTD |=  (1<<PD4); }

Dafür nimmt man Makros:

Martin schrieb:
> Beispielsweise#define Backlight_an    PORTD|=_BV(PD4)
Wobei diese Art schon etwas obsolet ist.

#define Backlight_an    PORTD |=  (1<<PD4)
ist die modernere Schreibweise.

Wenn man das schon in eine Funktion packen will, dann macht man das mit 
EINER und nicht mit drei Funktionen:

void Backlight(char function)
{
   switch (function)
   {
     case 0:
      PORTD &= ~(1<<PD4);
     break;

     case 1:
      PORTD |=  (1<<PD4);
     break;

     case 2:
      PORTD ^=  (1<<PD4);
     break;
   }
}

Die drei Zustände kannst du dann noch "griffig" definieren

#define OFF 0
#define ON 1
#define TOGGLE 2

Und dann: Backlight(ON);


mfg.

von Noah (Gast)


Lesenswert?

Thomas Eckmann schrieb:
> Dafür nimmt man Makros

Oder man markiert die Funktion als inline...

von Anno (Gast)


Lesenswert?

Wenn es nicht so albern und langweilig wäre, dann würd ich Popkorn 
holen. Aber... ne.

von Dominik H. (dominikh)


Lesenswert?

>> Beispielsweise#define Backlight_an    PORTD|=_BV(PD4)
>Wobei diese Art schon etwas obsolet ist.

>#define Backlight_an    PORTD |=  (1<<PD4)
>ist die modernere Schreibweise.

Da soll mir aber einer erklären, was an letzterer Schreibweise 
"moderner" ist. _BV ist ein Makro, welches man wunderbar einsetzen kann 
und laut offizieller Stelle (avr-libc Dokumentation) auch nicht 
"obsolet" ist...


> Oder man markiert die Funktion als inline...
Was aber nur genau so wie das Makro funktioniert, wenn man zusätzlich 
noch das passende (vom Compiler abhängige) Attribut hinzugibt, ansonsten 
ist inline nämlich nur ein Vorschlag an den Compiler. Ob er es 
letztenendes auch macht, ist seine Sache.

von Thomas E. (thomase)


Lesenswert?

Dominik Honnef schrieb:
> Da soll mir aber einer erklären, was an letzterer Schreibweise
> "moderner" ist. _BV ist ein Makro, welches man wunderbar einsetzen kann
> und laut offizieller Stelle (avr-libc Dokumentation) auch nicht
> "obsolet" ist...

#define _BV(bit) (1 << (bit))

Mit obsolet und modern lag ich vielleicht etwas daneben.

Nichtdestotrotz wird in den Datenblättern die (1 << xx) -Schreibweise 
verwendet. Genauso wie im AVR-GCC-Tutorial.

Ob man es nun so macht oder das _BV -Makro verwendet ist natürlich auch 
Geschmackssache und jedem selbst überlassen. Ich hatte jetzt nicht vor, 
jemandem auf den Schlips zu treten.

Allerdings wird sich ein Anfänger beim Anblick desselben nur die Haare 
raufen, weil er überhaupt nicht weiß, was das soll.

(1 << xx) begegnet einem dagegen andauernd.

Aber das muß man jetzt nicht in den folgenden 27 Posts durchdiskutieren.

mfg.

von Dominik H. (dominikh)


Lesenswert?

Dann stimme ich einfach nur zu :)

von Michael (Gast)


Lesenswert?

Thomas Eckmann schrieb:
> Wenn man das schon in eine Funktion packen will, dann macht man das mit
> EINER und nicht mit drei Funktionen:
>
> void Backlight(char function)
> {
>    switch (function)
>    {
>      case 0:
>       PORTD &= ~(1<<PD4);
>      break;
>
>      [...]
>    }
> }
>
> Die drei Zustände kannst du dann noch "griffig" definieren
>
> #define OFF 0
> #define ON 1
> #define TOGGLE 2
>
> Und dann: Backlight(ON);

Danke für den Hinweis. Ich nehme das auf und werde es künftig so 
umsetzen.
Gruß
Michael

von Klaus W. (mfgkw)


Lesenswert?

Bevor du es zu sehr verinnerlichst: statt der #define könnte man auch 
eine enum nehmen.
Viele Menschen (so auch ich) würden das bevorzugen.

Je weniger Makros, umso besser.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.