Hallo,
Ich steh da irgendwie auf dem Schlauch.
Im folgenden Code, habe da mal die relevanten Teile zusammengeschnitten,
habe ich das Problem dass die 2 letzten Anweisungen einfach nicht
klappen wollen, irgendwie funktioniert es nicht das struct das ich im
void * data hinterlegt habe anzusprechen.
Wäre schön wenn mir da jemand auf die Sprünge helfen könnte.
Nik
devices.h
1
typedefstructSensors_t
2
{
3
uint8_tid;
4
uint16_tlastUpdate;
5
void*data;
6
}Sensors;
7
8
typedefstructLeistung_t
9
{
10
intvcc;
11
longintID;
12
intWatt;
13
longintkWh;
14
longintkWhd;
15
}Leistung;
16
17
typedefstructKlima_t
18
{
19
intvcc;
20
longintID;
21
intGrad;
22
intRel;
23
}Klima;
main.c
1
...
2
staticuint8_tleistung_pt=0;// Zeiger auf das letzte element im array ‘leistung’
3
4
Sensorensensors[20];// Array von Allen Sensoren
5
Leistungleistung[4];// Array von Leisungssensoren
6
Klimaklima[6];// Array von Klimasensoren
7
8
int8_s=get_sensor_index((uint8_t)id,sensors);// Hole den index auf sensors[?] anhand der id
9
10
sensors[s].data=&leistung[leistung_pt];// Weise dem void * data die Addr von leistung[x] zu
11
12
Leistung*data=(Leistung*)sensors[s].data;// Initialisiere den ‘Arbeistpointer’
Verrätst du uns auch noch, was man sich unter
'funktioniert irgendwie nicht'
vorstellen soll.
Denn eines muss dir klar sein: Nur weil du den Compiler zwingst, die
Schnauze zu halten, indem du den Pointer niedercastest, wird nicht
magisch aus einer Klimastruktur, deren Adresse du in data abgelegt hast,
eine Leistung Datenstruktur.
Ich würde jedem empfehlen um void Pointer einen Bogen zu machen.
Meistens ist das keine gute Lösung.
In deiner Sensors Datestruktur brauchst du sowieso noch einen Member,
der dir sagt, ob du es jetzt mit einem Leistungssensor oder einem
Klimasensor zu tun hast. So etwas wie ein Typflag
1
typedefstructLeistung_t
2
{
3
intvcc;
4
longintID;
5
intWatt;
6
longintkWh;
7
longintkWhd;
8
}Leistung;
9
10
typedefstructKlima_t
11
{
12
intvcc;
13
longintID;
14
intGrad;
15
intRel;
16
}Klima;
17
18
typedefstructSensors_t
19
{
20
uint8_tid;
21
uint16_tlastUpdate;
22
23
uint8_tsensorTyp;
24
union
25
{
26
Leistung*pLeist;
27
Klima*pKlima;
28
}data;
29
}Sensors;
die beiden Pointer liegen durch die union übereinander. Entweder ist der
Pointer data.pLeist gültig, oder der Pointer data.pKlima ist gültig. Der
Member sensorTyp (den du natürlich beim Aufbau der Daten korrekt
besetzen musst), verrät dir dann, welcher der richtige ist, so dass du
zb alle Sensoren im Array in einer einzigen Schleife abhandeln kannst.
1
#define SENSOR_UNKNOWN 0
2
#define SENSOR_KLIMA 1
3
#define SENSOR_LEISTUNG 2
4
5
...
6
nrSensors=0;
7
8
...
9
10
sensors[nrSensors].senssorTyp=SENSOR_KLIMA;
11
sensors[nrSensors].data.pKlima=klima[0];
12
nrSensors++;
13
14
sensors[nrSensors].sensorTyp=SENSOR_LEISTUNG;
15
sensors[nrSensors].data.pLeistung=leistung[0];
16
nrSensors++;
17
18
19
...
20
for(i=0;i<nrSensors;i++)
21
{
22
if(sensors[i].sensorTyp==SENSOR_KLIMA)
23
{
24
//ist ein Klima Sensor
25
mach_was_mit(sensors[i].data.pKlima);
26
}
27
elseif(sensors[i].sensorTyp==SENSOR_LEISTUNG)
28
{
29
// ist ein Leistungssensor
30
mach_was_anderes_mit(sensors[i].data.pLeistung);
31
}
32
else
33
{
34
// unbekannter Sensortyp, mit dem kann man nichts anfagen
35
// Weißt auf einen programmfehler hin, wenn das Programm jemals
Da leistung[leistung_pt] bereits ein Pointer auf Leistung ist, ist das
doppelt gemoppelt, richtig wäre dann eher:
1
sensors[s].data=(void*)&leistung[leistung_pt];
da ich ja den Pointer in den .data reinschreiben will und der ein (void
*) ist.
Das casting muss ich aber eigentlich nur beim Zugreifen manchen, und
nicht unbedingt beim Pointer zuweisen.
@Heinz
Das mit der 'union' ist zwar das gleiche was ich gemacht habe, aber von
der Typenprüfung etwas sicherer. Werde das mal ausprobieren.
Das Problem äussert sich darin, dass der Atmega328 neu startet wenn ich
die zwei letzten Zeilen einfüge. Entweder schreibe ich ausversehen in
ein Register oder springe sonst an eine 'falsche' Addresse. - oder - ich
habe ein Problem mit dem Stack, da ich einige Interrupts in Betrieb
habe, und da vielleicht was überschrieben wird.
Gruss
Nik
Karl Heinz schrieb:> Ich würde jedem empfehlen um void Pointer einen Bogen zu machen.> Meistens ist das keine gute Lösung.
Hm, was wenn man ein Bridge Pattern in C implementieren will? Oder wenn
man flexibel auf Daten zugreifen will, die von verschiedenem Typ sein
können, und erst zur Laufzeit feststeht (z.B. durch Benutzereingabe) was
man denn haben will?
Oder wenn man eine Lib schreibt und der Benutzer sich nicht auf Details
der Implementierung verlassen soll, weswegen ihm diese nicht bekannt
sein sollen.
Wer weiß was sowas ist, kann dann auch schon mit void Pointern umgehen.
Der fragt aber dann auch nicht hier im Forum nach.
Das ein Thomas Bubendorfer die Eiger Nordwand ohne Seil durchklettern
kann ist kein Argument dafür, dass jeder Hamburger Flachlandtiroler mit
nichts anderem als Sandalen in die Berge gehen kann.
Hier geht es um den Aufbau einer einfachen Datenstruktur, die man gut
ohne void Pointer implementieren kann. So wie 95% aller anderen
Datenstrukturen oder Pattern.
Niklaus S. schrieb:> Das Problem äussert sich darin, dass der Atmega328 neu startet wenn ich> die zwei letzten Zeilen einfüge. Entweder schreibe ich ausversehen in> ein Register oder springe sonst an eine 'falsche' Addresse. - oder - ich> habe ein Problem mit dem Stack, da ich einige Interrupts in Betrieb> habe, und da vielleicht was überschrieben wird.
Schön.
Dann brauchen wir das konmplette Programm und nicht nur ein paar
Ausschnitte.
Denn das Problem sitzt dann nicht dort, wo du es vermutest. Du siehst
nur die Symptome. Die sind aber nicht das eigentliche Problem.
void * mögen zwar ihre Tücken haben, aber bis darauf, daß das oben
gezeigte Programm unvollständig ist und Tippfehler enthält, und daher
gar nicht kompilieren würde, ist das, was da mit den Pointern gemacht
wird, prinzipiell richtig.
Wenn der Prozessor abstürzt, liegt es wohl daran, daß das
Originalprogramm ganz anders aussieht, oder eben an anderen Teilen des
Programms.
Oliver
Hallo Karl Heinz,
Das ist mir jetzt auch klar. Ich wollte nur noch eine andere Meinung
dazu hören ob ich da was übersehen habe bei der Implementation der
Datenstruktur, weil ja nach dem Einfügen der letzten Zeilen der uC
restartete.
Ich kann auch gerne das ganze Program senden, aber da es halt auf einen
Atemea328 mit RFM12 zugeschnitten ist wird das nicht viel bringen. Ich
werde wohl selbst nochmals weitersuchen müssen.
Gruss
Nik