Du musst wert als unsigned deklarieren und vor und nach der Ubertragung
konvertieren.
Wenn du einen negativen int16 rechtsshiftest (>>), wird 1 statt 0
nachgeschoben.
Oder dividier und multiplizier mit 256 für das H-Byte
grundschüler schrieb:> Was ist falsch?
Vermutlich weiss der empfangende µC gar nicht, welches das High- und
welches das Low-Byte ist.
Ich erkenne in deinen Makros keinerlei Synchronisationsalgorithmus.
Jobst Q. schrieb:> Wenn du einen negativen int16 rechtsshiftest (>>), wird 1 statt 0> nachgeschoben.
klingt logisch, das wirds sein.
Wolfgang schrieb:> Synchronisationsalgorithmus
Der Sender trägt z.B. den Wert 325 in tx_buffer[10..11] ein. Der
Empfänger holt ihn aus rx_buffer[10..11] raus. Was soll da
synchronisiert werden?
Das Konvertieren zwischen unsigned und signed int macht man am besten
über eine union.
union {
int16 i;
uint16 u;
} wert;
Das heißt, es gibt für beide denselben Speicherplatz. Du schreibst den
Integerwert als wert.i rein und holst ihn als unsigned mit wert.u raus.
Oder umgekehrt.
Mit gcc kann man sogar direkt die Bytes herausholen:
#pragma pack(1) // Byteweise packen
typedef struct {
char h;
char l;
} tbytes
union {
int16 i;
tbytes b;
} wert;
#pragma pack() // Packweise zurückstellen
//Empfänger:
wert.b.h=owx_rx_buffer[pos]; wert.b.l= owx_rx_buffer[pos+1];
//Sender:
owx_tx_buffer[pos]=wert.b.h;owx_tx_buffer[pos+1]=wert.b.l;
grundschüler schrieb:> Was soll da synchronisiert werden?
In deinen Makros steht nur etwas von Zugriffen auf Byte-Arrays.
Irgendwie müssen die Daten doch vom µC1 zum µC2 rübergebeamt werden und
genau da muss es einen Synchronisationsmechanismus geben. Sonst könntest
du gleich deine 16Bit int16 Werte übertragen und dir die Byte-Arrays
sparen.
Oder geht es hier gar nicht um den Datentransfer?
was spricht gegen einen uint8_t *ptr mit längenangabe für die
sende/empfangsfunktion
so machen das alle üblichen verdächtigen
foo( uint8_t *ptr , uint32_t len )
{
foo( (uint8_t *)&daten16bit , 2 /*sizeof(datatype)*/ )
}
beim empfang auch in einen 16bit oder in 8bit array[2] empfangen mit
8bit *ptr
weil bei jedem byte der pointer incrementiert wird sind die daten immer
in der gleichen reihenfolge.
bei int16 oder short würde ich bei diversen architekturen aufpassen
das kann zum byteswap führen
Wenn ich eh nur 8bit übertragen kann ...
dann am besten mit uint8_t* pointer
Jobst Q. schrieb:> Das Konvertieren zwischen unsigned und signed int macht man am besten> über eine union.
Nein. Denn das bedeutet unterm Strich, dass du einen Member schreibst,
aber einen anderen liest. Und dies ist undefiniertes Verhalten. Man darf
nur den Member eines union lesen, welcher zu letzt geschrieben wurde.
Wolfgang schrieb:> Irgendwie müssen die Daten doch vom µC1 zum µC2
uc1 misst Temperaturen, Stromverbrauch, Durchfluss und regelt nach
diesen Werten die Heizung. Die Daten werden per Onewire an uc2
übertragen, der die Werte grafisch darstellt und zusätzliche
Steuerbefehle sendet. Die onewire-übertragung ist natürlich
synchronisiert. Das ganze funktioniert - bis auf die Übertragung
negativer Werte - perfekt.
Kaj G. schrieb:> Jobst Q. schrieb:>> Das Konvertieren zwischen unsigned und signed int macht man am besten>> über eine union.> Nein. Denn das bedeutet unterm Strich, dass du einen Member schreibst,> aber einen anderen liest. Und dies ist undefiniertes Verhalten. Man darf> nur den Member eines union lesen, welcher zu letzt geschrieben wurde.
Sind wir hier in einem schlechten Kindergarten, wo Regeln eingepaukt
werden, ohne sie zu verstehen?
union heißt, dass Variablen unterschiedlichen Typs auf demselben
Speicherplatz untergebracht werden. Oder andersherum, dass derselbe
Speicherinhalt als Variable unterschiedlichen Typs behandelt werden
kann. Da ist nichts am Verhalten undefiniert.
In diesem Fall ist es ja erwünscht, dass ein Integer mit Vorzeichen als
vorzeichenloser Typ behandelt wird, um ihn problemlos in einzelne Bytes
umzusetzen.
Wie würdest du das denn sonst machen?
Und wenn jetzt das Problem wäre, einen float-wert als einzelne Bytes zu
übertragen?
Mit einer union wäre das kein Problem. Eine andere Möglichkeit wäre über
einen gecasteten void-Pointer, aber Pointer sind ja auch nicht so
beliebt, außer bei denen, die damit umgehen können.
Jobst Q. schrieb:> Sind wir hier in einem schlechten Kindergarten, wo Regeln eingepaukt> werden, ohne sie zu verstehen?
Das ändert nichts daran, dass dein Ansatz garantiert
implementationsabhängiges Verhalten ist.
Ja, kann man so machen.
Wird auch funktionieren.
Ist nicht standardkonform.
Ein Cast über einen char-Pointer dagegen ist standardkonform.
Mit meinem winavr - neuere toolchain - geht das get_rx16 nicht. Im
Buffer steht richtig 0xfffe, ausgegeben wird 254.
Mit
#define get_rx16(pos) (i16)(owx_rx_buffer[pos]*256|owx_rx_buffer[pos+1])
kommt dann richtig -2 heraus.
Scheint also von der toolchain abhängig zu sein.
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