Forum: Mikrocontroller und Digitale Elektronik Bitschubserei...


von crazy horse (Gast)


Lesenswert?

Es müssen 2 CAN-Geräte gekoppelt werden, die sich erstmal nicht
verstehen. AT90CAN128/16MHz + MCP2515, also 2 getrennte Bussysteme.
Compiler CodeVision. Läuft auf beiden Seiten mit 500kbit und die Daten
und IDs müssen hübsch durcheinandergewürfelt werden. Im Prinzip
funktionierts, allerdings bekomme ich bei hoher Buslast Zeitprobleme.
Hauptverursacher ist folgende Routine:

void copy_bit_up (uchar s_botschaft, uchar s_byte, uchar s_bit, uchar
d_botschaft, uchar d_byte, uchar d_bit)
{if (CAN_Matrix1[s_botschaft].data[s_byte] & (1<<s_bit))
CAN_Matrix2[d_botschaft].data[d_byte]|= (1<<d_bit);     //Bit setzen
    else CAN_Matrix2[d_botschaft].data[d_byte]&= ~(1<<d_bit);
                                         //Bit löschen
}

copy_bit_up (6,1,4,4,1,7);     //source Botschaft, source byte_nr,
source bit_nr, dest_Botschaft, dest_byte_nr, dest_bit_nr
Generatorleuchte
Das dauert über 200 Takte...

Lösung2:
if (CAN_Matrix1[Botschaft6].data[byte1] & (0x10))
CAN_Matrix2[Botschaft4].data[byte1]|= (0x80);      //Bit setzen
    else CAN_Matrix2[Botschaft4].data[byte1]&= ~0x80;

Im Gegenzug mit absoluten Werten nur ca. 20 Takte
Und da ich ca. 150 Bits je Richtung umsortieren muss, gerät das ganze
schnell an Grenzen.
Codespeicher hätte ich genug, allerdings möchte ich mir es nicht antun,
Lösung2 300 mal zu schreiben, das ist zu fehlerträchtig.
Und nun die eigentliche Frage: Gibt es eine Möglichkeit, dieses ähnlich
guter alter Assembler-Macro-Programmierung zu lösen?

von Bjoern B. (tishima)


Lesenswert?

Hallo!

Mal etwas naiv gefragt, Codespeicher hast Du genug, was spricht denn
gegen eine look up table ??

mfg,
Bjoern

von thkais (Gast)


Lesenswert?

Moin,

Den Ausdruck (1<<x) durch Tabellen ersetzen sollte schon einiges
bringen, ist auch noch nicht zu groß. Ich würde auch noch eine
getrennte Tabelle für die negierten Werte machen.
Arbeitet der Compiler bei den logischen Operationen mit 16 oder 8 Bit?
Ein Typcasting auf 8 Bit bringt manchmal auch noch etwas.

von thkais (Gast)


Lesenswert?

hmpf - doch zu spät g

von Klaus H (Gast)


Lesenswert?

Vielleicht etwas optimieren:

Du berechnest 2 mal 1<<d_bit. Das kannst du in einer Variable
speichern. Dann der Datentyp: Welche Werte können (1<<d_bit) bzw.
(1<<s_bit) annehmen? Laut deinem Beispiel könnte das nur ein Byte sein,
der Compiler wird aber wahrscheinlich ein int daraus machen. Also
explizite typumwandlungen vornehmen:
((unsigned char)(1<<d_bit))


Macroprogrammierung kannst du mit Templates machen (wenn der compiler
das kann)

von Peter D. (peda)


Lesenswert?

Wie wärs, gleich beim Aufruf statt der Bitnummer die Bitmaske zu
übergeben ?

Dann entfällt die zeitraubende Schieberei.

Dem GCC ist leider in Vergleichsausdrücken das 16Bitten selbst mit cast
nicht abzugewöhnen.
Erst wenn man den Wert in einer 8Bit-Variablen ablegt, muß er
notgedrungen nur 8Bit vergleichen, z.B. wenn die Maske schon als 8Bit
vorliegt.


Peter

von crazy horse (Gast)


Lesenswert?

So, gerade mal die Funktion mit konstanter Bitadresse compiliert statt
der Schieberei

void copy_bit_up_test(uchar s_botschaft, uchar s_byte, uchar
d_botschaft, uchar d_byte)
{if (CAN_Matrix1[s_botschaft].data[s_byte] & (0x80))
CAN_Matrix2[d_botschaft].data[d_byte]|= (0x40);     //Bit setzen
    else CAN_Matrix2[d_botschaft].data[d_byte]&= ~(0x40);
                                         //Bit löschen
}
Da sind es nur noch 130 Takte, dazu käme ja noch der Tabellenzugriff +
Parameterübergabe, das wird nicht die Lösung werden.

Ich möchte schon zur Compile-Zeit die Bitadresse ausrechnen lassen.
Was sind templates? Klingt erstmal interessant.

von Peter D. (peda)


Lesenswert?

Wie wird denn copy_bit_up_test() aufgerufen ?

Wenn die Argumente Konstanten sind, dann ist es besser gleich beim
Aufruf die Adresse zu übergeben, statt erst umständlich ne 2-fache
Indirektion ausrechnen zu lassen.


Peter

von crazy horse (Gast)


Lesenswert?

Logisch, direkt die Bitmaske zu übergeben, ist natürlich effektiver. Kam
wohl daher, dass im CAN-Funktionsrahmen die Bitvariablen mit Botschaft:
ByteNr:BitNr angegeben sind:-)
Aber es ist auch nicht die Lösung, braucht 140 Takte

von crazy horse (Gast)


Lesenswert?

copy_bit_up_test (6,1,0x10,4,1,0x80);     //source Botschaft, source
byte_nr,source_bit_mask, dest_Botschaft, dest_byte_nr, dest_bit_mask

Die Variablen selbst:
typedef struct
{
    unsigned int  id;
    unsigned char rtr;
    unsigned char length;
    unsigned char data[8];
} CANMessage;


CANMessage CAN_Matrix1[24];
CANMessage CAN_Matrix2[24];

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.