Forum: Compiler & IDEs Struct ins EEPROM schreiben


von Sebastian B. (sebastian86)


Lesenswert?

Guten Tag zusammen,

ich habe ein Problem mit dem Verständnis der Funktion 
"eeprom_write_block"

Folgendes - ich möchte eine Struktur welche 14bit groß ist (2 Byte) ins 
EEPROM schreiben in dieser Struktur stehen Zustandsmeldungen.

Einzelne Bytes ins EEPROM schreiben hat bei mir funktioniert, aber ich 
glaube ich habe den Syntax noch nicht ganz verstanden um einen ganzen 
Block (struct) zu schreiben:

So sieht mein struct aus.
1
volatile uint16_t   adresse = 0x05;
2
3
4
struct {
5
  unsigned V_1:1; // 
6
  unsigned V_2:1; // 
7
  unsigned V_3:1; // 
8
  unsigned P_1:1; // 
9
  unsigned P_2:1; // 
10
  unsigned P_3:1; // 
11
  unsigned P_4:1; // 
12
  unsigned P_5:1; //
13
  unsigned M_1:1; 
14
  unsigned M_2:1;
15
  unsigned M_3:1;
16
  unsigned KW:1;
17
  unsigned KF:1;
18
  unsigned Temp_Diff:1;     
19
} state;

Und im Programm kommt dann der Aufruf:
1
cli();
2
eeprom_write_block(state, adresse, sizeof(state));
3
sei();
Dort bekomme ich dann eine Fehler meldung und eine Warnung:
Error  1  incompatible type for argument 1 of 'eeprom_write_block'
Warning  2  passing argument 2 of 'eeprom_write_block' makes pointer 
from integer without a cast


Im Tutorial für den die Fuktion sieht es auch so aus als wenn nur ein 
Array ins EEPROM geschrieben wird.

Kann mich da vieleicht jemand mal aufklären?

Das wäre super.

Vielen Dank

von egal (Gast)


Lesenswert?

cli();
eeprom_write_block(&state, adresse, sizeof(state));
sei();             ^^

von Coder (Gast)


Lesenswert?

Was Du falsch gemacht hast, sagen Dir die Fehlermeldungen? Und wenn 
"state" eine Variable ist, müsstest Du doch zumindest diese als "&state" 
übergeben.

von Adib T. (adib_t)


Lesenswert?

ich glaube nicht, dass man hier die Interrupts verbieten muss. Hat das 
bei dir einen bestimmten Grund?

Adib.

von Rolf M. (rmagnus)


Lesenswert?

Sebastian B. schrieb:
> volatile uint16_t   adresse = 0x05;
> Und im Programm kommt dann der Aufruf:cli();
> eeprom_write_block(state, adresse, sizeof(state));
> sei();
> Dort bekomme ich dann eine Fehler meldung und eine Warnung:

> Error  1  incompatible type for argument 1 of 'eeprom_write_block'

Das wurde ja schon genannt.

> Warning  2  passing argument 2 of 'eeprom_write_block' makes pointer
> from integer without a cast

Steht doch dran, was das Problem ist. eeprom_write_block() erwartet 
einen Zeiger, aber du übergibst
1
volatile uint16_t   adresse = 0x05;
einen Integer.

Übrigens:  Warum ist der denn volatile? Änderst du die Adresse in einer 
ISR? Das würde dann auch das cli()/sei() erklären.

von Vlad T. (vlad_tepesch)


Lesenswert?

Sebastian B. schrieb:
> So sieht mein struct aus.
> volatile uint16_t   adresse = 0x05;

Sebastian B. schrieb:
> cli();
> eeprom_write_block(state, adresse, sizeof(state));
> sei();

warum sich alle bei eeprom immer so auf den Kopf stellen müssen und 
alles künstlich verkomplizieren?!
https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#EEPROM

von Sebastian B. (sebastian86)


Lesenswert?

Das mit der Struktur und dem EEPROM hat soweit funktioniert nur habe ich 
nun irgendwie probleme mit der Struktur.

Muss man die irgendwie anders handeln als normale variablen ?

Ich setzte am Anfang einfach zum test in meiner Struktur "state" den 
eintrag V_2 auf "0" und ich sezte den Ausgang für V2 auf High.

so nun teste ich ja mit != auf ungleichheit der beiden. und stelle fest 
das die beiden ungleich sind. in der simulation wird dann state.V_2 auf 
1 gesetzt in der ersten if abfrage.

Nun sollten ja in der zweiten Abfrage beide 1 sein und die abfrage 
sollte übersprungen werden...
Dies ist aber nicht der Fall. Muss man die Struktur variablen irgendwie 
anders behandeln?

1
state.V_2 = 0;
2
PORT_OUT |= (1<<V2);
3
4
5
if ( ( (state.V_2) != (PORT_OUT & (1<<V2) ) ) )
6
{
7
  bStatus_geandert = TRUE;
8
        state.V_2 = 1;
9
}
10
11
if ( ( (state.V_2) != (PORT_OUT & (1<<V2) ) ) )
12
{
13
  bStatus_geandert = TRUE;
14
  state.V_2 = 1;
15
}

von Sebastian B. (sebastian86)


Lesenswert?

so und wenn ich state und V2 auf 1 setzte und mit == abfrage wird das if 
auch übersprungen. nun bin ich ratlos?!
was mache ich falsch ?



state.V_2 = 1;
PORT_OUT |= (1<<V2);




if ( ( (state.V_2) == (PORT_OUT & (1<<V2) ) ) )
{
bStatus_geandert = TRUE;
}

von Karl H. (kbuchegg)


Lesenswert?

Sebastian B. schrieb:


> Dies ist aber nicht der Fall. Muss man die Struktur variablen irgendwie
> anders behandeln?

Nein. Aber du solltest dir mal überlegen, was du bei deinem != 
tatsächlich vergleichst. Links Seite - Rechte Seite. Welche Werte 
entstehen da jeweils.

Hinweis: Das Ergebnis von (PORT_OUT & (1<<V2) ) ist NICHT 0 oder 1, 
sondern 0 oder (1<<V2).
Dein Bit in der Struktur ist aber definitiv entweder 0 oder 1.
Wenn beide 0 sind, passt das alles. Aber der '1' Fall ist nicht in 
Ordnung. Denn wenn V2 bspweise der Pin 3 ist, dann bedeutet der Ausdruck 
(PORT_OUT & (1<<V2) ), dass da bei der Abfrage numerisch 8 rauskommt. 
Und 1 ist nun mal nicht gleich 8.

von Sebastian B. (sebastian86)


Lesenswert?

mhm Wie heisst denn dann mein Zauberzeichen damit ich auf ungleichnis 
prüfen kann ?ich müsste mein PORT 1<<V2 nur irgendwie auf TRUE bzw FALSE 
umwandeln müssen.

Dat ist doch bestimmt auch irgendwas ganz simples
Finde da gerade nur nichts in meinem Buch

von Karl H. (kbuchegg)


Lesenswert?

Sebastian B. schrieb:

> Dat ist doch bestimmt auch irgendwas ganz simples

Du kannst natürlich auch das Ergebnis von PORT_OUT & (1<<V2) auf 
explizit 0 oder 1 forcieren.

   !!( PORT_OUT & (1<<V2) )

toll ist es aber nicht.

Du kannst auch den linken Teilausdruck so zurechtschieben, dass das 1 
Bit an der Stelle V2 zu liegen kommt und so praktisch den linken 
Teilausdruck an den Wertebereich des rechten anpassen

  if ( ( (state.V_2<<V2) != (PORT_OUT & (1<<V2) ) ) )

finde ich immer noch nicht wirklich prickelnd.


An dieser Stelle würde ich vorschlagen, tatsächlich explizit zu sein.
Was willst du denn wissen?

Du willst wissen ob
entweder beide 0 sind
oder beide ungleich 0 sind

und genau so würde ich das auch schreiben.

  if ( (  state.V_2 &&   PORT_OUT & (1<<V2) ) ||   // beide ungleich 0?
       ( !state.V_2 && !( PORT_OUT & (1<<V2) ) ) )  // beide gleich 0?

wenn dir das zu geschwätzig ist, dann mach dir eine Funktion dafür
1
uint8_t EqualBitValues( uint8_t Bit1, uint8_t Bit2 )
2
{
3
  return ( Bit1 && Bit2 ) || ( !Bit1 && !Bit2 );
4
}
5
6
  ....
7
  if( EqualBitValues( state.V_2, PORT_OUT & (1<<V2) ) )
8
    ....

Das hat dann auch den Vorteil, dass es die doppelte Auswertung des Ports 
vermeidet. Manchmal muss man eben seine 'Werkzeuge' selber bauen, wenn 
einem die Sprache nicht das gibt, was man braucht.

von Krapao (Gast)


Lesenswert?

Der einfache Ersatz des != in dem Beispiel
> if ( ( (state.V_2) != (PORT_OUT & (1<<V2) ) ) )
ist das logische XOR (
http://de.wikipedia.org/wiki/XOR-Verkn%C3%BCpfung).

Bzw. das logische XNOR (log. XOR gefolgt von log. NOT) in diesem 
Ausdruck
> if ( ( (state.V_2) == (PORT_OUT & (1<<V2) ) ) )

Mögliche Umsetzung (nicht optimal und fehlerträchtig, weil x und y 
mehrfach ausgewertet werden!)
1
#include <stdio.h>
2
3
#define XOR(x,y) ((!(x) && (y) ) || ((x) && !(y)))
4
#define XNOR(x,y) (!XOR(x,y))
5
6
int main(void)
7
{
8
  int x,y;
9
  printf("x     y     XOR     XNOR\n");
10
  printf("========================\n");
11
  for (x=0; x<2; x++)
12
    for (y=0; y<2; y++)
13
      printf("%d     %d     %d       %d\n", x,y,XOR(x,y),XNOR(x,y));
14
}

Ausgabe (http://de.wikipedia.org/wiki/Wahrheitstabelle)
1
x     y     XOR     XNOR
2
========================
3
0     0     0       1
4
0     1     1       0
5
1     0     1       0
6
1     1     0       1

von Rolf Magnus (Gast)


Lesenswert?

Krapao schrieb:
> Der einfache Ersatz des != in dem Beispiel
>> if ( ( (state.V_2) != (PORT_OUT & (1<<V2) ) ) )
> ist das logische XOR

Man fragt sich nur warum C das nicht hat. Alle üblichen booleschen 
Verküpfungen gibt es sowohl bitweise als auch als boolesche Variante. 
Nur das xor gibt es ausschließlich bitweise.

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.