mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik C - Struct macht mich wahnsinnig


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Wühlhase (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Guten Abend allerseits.

Folgendes: Ich möchte mit einem Nucleoboard eine primitive 
Lichtsteuerung bauen. In einer Strucktur wollte ich also die gewünschten 
Zeiten, wie lange eine LED leuchten und nicht leuchten soll sowie die 
jeweiligen Port und Pin.

Dann für jede LED eine Struktur in ein Array gestopft und regelmäßig 
einen Ticker inkrementieren, das Array durchlaufen und die Pins 
umschalten.

Jetzt beschwert sich Eclipse den ganzen Tag über meine Struktur. Aktuell 
setzt es vier Käfer neben die If-Anweisung und jeweils die Zeile 
darunter mit der Meldung "Field could not be resolved".

Kann mir irgendwer auf die Sprünge helfen?
typedef struct{
  int time_dark;
  int time_bright;
  struct GPIO_InitTypeDef *Port;
  uint16_t GPIO_Pin;
}light;

const LIGHTSCOUNT = 1;

struct light lights[] = {
  {10, 25, LD2_GPIO_Port, LD2_Pin}
};

unsigned int LightsTick;

void controlLights(){
  int i = 0;
  while(i >= LIGHTSCOUNT){
    if(LightsTick % (lights[i].time_dark + lights[i].time_bright) == 0){
      HAL_GPIO_WritePin(lights[i].Port, lights[i].GPIO_Pin, GPIO_PIN_RESET);
      continue;
    }
    if(LightsTick % (lights[i].time_dark + lights[i].time_bright) == lights[i].time_dark){
      HAL_GPIO_WritePin(lights[i].Port, lights[i].GPIO_Pin, GPIO_PIN_SET);
    }
  }
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
  //HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
  LightsTick++;
  controlLights();
}

Autor: Stefan E. (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
struct light lights[] = {
->
light lights[] = {

Autor: René H. (Firma: Herr) (hb9frh)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Gibt es auch auch ein Bienchen wenn es richtig ist?

Grüsse,
René

Autor: Wühlhase (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke...ja, das hat gepaßt. Danke. Dafür gibts ein

  .--.               .--.
 /    `.   o   o   .'    \
 \      \   \          /
 /\_     \ .-"-. /     _/\
(         V ^ ^ V         )
 \_      _| 9_9 |_      _/
  `.    //\__o__/\\    .'
    `._//\=======/\\_.'
     _ /\=====/\ \_\
       _// \===/ \\_
      /_/_//`='\\_\_\
        _     \_\


Das Programm ist noch nicht fehlerfrei (ich hab z.B. grad festgestellt 
daß ich i nicht inkrementiere), aber ich denk das wird was für morgen.

Autor: derjaeger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
LightsTick % (lights[i].time_dark + lights[i].time_bright

Lager mal diese Berechnung in eine eigene Variable aus. Dann ist erstmal 
der Code lesbarer und du musst diese Berechnung nicht 2 mal pro 
Schleifendurchgang machen ...

Autor: Teddy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan E. schrieb:
> struct light lights[] = {->light lights[] = {

Was ist eigentlich der Unterschied zwischen:
typedef struct = {}"name";  und

struct "name" = {}; ?


Mir ist dann bei der Deklaration dann aufgefallen, dass die zweite 
Variante
struct "name" "variable"
will,
während man bei typedef den "struct" weglassen kann,  sprich
"name" "variable"

Autor: Daniel A. (daniel-a)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wühlhase schrieb:
> LightsTick % (lights[i].time_dark + lights[i].time_bright)

Wenn 1ull<<sizeof(LightsTick) nicht durch time_dark + time_bright 
teilbar ist, also time_dark + time_bright keine zweierpotenz ist, kommt 
es beim overflow von LightsTick zu einer zu kurzen Wartezeit. Ausserdem, 
ist garantiert dass du keinen LightsTick verpasst?

Autor: W.S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wühlhase schrieb:
> Kann mir irgendwer auf die Sprünge helfen?
> typedef struct{
>   int time_dark;
>   int time_bright;
>   struct GPIO_InitTypeDef *Port;
>   uint16_t GPIO_Pin;
> }light;

Ob dir jemand wirklich auf die Sprünge helfen kann? Hmm..

Also, du gehst es von der falschen Seite an, so daß du selbst in höheren 
Ebenen immer wieder dich mit Lowlevel-Angelegenheiten herumschlagen 
mußt. Zum Schluß landet das Gefummel mit *Port vermutlich sogar in 
main().

Mein Rat: trenne dein Zeitschema komplett von den tatsächlichen 
Aktionen.

Ich skizziere das mal so aus dem Handgelenk:

1. bau dir eine Systemuhr. Intervall im Bereich 1..10 ms, beachte dabei 
das Rücksetzen aller Soft-Timer um Mitternacht.
2. rufe aus der Systemuhr deinen Zeitschema-Handler auf. Laß diesen 
passende Events generieren, die dann in der Grundschleife behandelt 
werden
3. bau dir für jede Lampe einen separaten Handler, jaja der wird kurz 
und knapp sein, mach ihn dennoch separat von allem Anderen.

So, nun zu den Strukturen:
#define evLampe1  1
#define evLampe2  2
..usw.

#define to_off  (1<<16)

struct MyElement
{ long Zyklus;
  long OffDelay;
  long aEvent;
}

/* für 1 ms Systemzeitintervall und 100 Lampen */
const struct MyElement MeineListe[100] =
{ /* Zyklus   */  10000,
  /* Off nach */   3000,
  /* event    */  Lampe1,
... usw.
}

/* Liste der letzten Aktualisier-Zeiten für 100 Lampen */
long Zuletzt[100];


Dein Zeitschema-Handler ( z.B. void LampenBonze(void) ) macht dann 
sinngemäß folgendes:

Für jede Lampe do:
( if aktuelle Zeit >= Zuletzt+Zyklus
  then (Zuletzt = Zuletzt+Zyklus; Add_Event(evLampeN)
  else ( if aktuelle Zeit >= Zuletzt + OffDelay
         then Add_Event(evLampeN or to_off) )
)

Und in der Grundschleife nimmst du dir in aller Ruhe die eventuell in 
der Event-Liste stehenden Events vor und rufst die jeweiligen Handler 
auf. Das hat den Vorteil, daß du nicht angewiesen bist darauf, WIE denn 
nun deine LampeX an oder ausgeschaltet werden muß - kann ja auch was 
anderes als ein Portbein sein. Kann übrigens auch was anderes als ne 
Lampe sein. Das ist Sache des Lowlevel-Handlers und darum solltest du 
dich in main() nicht kümmern müssen.

So, das war aus dem Handgelenk, wie es gemeint ist, siehst du ja.

W.S.

Autor: W.S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Teddy schrieb:
> Was ist eigentlich der Unterschied zwischen:
> typedef struct = {}"name";  und
>
> struct "name" = {}; ?

Die eigentliche Struct-Deklaration ist
struct name { sachlicher Inhalt };

Das Wort "typedef" dient dazu, einem bereits vorhandenen Typ einen 
zweiten Namen zu geben, ohne daß man die rein lexikalische Ersetzung per 
#define benutzen muß.
Also:
typedef name  neuer_name;

Das ist alles. Man kann leider auch namenlose Typen dort verwenden, 
was von manchen gern gemacht wird,
also:
typedef struct_definition_ohne_namen  neuer_name;

Ich finde dies allerdings ausgesprochen unästhetisch. Es hat auch den 
Nachteil, daß man damit gern auf die Fresse fliegt.
funktionierendes Beispiel:

struct kringel =
{ kringel* davor;
  kringel* danach;
  .. sonstiger Inhalt
};

Und wenn du das jetzt mit typedef und namenlosem struct probierst, 
gibt's ne Bauchlandung, weil namenlos* davor usw. eben nicht geht.


W.S.

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.