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


von Wühlhase (Gast)


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?
1
typedef struct{
2
  int time_dark;
3
  int time_bright;
4
  struct GPIO_InitTypeDef *Port;
5
  uint16_t GPIO_Pin;
6
}light;
7
8
const LIGHTSCOUNT = 1;
9
10
struct light lights[] = {
11
  {10, 25, LD2_GPIO_Port, LD2_Pin}
12
};
13
14
unsigned int LightsTick;
15
16
void controlLights(){
17
  int i = 0;
18
  while(i >= LIGHTSCOUNT){
19
    if(LightsTick % (lights[i].time_dark + lights[i].time_bright) == 0){
20
      HAL_GPIO_WritePin(lights[i].Port, lights[i].GPIO_Pin, GPIO_PIN_RESET);
21
      continue;
22
    }
23
    if(LightsTick % (lights[i].time_dark + lights[i].time_bright) == lights[i].time_dark){
24
      HAL_GPIO_WritePin(lights[i].Port, lights[i].GPIO_Pin, GPIO_PIN_SET);
25
    }
26
  }
27
}
28
29
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
30
  //HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
31
  LightsTick++;
32
  controlLights();
33
}

von Stefan E. (sternst)


Lesenswert?

1
struct light lights[] = {
->
1
light lights[] = {

von René H. (Gast)


Lesenswert?

Gibt es auch auch ein Bienchen wenn es richtig ist?

Grüsse,
René

von Wühlhase (Gast)


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.

von derjaeger (Gast)


Lesenswert?

1
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 ...

von Teddy (Gast)


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"

von Daniel A. (daniel-a)


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?

von W.S. (Gast)


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:
1
#define evLampe1  1
2
#define evLampe2  2
3
..usw.
4
5
#define to_off  (1<<16)
6
7
struct MyElement
8
{ long Zyklus;
9
  long OffDelay;
10
  long aEvent;
11
}
12
13
/* für 1 ms Systemzeitintervall und 100 Lampen */
14
const struct MyElement MeineListe[100] =
15
{ /* Zyklus   */  10000,
16
  /* Off nach */   3000,
17
  /* event    */  Lampe1,
18
... usw.
19
}
20
21
/* Liste der letzten Aktualisier-Zeiten für 100 Lampen */
22
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.

von W.S. (Gast)


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.

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.