Forum: Compiler & IDEs GCC ignoriert Zuweisung in struct


von Andreas G. (Gast)


Lesenswert?

Hallo!

Ich schaffs nicht, in einer schleife nem Struct einen Wert zuzuweisen.

Der struct ist global definiert:

struct {
  u08 high:8;
  u08 low:8;
} servo1;

Beim Init wird der Timer0 gestartet, welcher beim Überlauf die
Compare-Werte des Timer1 setzt:
OCR1H = servo1.high;
OCR1L = servo1.low;

Die Variablen werden vorher in der Main-Funktion mit:
servo1.high = 16000/256;
servo1.low  = 16000%256;
gesetzt.

Soweit funktionierts noch. (Sowohl in AVRStudio als auch in Hardware)
Im Hauptprogramm (main()) befindet sich jetzt folgende Schleife:
while (1)
{
  if (bit_is_clear(PINC,0))
  {
    sbi(PORTC,2);
    servo1.high = 46;
    servo1.low  = 224;
  }
  else
  {
    cbi(PORTC,2);
    servo1.high = 31;
    servo1.low  = 64;
  }
}

Mit dieser Schleife kann ich bei drücken auf den Schalter an PINC,0 die
LED an PORTC,2 ausschalten. Nur leider wird der Wert in meinem struct
nicht verändert. Ein Blick in den ASM-Code zeigt:

SBIC    0x13,0           Skip if bit in I/O register cleared
RJMP    PC+0x0003
SBI     0x15,2           Entspricht sbi(PORTC,2);
RJMP    PC-0x0003
CBI     0x15,2           Entspricht cbi(PORTC,2);
RJMP    PC-0x0005

d.h. gcc ignoriert einfach meine Zuweisung.
Jetzt bin ich etwas ratlos. Ich hoffe, es kann mir von euch jemand
helfen.

Gruss, Andreas

von Daniel Jelkmann (Gast)


Lesenswert?

Hi Andreas,

vermutlich hat der GCC zuviel wegoptimiert. Werden die Werte in der
Structure servo1 irgendwann nochmal verwendet?
Versuch mal ein volatile vor die struct zu schreiben, also:

volatile struct {
  u08 high:8;
  u08 low:8;
} servo1;

Vielleicht hilft das. Ansonsten poste mal bitte etwas mehr Code, das
macht die Fehlersuche einfacher.

Bye
  Daniel Jelkmann

von Mike (Gast)


Lesenswert?

Nur am Rande:
Verwende in Zukunft nicht mehr sbi (...) und cbi (...), diese Ausdrücke
sind veraltet.
OCR1 kannst du direkte ansprechen, warum der Umweg über Low- und
High-Byte?

von Stefan Kleinwort (Gast)


Lesenswert?

Daniel hat Recht.
Dein Code wurde wegoptimiert. War ja auch völlig sinnlos ;-)
Alternativ zu volatile kannst Du gcc nach den Zuweisungen noch etwas
mit den Werten arbeiten lassen. Denn nur wenn er den Eindruck hat,
wirklich gebraucht zu werden, arbeitet er auch klaglos. Also z.B.
folgendes anhängen:

  if ((servo1.low + servo1.high) > 200){
    beschaeftigungstherapie();
  }


Gruß, Stefan

von OldBug (Gast)


Lesenswert?

Btw:

volatile struct {
  u08 high:8;
  u08 low:8;
} servo1;

Wo ist da der Sinn? Das ist keine "struct" in dem Sinne, sondern ein
Bitfeld. Richtiger wäre da wohl eher:

volatile struct {
  u08 high;
  u08 low;
} servo1;

...IMHO...

von Andreas G. (Gast)


Lesenswert?

Danke!

Wurde tatsächlich wegoptimiert. volatile hat geholfen. Wundert mich nur
etwas, denn ich hab im Makefile extra die optimierung auf 0 gestellt.

@Mike: was wird statt sbi() und cbi() verwendet? Das konstrukt aus dem
Wiki (PORTA &= ~(1<<MEINBIT);) find ich ziemlich unmerkbar, und sbi()
wird doch schön in Assembler übersetzt.

@OldBug: ...richtig!

von OldBug (Gast)


Lesenswert?

Naja, unmerkbar oder nicht: es ist schlicht und einfach Standard-C ;-)
Es gibt auf der Doku-Seite der avr-libc eine Seite mit abgekündigten
funktionen, unter anderen sind da auch sbi und cbi vermerkt.
Also besser jetzt schon mal an diese Schreibweise gewöhnen, in der
nächsten avr-libc release wirds wohl laut Jörg Wunsch nicht mehr
vorhanden sein...

von Dirk (Gast)


Lesenswert?

Hi,

du kannst dir ja definitonen machen fuer sbi und cbi.

Mfg

Dirk

von Jörg Wunsch (Gast)


Lesenswert?

Es ist aus den aktuellen Quellen bereits raus.  U. a.  wegen solcher
Mißverständnisse:

> "und sbi() wird doch schön in Assembler übersetzt."

Wurden sie nämlicht mitnichten zwangsläufig, da sie seit mehreren
Jahren bereits weiter nichts als Aliase für die Standard-C-
Bitmanipulationen waren.  D.h. insbesondere, daß mit -O0 keine
Optimierung in SBI/CBI automatisch stattfand.

Mit -O>=1 erfolgt die Umsetzung, sofern die übrigen Randbedingungen
eine solche gestatten, d.h. nur ein Bit wird gesetzt oder gelöscht,
die Bitnummer ist zur Compilezeit bekannt/konstant, und das
IO-Register liegt im erreichbaren Bereich für SBI/CBI.

von OsiriS (Gast)


Lesenswert?

Hier mal mein Problem, vielleicht kann mir ja ein alter C-Hase sagen,
was ich falsch mache:

struct {
  char     *MenuKey;
  unsigned char  MenuButton;
  } Menu_1[20]  = {
    "\t\t +++ Mainmenu +++\n\n", 0,
    "\t\t Menupunkt1\n\n", '1',
    "\t\t Menupunkt2\n\n", '2',
    "\t\t Menupunkt3\n\n", '3',
    "\t\t Menupunkt4\n\n", '4',
    "\t\t Exit\n\n"},      '5',
  },
  Menu_2_1[20] = {
    "\t\t +++ Submenu 1 +++\n\n", 0,
    "\t\t Unterpunkt_1_1\n\n", '1',
    "\t\t Unterpunkt_1_2\n\n", '2',
    "\t\t Unterpunkt_1_3\n\n", '3',
    "\t\t Unterpunkt_1_4\n\n", '4',
    "\t\t Unterpunkt_1_5\n\n", '5',
    "\t\t Unterpunkt_1_6\n\n", '6',
    "\t\t Unterpunkt_1_7\n\n", '7',
  };

Unter Borland C geht das wunderbar, bei GCC krieg ich nur
Fehlermeldungen...
habs auch schon mit geschweiften Klammern um die einzelnen Einträge
versucht...dann krieg ich "menu.inc:26: warning: initialization makes
pointer from integer without a cast" als Fehler
Hab in der Doku von der Lib nix gefunden.
Hat da jemand noch ne andere Doku?
Greetz  OsiriS

von Jörg Wunsch (Gast)


Lesenswert?

Das Schachteln der Klammern ist laut Standard notwendig.

Der `pointer from integer' ist wohl die herumlungernde '5' dort
(zwischen dem Initializer von Menu_1[] und Menu_2_1[]).

Aber sei gewarnt: der Krempel geht komplett in den RAM.  In der
fertigen Lösung wirst Du das wohl so nicht wollen.  Außerdem
verplemperst Du Platz, da Du den Arrays eine explizite Größe verpasst,
diese aber nicht ausnutzt.

Bitte für neue Fragen auch einen neuen Thread aufmachen, das hat mit
dem ursprünglichen Thread ja absolut nichts mehr gemein.

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.