Hallo,
ich habe folgendes Problem:
ich bekomme vom PC Daten über ein Protokoll mit folgendem Aufbau
Art Befehl-ID Wert
1Byte 2Byte 5 Byte
jetzt bekomme ich beim Wert jeweils Variablen mit Werten aus einem
Struct.
Ich empfange diese Daten und schreibe die als Struct ins EEPROM wobei
ich wiederrum zur Laufzeit auch einzelne Werte aus dem EEPROM lese bzw.
auch wieder schreibe.
Soweit so gut aber jetzt komme ich nicht weiter undzwar: Ist mir nicht
ganz klar wie ich:
a) empfangene Daten max 5 Byte (Wert) in das struct jeweils richtig den
entsprechenden Variablen zuordne.
b) wie stelle ich sicher, dass ich aus dem EEPROM auch wirklich die
Werte aus abgelegten Struct lese und sich das ganze nicht verschiebt.
Wäre schön wenn einer das Prinzip erklären könnte, denn ich kann nicht
ganz nachvollziehen wie ich die Informationen die in den 5 Bytes
enthalten sind so im struct ablege, sodass im PC und µC es gleich
aufgebaut ist.
Danke!
Das #pragma ist compilerspezifisch (hier für Microsoft C), bei anderen
Compilern ist das ein __packed, _attribute(irgendwas) oder wie auch
immer - steht jedenfalls in der Dokumentation.
Damit sagst Du dem Compiler, dass er die Variablen so dicht wie möglich
packed soll. Er würde sonst int16 auf durch 2 oder durch 4 teilbare
Adressen legen, denn manche Architekturen können keine misaliged
Zugriffe (zB Wortzugriffe auf ungerade Adressen).
fchk
Wenn die selbe Architektur das struct speichert und lädt ist gar kein
packed nötig! Wenn man nicht unbedingt jedes Byte sparen will!
Vorschlag:
int eeprom_store(uint32_t addr, void *data, size_t len);
int eeprom_load(uint32_t addr, void *data, size_t len);
aufrufen z.B. mit:
eeprom_store(0, &my_struct, sizeof(my_struct));
eeprom_load(0, &my_struct, sizeof(my_struct));
VG
Basti
P.S. sizeof beachtet das padding des Kompilates!
Jap,
selbst mit packed und gleichem Endian würde ich bei der Kommunikation
nicht folgendes tun:
memcpy(&my_struct, recv_buffer, sizeof(my_struct));
Dann sollte jeder lieber Element einzeln kopiert/extrahiert werden, auch
wenn es mehr Schreibarbeit bedeutet.
Beim EEPROM laden und speichern ist es dann wieder egal...
Hallo,
die Struktur sieht in etwa so aus (siehe unten) die ich bekomme und da
ist mir schon nicht ganz klar wie sie in 5Bytes übertragen wird, ich
denke das jede einzelne Variable die max 5Bytes vom Wert belegt aus dem
Struct übertragen wird, richtig?
Basti schrieb:> Vorschlag:>> int eeprom_store(uint32_t addr, void *data, size_t len);> int eeprom_load(uint32_t addr, void *data, size_t len);
ich möchte dafür die funktionen eeprom_update_block und
eeprom_read_block
nutzen aus <avr/eeprom.h>. Wie füge ich jetzt die Informationen die ich
in den 5 Bytes bekommen habe in das Struct ein ?
@Hans woher sollen wir wissen warum das 5 Byte sind und wie die
angeordnet sind? Das musst du herausfinden und das wäre auch die Lösung
wie du die eingehende Variable in deine Struktur speicherst.
Basti schrieb:> @Hans woher sollen wir wissen warum das 5 Byte sind und wie die> angeordnet sind? Das musst du herausfinden und das wäre auch die Lösung> wie du die eingehende Variable in deine Struktur speicherst.
Naja nach dem Protokoll
Art Befehl-ID Wert
1Byte 2Byte 5 Byte
werden die Variablen jeweils aus dem Struct von der Gegenseite (PC)
nacheinander in Wert übertragen. Jetzt hab ich z.B. dort den Wert von
der Variablen uint8_t zoomL; drinne. Aber wie schreibe ich das jetzt in
mein Struct auf dem µC welches ich dann ins EEPROM verschiebe oder wenn
das geht sofort ins EEPROM schreibe.
Denn von meinem Verständnis passt ja das ganze Struct nicht in 5 Bytes.
Daher ist das Schreiben hintereinander notwenig und woher weiß ich
welche Variable sich gerade in den 5 Bytes befindet?
Ich hoffe man kann das Problem in etwa verstehen ._.
Das Protokoll wird hoffentlich aus einem längeren Dokument bestehen und
das musst du verstehen!
Wir können maximal vermuten:
Wahrscheinlich sagt dir die "Befehl-ID" welche Variable gerade kommt und
dann liegt evtl. die Variable little endian gleich vorn in den 5 Byte...
Basti schrieb:> Wir können maximal vermuten:> Wahrscheinlich sagt dir die "Befehl-ID" welche Variable gerade kommt und> dann liegt evtl. die Variable little endian gleich vorn in den 5 Byte...
Es geht um das Prinzip das Protokoll besagt folgendes:
Art:Write / Read Befehl-ID: Adresse beginnt bei NULL Wert: Variable
aus dem Struct vom PC
Das vom PC gesendete könnte so ausehen:
Write (max. 1Byte) NULL (max. 2 Byte) zoomL = 240 (max 5.Byte);
Write (max. 1Byte) 1 (max. 2 Byte) gammaR = 2400 (max 5.Byte);
Write (max. 1Byte) 2 (max. 2 Byte) gammaG = 50000 (max 5.Byte);
etc..
Die Frage die ich eigentlich habe ist jetzt: wie extrahiere ich jetzt
aus dem Befehlsatz die Befehl-ID also die Adresse von wo das schreiben
ins EEProm beginnt dann den dazugehörigen Wert und wie schreibe ich das
nun ins EEPROM hab an sowas gedacht:
Es wird jetzt zwar ins EEPROM geschrieben und der Platz des Struct wird
im EEPROM angelegt aber ich möchte ja die Variablen die ich aus dem
Protokoll bekommen habe an die richtige adresse im EEPROM schreiben.
Um später z.B. beim start des µC die werte aus dem EEPROM zu laden oder
im laufenden betrieb darauf zu greifen uns sie als Offset verwenden.
Also ich weiß nicht genau worauf du hinaus willst... ich habe zwei
Vermutungen:
1. Du weißt nicht wie du mit einer Statemachine dieses Protokoll in
deinen µC sauber in einen Buffer einlesen kannst. Du kennst auch nicht
die Grundlagen des Framings. Dann könntest du dich z.B. hier erst einmal
grob über die Konzepte belesen:
https://sebastianfoerster86.wordpress.com/2017/02/01/protokolldesign-kommunikation/
2. Du hast noch keine switch case verwendet. Dann schlage ich mal vor
1
switch(Befehl_ID)
2
{
3
case0://schöner mit enum typen!
4
{
5
//Daten der EEPROM struct zuordnen und zuweisen und abspeichern
Basti schrieb:> Also ich weiß nicht genau worauf du hinaus willst... ich habe zwei> Vermutungen:>> 1. Du weißt nicht wie du mit einer Statemachine dieses Protokoll in> deinen µC sauber in einen Buffer einlesen kannst. Du kennst auch nicht> die Grundlagen des Framings. Dann könntest du dich z.B. hier erst einmal> grob über die Konzepte belesen:> https://sebastianfoerster86.wordpress.com/2017/02/01/protokolldesign-kommunikation/>> 2. Du hast noch keine switch case verwendet. Dann schlage ich mal vor> switch(Befehl_ID)> {> case 0: //schöner mit enum typen!> {> //Daten der EEPROM struct zuordnen und zuweisen und abspeichern> }> break;> }
Ein großes Danke schön dir schon mal !!!
Aber die Statemachine für das Protokol habe ich schon die auch soweit
funktioniert mir Fehlt das wissen in der Zeile von dir wo der Kommentar:
"//Daten der EEPROM struct zuordnen und zuweisen und abspeichern"
steht.
mein Buffer ist [8] groß wenn ich jetzt z.b die Befehls-ID extrahieren
möchte dann mache ich das so
1
2
uint16_tget_adr(void)
3
{
4
uint16_tui16Temp;
5
6
ui16Temp=ucRxBuffer[1];
7
ui16Temp<<=8;
8
ui16Temp+=ucRxBuffer[2];
9
10
returnui16Temp;
11
}
12
13
ui16Adr=get_adr();
soweit so gut aber wie gehe ich jetzt weiter vor wenn ich die Adresse in
der Variable ui16Adr habe wie weise ich das jetzt dem Struct zu und
schreibe das ins EEPROM?
Hans89 schrieb:> wie weise ich das jetzt dem Struct zu
In dem du die Daten in einen dafür reservierten Speicherbereich
schreibst!
Denn man kann einer Struktur keine Daten zuweisen.
Das wäre ein bisschen so, als würdest du das Wort "Eimer" auf Papier
schreiben und dann versuchen da Wasser einzufüllen.
Arduino F. schrieb:> In dem du die Daten in einen dafür reservierten Speicherbereich> schreibst!
Ich fürchte ich kann mein Problem schlecht in Worte fassen.
ich versuche es nochmal etwas anders zu beschreiben:
Bsp.:
1)Vom PC gesendet
Write (max. 1Byte) NULL (max. 2 Byte) zoomL = 240 (max 5.Byte);
Write (max. 1Byte) 1 (max. 2 Byte) gammaR = 2400 (max 5.Byte);
Write (max. 1Byte) 2 (max. 2 Byte) gammaG = 50000 (max 5.Byte);
2)extrahieren der Adresse und des Wertes aus dem RxBuffer
1
uint16_tget_adr(void)
2
{
3
uint16_tui16Temp;
4
5
ui16Temp=ucRxBuffer[1];
6
ui16Temp<<=8;
7
ui16Temp+=ucRxBuffer[2];
8
9
returnui16Temp;
10
}
11
12
uint64_tget_val(void)
13
{
14
uint64_tui64Temp;
15
16
ui64Temp=ucRxBuffer[3];
17
ui64Temp<<=8;
18
ui64Temp+=ucRxBuffer[4];
19
ui64Temp<<=8;
20
ui64Temp+=ucRxBuffer[5];
21
ui64Temp<<=8;
22
ui64Temp+=ucRxBuffer[6];
23
ui64Temp<<=8;
24
ui64Temp+=ucRxBuffer[7];
25
26
returnui64Temp;
27
}
28
29
ui16Adr=get_adr();
30
ui64Val=get_val();
3)
jetzt habe ich die Adresse als Wert in ui16Adr Variable und analog dazu
Wert in der ui64Val Variablen.
4) wie schreibe ich das ganze ins EEPROM an die Adresse 0 und den Wert
der in ui64Val steht und das ganze immer weiter je nachdem was im
Kommando vom PC steht[andere Adresse, anderer Wert].
folgendes funktioniert aber dabei schreibe ich nur den Wert
Hans89 schrieb:> Ich fürchte ich kann mein Problem schlecht in Worte fassen.
Das ist so nicht das Problem!
Folgendes läuft hier schief:
Du hast dir was ausgedacht, ohne die Bedingungen zu beachten.
Und jetzt hängst du auf dem falschen Ast, und siehst kein Weiterkommen.
Wie ich es machen würde:
Ich würde eine Struktur definieren, welche alle meine Daten, welche ins
EEProm kommen sollen erfasst.
Dann erzeuge ich eine Variable dieses Types, und teile dem Kompiler mit,
dass er diese Variable in der EEPROM Section anlegen soll.
Der Vorteil dieser Konstruktion:
1:
Der Kompiler/linker erzeugt mir ein *.eep File, welches ich per ISP auf
den Controler schreiben kann. Das ist schön, wenn man den Bereich mit
default Daten versehen möchte/muss.
2:
Ich komme nie mit der Adressberechnung durcheinander! Das tut alles der
Compiler für mich.
Arduino F. schrieb:> Ich würde eine Struktur definieren, welche alle meine Daten, welche ins> EEProm kommen sollen erfasst.
die Struktur gibt es siehe oben
Arduino F. schrieb:> Dann erzeuge ich eine Variable dieses Types, und teile dem Kompiler mit,> dass er diese Variable in der EEPROM Section anlegen soll.
hab ich auch soweit gemacht
Die Frage ist eine andere: Wie kann ich wenn ich die Funktion
eeprom_update_block nutzen möchte die Empfangen Daten ins EEPROM
schreiben, sodass ich darauf zu greifen kann
Hans89 schrieb:> Die Frage ist eine andere: Wie kann ich wenn ich die Funktion> eeprom_update_block nutzen möchte die Empfangen Daten ins EEPROM> schreiben, sodass ich darauf zu greifen kann
Die Funktion mit Quelle, Ziel, Anzahl aufrufen!
Wie sonst?
Beispiel:
Arduino F. schrieb:> int main(void)> {> unsigned long counter;> eeprom_read_block(&eep_datensatz.resetCounter,&counter,sizeof(counter)); //> lesen> counter++;> eeprom_write_block(&eep_datensatz.resetCounter,&counter,sizeof(counter)) ;//> schreiben>>> for(;;);> }
bei mir ist Information (Wert) in der Variablen ui64Val(Max. 5 Bytes)
enthalten welche sich entsprechend (je nachdem was der PC sendet) ändert
enthalten wie schreibe ich diese ins EEPROM?
Sorry:
eeprom_write_block(&eep_datensatz.resetCounter,&counter,sizeof(counter))
;// schreiben
Muss so:
eeprom_write_block(&counter,&eep_datensatz.resetCounter,sizeof(counter))
;// schreiben
Hans89 schrieb:> bei mir ist Information (Wert) in der Variablen ui64Val(Max. 5 Bytes)> enthalten welche sich entsprechend (je nachdem was der PC sendet) ändert> enthalten wie schreibe ich diese ins EEPROM?
Ich glaube, ich kann dir nicht helfen....
aufgeb
Hallo,
so geht es jetzt aber ich möchte eigentlich das die Variable ui64Val die
gesamte Struktur mit dem Wert von ui64Val füll unzwar jenachdem welches
element aus der Struktur (die Strukturen sind im µC und PC gleich
aufgebaut) vom PC gesendet wird:
in etwa so aber das funktioniert nicht weil die syntax nicht passt kann
mir vllt einer einen Tip geben wie man sowas macht?
Ich gebe auch auf...
Da hilft nur selbst nachdenken Hans! Alternativ ist dir das Projekt
evtl. zur Zeit zu schwieirg und zu viel für deine Fähigkeiten.
Das ist sehr motivierend .-(
Ich bin noch nicht so erfahren in C und weiß daher nicht wie man das
korrekt mit der syntax ausprogrammieren muss...
Vllt kann mir doch einer ein Beispiel machen
hmm
Du musst dich erst mal damit befassen wie die Daten im EErom abgelegt
werden. Außerdem ob es wirklich sinnvoll ist diese Daten zur Laufzeit
dauert aus dem EErom zu lesen ? Denn dieser ist langsam und veranlasst
zum warten .
Wenn du dass versteht wirst du auch Festellen das du nicht so einfach
auf einzelne Werte im Struct zugreifen kannst. Denn es wird Blockweise
gelesen und geschrieben. Du müssten wissen in welchen Block die Daten
liegen ;)
Überlichtweise ließt man das ganze Struct aus und schreibt es zurück
wenn sich etwas ändert.
Parameter etc. ließt man aus und arbeitet aus dem Speicher heraus mit
ihnen.
Nun auch solltest du dich damit befassen wie die Daten im Speicher
abgelegt werden. Es ist nicht gesagt das sie mit aufsteigenden Adressen
dort liegen. Auch weist du nicht wie die verschieden Datentype dort
angeordnet werden. Naja wenn man sich damit befasst schon ;)
Solche Konstrukte sind immer gefährlich wenn man die Architektur nicht
ausreichend kennt.
Ich verstehe auch nicht warum deine 64bit Daten Type nicht als Array
belässt. Das hin und herschieben bringt kaum was. Denn ein AVR wird sie
weiterhin byte weise speichern müssen.
Es gäbe noch eine Möglichkeit in dem man den Datentyp drüber castet.
ZoomSettings_t *packet=(ZoomSettings_t*)rxbuffer;
Du legst also einen pointer an von type ZoomSettings_t und weißt diesen
die Adresse von deinen buffer zu. Damit sich der Compiler nicht
beschwert wird dieser zum zoomSettings_t ebenfals gecastet.
dann kannst du mit packet->x=10; auf die daten zugreifen. Allerdings
musst du sicherstellen das dieser zusammenhängt angelegt (packed) .
Sonst greift du auf Adressen zu wo andere Daten liegen. Die MSB-LSB
Problematik muss man berücksichtigen bei Datentypen größer wie 1 byte.
Marco H. schrieb:> hmm>> Du musst dich erst mal damit befassen wie die Daten im EErom abgelegt> werden. Außerdem ob es wirklich sinnvoll ist diese Daten zur Laufzeit> dauert aus dem EErom zu lesen ? Denn dieser ist langsam und veranlasst> zum warten .
dieses wird nicht ständig gelesen nur beim start vom µc diese
offsetwerte werden vom PC bei der Konfiguration einmalig geschickt.
Marco H. schrieb:> Ich verstehe auch nicht warum deine 64bit Daten Type nicht als Array> belässt. Das hin und herschieben bringt kaum was. Denn ein AVR wird sie> weiterhin byte weise speichern müssen.
das hängt mit dem protokoll zusammen mit dem die Daten gesendet werden
welches 8Byte groß ist und aufgeteil in Art 1Byte , CMD-ID 2Byte und
Wert 5Byte ist ich extrahiere nur die 5Bytes da nur diese werte
interessant sind welche ich nacheinander in das Struct schreibe also
z.B. bekomme ich so etwas vom PC:
TYPE COMMAND-ID VALUE
W (max. 1Byte) 200 (max. 2 Byte) zoomL = 240 (max 5.Byte);
W (max. 1Byte) 200 (max. 2 Byte) gammaR = 2400 (max 5.Byte);
W (max. 1Byte) 200 (max. 2 Byte) gammaG = 50000 (max 5.Byte);
ich möchte jetzt nur jeweils VALUE in das Struct schreiben erst ins RAM
und dann mit eeprom_update_block() ins EEPROM.
und da weiß ich halt nicht wie ich den wert der bei mir in der Variable
ui64Val steht der Struct zuweise
Marco H. schrieb:> Es gäbe noch eine Möglichkeit in dem man den Datentyp drüber castet.>> ZoomSettings_t *packet=(ZoomSettings_t*)rxbuffer;>> Du legst also einen pointer an von type ZoomSettings_t und weißt diesen> die Adresse von deinen buffer zu. Damit sich der Compiler nicht> beschwert wird dieser zum zoomSettings_t ebenfals gecastet.>> dann kannst du mit packet->x=10; auf die daten zugreifen. Allerdings> musst du sicherstellen das dieser zusammenhängt angelegt (packed) .> Sonst greift du auf Adressen zu wo andere Daten liegen. Die MSB-LSB> Problematik muss man berücksichtigen bei Datentypen größer wie 1 byte.
die Daten sind packed und padding macht avr8 bit ja normal nicht
kannst du dan vllt ein Bsp. bringen etwas ausführlicher werde aus
ZoomSettings_t *packet=(ZoomSettings_t*)rxbuffer; nicht ganz schlau...
Moin...
Nächster Versuch dich zu verstehen, bzw. zu kommunizieren!
In deinen Texten kommen oft (max 5.Byte) vor.
Das finde ich sehr komisch.
Vielleicht hast du dich da ein bisschen festgebissen....
Und lenkst dich und uns damit ab.
Besonders absurd mit den (max 5.Byte) wird ist es hier:
Hans89 schrieb:> bei mir ist Information (Wert) in der Variablen ui64Val(Max. 5 Bytes)> enthalten
Das ist einfach unlogisch!
Eine uint64_t Variable wird niemals kleiner oder größer sein, als 8
Byte.
NIEMALS
So wie du sagst, kannst du grundsätzlich das EEPROM lesen und auch
beschreiben.
Du sagst aber nicht, warum du es mit diesen Daten nicht kannst.
Dabei ist den EEPROM Funktionen doch egal was du schreibst oder ließt.
Das sind treue und folgsame Sklaven.
Mein Tipp, fürs erste:
Vergiss das mit den 5 Byte!
Das verwirrt mich und auch offensichtlich dich selber.
Verwende stattdessen die Datentypen, welche dir dein C/C++ anbietet,
oder schaffe selber welche.
Aber höre bitte auf über die "max 5 Byte" zu reden.
Sag mal deine 5 byte sind nicht etwa eine Gleitkomma oder Festkomma Zahl
? Du versucht das in ein 64bit Format und quetschen und beim auslesen
kommt nur Käse raus ?
welchen Wertebereich haben denn einen ominösen 5 byte ?
Auf welche Art Hardware werden die Daten übertragen ? Ist das Protokoll
bekannt ? Ja welches ? Was soll man den Wert gemacht werden ?
MSB-LSB beachtet, besonders bei Seriellen Sachen die über
Schieberegister funktionieren, kommen die Daten auch so an wie du sie
erwartest ? oder ewt. spiegelverkehrt ?
Egal was du auf deinen AVR(8bit) anstellst alles bleibt bei 8bit auch
deine 64bit sind nur ein Array aus 1 byte Elemente auf die man über
Zeiger zugreifen kann.
Ach so was heißt maximal ? Ist der Frame dann etwa kleiner ? wer macht
denn so etwas ? Die Telegrammlänge sollte man schon Allgemein gültig
aushandeln unabhängig vom Wert. Dann füllt man sie eben mit Nullen auf
oder fügt im Frame die Länge der angehängten Daten mit ein. Der Header
bleibt immer immer gleich.
Arduino F. schrieb:> Das ist einfach unlogisch!> Eine uint64_t Variable wird niemals kleiner oder größer sein, als 8> Byte.> NIEMALS
das ist so gemeint, dass in der uint64_t ui64Val Variable die 5 Bytes
schon in der richtigen Reihenfolge aus dem buffer abgelegt sind
Arduino F. schrieb:> So wie du sagst, kannst du grundsätzlich das EEPROM lesen und auch> beschreiben.> Du sagst aber nicht, warum du es mit diesen Daten nicht kannst.> Dabei ist den EEPROM Funktionen doch egal was du schreibst oder ließt.> Das sind treue und folgsame Sklaven.
ich kann es auch mit diesen Daten z.B so
RAMZoomSettings.zoomL = ui64Val;
eeprom_update_block( &RAMZoomSettings, &EEPROMZoomSettings,
sizeof(ZoomSettings_t) );
die Frage ist ich weiß nicht wie ich die Daten die nach und nach vom PC
gesendet werden in das struct entsprechend ablegen kann...
Marco H. schrieb:> Sag mal deine 5 byte sind nicht etwa eine Gleitkomma oder Festkomma Zahl> ? Du versucht das in ein 64bit Format und quetschen und beim auslesen> kommt nur Käse raus ?
nein es sind die Datentypen aus dem Struct welches gleich im µC und PC
aufgebaut ist
Marco H. schrieb:> Auf welche Art Hardware werden die Daten übertragen ? Ist das Protokoll> bekannt ? Ja welches ? Was soll man den Wert gemacht werden ?
über HID-USB aber mit einem eigenem Datagram:
TYPE COMMAND-ID VALUE
W (1Byte) 200 (2 Byte) zoomL = 240 (5.Byte);
Marco H. schrieb:> MSB-LSB beachtet, besonders bei Seriellen Sachen die über> Schieberegister funktionieren, kommen die Daten auch so an wie du sie> erwartest ? oder ewt. spiegelverkehrt ?
senden empfangen funktioniert soweit
Marco H. schrieb:> Ach so was heißt maximal ? Ist der Frame dann etwa kleiner ? wer macht> denn so etwas ? Die Telegrammlänge sollte man schon Allgemein gültig> aushandeln unabhängig vom Wert. Dann füllt man sie eben mit Nullen auf> oder fügt im Frame die Länge der angehängten Daten mit ein. Der Header> bleibt immer immer gleich.
wird auch so gemacht wenn die Information nur 1Byte breit ist wird
trozdem 5 Byte gesendet also z.B so W (1Byte) 100 (2Byte) zoomL = 240
(5Byte)
Telegram ist immer 8Byte breit
Hans89 schrieb:> das ist so gemeint, dass in der uint64_t ui64Val Variable die 5 Bytes> schon in der richtigen Reihenfolge aus dem buffer abgelegt sind
Da findet eine Transformation statt:
Es tröpfeln 5 Byte über die Serielle rein.
Dann stopfst du sie in ein uint64_t.
Jetzt ist es ein 8 Byte uint65_t.
Fertig und Ende mit 5 Byte!
Die sind weg.
Transformiert!
Aus der Pferdescheiße sind Tomaten geworden.
(nur nicht in deinem Kopf, da gibts die 5 Byte immer noch)
Habe ich das gut erklärt?
;-)
Bisher extrahiere ich mir die jeweils notwendige Information aus dem
Datagramm so:
1
uint8_tget_art(void)
2
{
3
returnucRxBuffer[0];
4
}
5
6
uint16_tget_adr(void)
7
{
8
uint16_tui16Temp;
9
10
ui16Temp=ucRxBuffer[1];
11
ui16Temp<<=8;
12
ui16Temp+=ucRxBuffer[2];
13
14
returnui16Temp;
15
}
16
17
uint64_tget_val(void)
18
{
19
uint64_tui64Temp;
20
21
ui64Temp=ucRxBuffer[3];
22
ui64Temp<<=8;
23
ui64Temp+=ucRxBuffer[4];
24
ui64Temp<<=8;
25
ui64Temp+=ucRxBuffer[5];
26
ui64Temp<<=8;
27
ui64Temp+=ucRxBuffer[6];
28
ui64Temp<<=8;
29
ui64Temp+=ucRxBuffer[7];
30
31
returnui64Temp;
32
}
33
34
uint8_tucArt;
35
uint16_tui16Adr;
36
uint64_tui64Val;
37
38
ucArt=get_art();
39
ui16Adr=get_adr();
40
ui64Val=get_val();
was auch gut klappt vllt kann man hier besser erkennen das mein Wert der
vom PC gesendet wir sich in der Variablen ui64Val befindet und bei jedem
Sendevorgang befindet sich der Wert der jeweilen Variablen aus dem
Struct
Bsp:
Was sind in den Telegrammen dann diese "Type-ID" und "Command"?
Wenn ein Telegramm empfangen wird, woher weisst du ob ExposeN,
ExposeL oder ExposeD verschickt wurde?
> Bsp:>> typedef struct> {>> uint16_t exposeN;> uint16_t exposeL;> uint16_t exposeD;
...
> }Att_t;>> ui64Val = Att_t.exposeN;> ui64Val = Att_t.exposeL;> ui64Val = Att_t.exposeD;> usw...
Att_t ist eine Typedef, keine Variable. Die Zuweisung wird so nicht
funktionieren. Vielleicht suchst du einfach so was:
Bahnhof? Ich habe nicht den leisesten Hauch einer Ahnung wo dein Problem
ist (und ich glaube das liegt nicht an mir)
Wie sieht ein Beispieltelegramm aus, was genau soll damit gemacht
werden, warum geht das bei dir nicht?
Hans89 schrieb:> Bisher extrahiere ich mir die jeweils notwendige Information aus dem> Datagramm so:
Das, was Du da vorhast, geht vermutlich wesentlich einfacher mit einer
Union. Das ist eine spezielle Datenstruktur, mit der derselbe Speicher
mithilfe verschiedener Datentypen angesprochen werden kann.
Im folgenden Beispiel ist command_t::eeprom ein ganz einfacher Puffer,
in den die Daten aus der seriellen Schnittstellen geschrieben werden
können. command_t::data ist eine Datenstruktur vom Typ data_t, mit der
die Daten strukturiert aus dem Puffer gelesen oder hineingeschrieben
werden können.
Beachte bitte auch, daß ein struct oder ein typedef struct nur
beschreiben, wie eine Datenstruktur aussehen soll. Um die Datenstruktur
zu benutzen, muß sie angelegt werden; im folgenden Beispiel tut das die
Zeile "command_t c".
1
#include<stdio.h>
2
#include<string.h>
3
#include<inttypes.h>
4
5
typedefstruct{
6
charart;
7
charbefehl[2];
8
charwert[5];
9
}data_t;
10
11
typedefunion{
12
data_tdata;
13
chareeprom[8];
14
}command_t;
15
16
17
intmain(void){
18
19
charcmd[]="12345678";
20
21
command_tc;
22
memcpy(&c.eeprom,cmd,sizeof(c.eeprom));
23
24
for(inti=0;i<8;++i){
25
printf("%c",c.eeprom[i]);
26
}
27
printf("\n");
28
29
printf("%c | %c %c | %c %c %c %c %c\n",
30
c.data.art,
31
c.data.befehl[0],c.data.befehl[1],
32
c.data.wert[0],c.data.wert[1],
33
c.data.wert[2],c.data.wert[3],
34
c.data.wert[4]);
35
36
return0;
37
}
Ansonsten möchte ich Dir die Lektüre des Standardwerks "The C
Programming Language" von Brian Kerninghan und Dennis Ritchie ans Herz
legen. Da sind Sprachfeatures wie Zeiger, Datenstrukturen, Unions und
deren Verwendung hervorragend und mit Beispielen beschrieben. Das wird
Dir einerseits dabei helfen, ein besserer C-Programmierer zu werden,
andererseits aber auch, eventuell auftretende Probleme wie dieses besser
zu beschreiben, wenn Du noch einmal Hilfe benötigen solltest.
HTH und viel Erfolg!
PS: Die Verwendung strukturierender Satzzeichen, zum Beispiel von
Kommata, würde es wesentlich einfacher machen, Deine Texte zu verstehen.
Eric B. schrieb:> Was sind in den Telegrammen dann diese "Type-ID" und "Command"?> Wenn ein Telegramm empfangen wird, woher weisst du ob ExposeN,> ExposeL oder ExposeD verschickt wurde?
die Variablen werden vom PC nach und nach gesendet bis die gesamte
Struktur versendet wurde.
Das Problem ist der Buffer denke ich weil jetzt steht im EEPROM der
gesamte reservierte Bereich auf 0x91 (siehe Anhang) obwohl vom PC nur
einmal der Wert gesendet wurde nach dem folgenden Datagram:
[Type] [CMD-ID] [VALUE]
57 00 c8 00 00 00 00 91 (all Bytes in HEX)
1Byte 2Byte 5Byte
Wie kann ich den Buffer so aufbauen, dass alle Werte die Datagram für
Datagram vom PC gesendet werden sich darin befindet.
Sodass ich danach das ganze ins EEPROM schreiben kann...
z.B.
Vom PC gesendet:
[Type] [CMD-ID] [VALUE]
57 00 c8 00 00 00 00 22 (all Bytes in HEX)
57 00 c8 00 00 00 40 22 (all Bytes in HEX)
57 00 c8 00 00 34 00 22 (all Bytes in HEX)
57 00 c8 00 34 00 00 22 (all Bytes in HEX)
usw.......
jeweils nur Value extrahiert und im Buffer abgelegt dann den gesamten
buffer ins EEPROM
EEPROM sollte dann enthalten: 00 00 00 00 22 00 00 00 40 22 00 00 34 00
22 00 00 34 00 22
P.S. struct ist packed und aligned.
Hans89 schrieb:> z.B.>> Vom PC gesendet:>> [Type] [CMD-ID] [VALUE]>> 57 00 c8 00 00 00 00 22 (all Bytes in HEX)> 57 00 c8 00 00 00 40 22 (all Bytes in HEX)> 57 00 c8 00 00 34 00 22 (all Bytes in HEX)> 57 00 c8 00 34 00 00 22 (all Bytes in HEX)> usw.......>> jeweils nur Value extrahiert und im Buffer abgelegt dann den gesamten> buffer ins EEPROM>> EEPROM sollte dann enthalten: 00 00 00 00 22 00 00 00 40 22 00 00 34 00> 22 00 00 34 00 22
Das ist einfach, und dafür brauchst du weder structs noch uint64_t oder
sogar verschachtelte Funktionen.