PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : was für echte Profis????



baumagnat
06.08.2009, 18:17
Mein Code der unteranderem eine BUS-Verbindung eines Masters und mehreren Slaves beinhaltet funktioniert soweit. Jetzt wollte ich noch etwas optimieren und habe zwei Unterprogramme von dennen ich nicht weiß wie man es besser machen könnte.

Beim ersten wird ein 32Bit Wert in einzelne Bits zerlegt und dann seriell gesendet. Dies macht der Master....


void zerlegen (unsigned long int wert)
{
char bits01 , bits02 , bits03 , bits04 , bits05 , bits06 , bits07 , bits08 , bits09 , bits10;
char bits11 , bits12 , bits13 , bits14 , bits15 , bits16 , bits17 , bits18 , bits19 , bits20;
char bits21 , bits22 , bits23 , bits24 , bits25 , bits26 , bits27 , bits28 , bits29 , bits30;
char bits31 , bits32 ;

bits01 = bits02 = bits03 = bits04 = bits05 = bits06 = bits07 = bits08 = bits09 = bits10 = 0x00;
bits11 = bits12 = bits13 = bits14 = bits15 = bits16 = bits17 = bits18 = bits19 = bits20 = 0x00;
bits21 = bits22 = bits23 = bits24 = bits25 = bits26 = bits27 = bits28 = bits29 = bits30 = 0x00;
bits31 = bits32 = 0x00;

if ((wert & 0x80000000) == 0x80000000) bits01 = 1;
if ((wert & 0x40000000) == 0x40000000) bits02 = 1;
if ((wert & 0x20000000) == 0x20000000) bits03 = 1;
if ((wert & 0x10000000) == 0x10000000) bits04 = 1;
if ((wert & 0x08000000) == 0x08000000) bits05 = 1;
if ((wert & 0x04000000) == 0x04000000) bits06 = 1;
if ((wert & 0x02000000) == 0x02000000) bits07 = 1;
if ((wert & 0x01000000) == 0x01000000) bits08 = 1;
if ((wert & 0x00800000) == 0x00800000) bits09 = 1;
if ((wert & 0x00400000) == 0x00400000) bits10 = 1;
if ((wert & 0x00200000) == 0x00200000) bits11 = 1;
if ((wert & 0x00100000) == 0x00100000) bits12 = 1;
if ((wert & 0x00080000) == 0x00080000) bits13 = 1;
if ((wert & 0x00040000) == 0x00040000) bits14 = 1;
if ((wert & 0x00020000) == 0x00020000) bits15 = 1;
if ((wert & 0x00010000) == 0x00010000) bits16 = 1;
if ((wert & 0x00008000) == 0x00008000) bits17 = 1;
if ((wert & 0x00004000) == 0x00004000) bits18 = 1;
if ((wert & 0x00002000) == 0x00002000) bits19 = 1;
if ((wert & 0x00001000) == 0x00001000) bits20 = 1;
if ((wert & 0x00000800) == 0x00000800) bits21 = 1;
if ((wert & 0x00000400) == 0x00000400) bits22 = 1;
if ((wert & 0x00000200) == 0x00000200) bits23 = 1;
if ((wert & 0x00000100) == 0x00000100) bits24 = 1;
if ((wert & 0x00000080) == 0x00000080) bits25 = 1;
if ((wert & 0x00000040) == 0x00000040) bits26 = 1;
if ((wert & 0x00000020) == 0x00000020) bits27 = 1;
if ((wert & 0x00000010) == 0x00000010) bits28 = 1;
if ((wert & 0x00000008) == 0x00000008) bits29 = 1;
if ((wert & 0x00000004) == 0x00000004) bits30 = 1;
if ((wert & 0x00000002) == 0x00000002) bits31 = 1;
if ((wert & 0x00000001) == 0x00000001) bits32 = 1;


senden(bits01);
senden(bits02);
senden(bits03);
senden(bits04);
senden(bits05);
senden(bits06);
senden(bits07);
senden(bits08);
senden(bits09);
senden(bits10);
senden(bits11);
senden(bits12);
senden(bits13);
senden(bits14);
senden(bits15);
senden(bits16);
senden(bits17);
senden(bits18);
senden(bits19);
senden(bits20);
senden(bits21);
senden(bits22);
senden(bits23);
senden(bits24);
senden(bits25);
senden(bits26);
senden(bits27);
senden(bits28);
senden(bits29);
senden(bits30);
senden(bits31);
senden(bits32);

}

Nachdem der Slave beim Empfangen den Wert wieder zusammengezogen hat möchte ich zwei Werte haben. action ---> ist der Befehl und empf ---> ist der Wert dazu. Ich habe den Wert dazu zerlegt und dann neu errechnet.


void zerlegenempf (unsigned long int wert)
{

char bits01 , bits02 , bits03 , bits04 , bits05 , bits06 , bits07 , bits08 , bits09 , bits10;
char bits11 , bits12 , bits13 , bits14 , bits15 , bits16 , bits17 , bits18 , bits19 , bits20;
char bits21 , bits22 , bits23 , bits24 , bits25 , bits26 , bits27 , bits28 , bits29 , bits30;
char bits31 , bits32 ;

bits01 = bits02 = bits03 = bits04 = bits05 = bits06 = bits07 = bits08 = bits09 = bits10 = 0x00;
bits11 = bits12 = bits13 = bits14 = bits15 = bits16 = bits17 = bits18 = bits19 = bits20 = 0x00;
bits21 = bits22 = bits23 = bits24 = bits25 = bits26 = bits27 = bits28 = bits29 = bits30 = 0x00;
bits31 = bits32 = 0x00;



if ((wert & 0x80000000) == 0x80000000) bits01 = 1;
if ((wert & 0x40000000) == 0x40000000) bits02 = 1;
if ((wert & 0x20000000) == 0x20000000) bits03 = 1;
if ((wert & 0x10000000) == 0x10000000) bits04 = 1;
if ((wert & 0x08000000) == 0x08000000) bits05 = 1;
if ((wert & 0x04000000) == 0x04000000) bits06 = 1;
if ((wert & 0x02000000) == 0x02000000) bits07 = 1;
if ((wert & 0x01000000) == 0x01000000) bits08 = 1;
if ((wert & 0x00800000) == 0x00800000) bits09 = 1;
if ((wert & 0x00400000) == 0x00400000) bits10 = 1;
if ((wert & 0x00200000) == 0x00200000) bits11 = 1;
if ((wert & 0x00100000) == 0x00100000) bits12 = 1;
if ((wert & 0x00080000) == 0x00080000) bits13 = 1;
if ((wert & 0x00040000) == 0x00040000) bits14 = 1;
if ((wert & 0x00020000) == 0x00020000) bits15 = 1;
if ((wert & 0x00010000) == 0x00010000) bits16 = 1;
if ((wert & 0x00008000) == 0x00008000) bits17 = 1;
if ((wert & 0x00004000) == 0x00004000) bits18 = 1;
if ((wert & 0x00002000) == 0x00002000) bits19 = 1;
if ((wert & 0x00001000) == 0x00001000) bits20 = 1;
if ((wert & 0x00000800) == 0x00000800) bits21 = 1;
if ((wert & 0x00000400) == 0x00000400) bits22 = 1;
if ((wert & 0x00000200) == 0x00000200) bits23 = 1;
if ((wert & 0x00000100) == 0x00000100) bits24 = 1;
if ((wert & 0x00000080) == 0x00000080) bits25 = 1;
if ((wert & 0x00000040) == 0x00000040) bits26 = 1;
if ((wert & 0x00000020) == 0x00000020) bits27 = 1;
if ((wert & 0x00000010) == 0x00000010) bits28 = 1;
if ((wert & 0x00000008) == 0x00000008) bits29 = 1;
if ((wert & 0x00000004) == 0x00000004) bits30 = 1;
if ((wert & 0x00000002) == 0x00000002) bits31 = 1;
if ((wert & 0x00000001) == 0x00000001) bits32 = 1;

aktion = (bits01 * 0x80) + (bits02 * 0x40) + (bits03 * 0x20) + (bits04 * 0x10) + (bits05 * 0x08) + (bits06 * 0x04) + (bits07 * 0x02) + (bits08 * 0x01);

empf = (bits09 * 0x800000) + (bits10 * 0x400000) + (bits11 * 0x200000) + (bits12 * 0x100000) + (bits13 * 0x080000) + (bits14 * 0x040000) + (bits15 * 0x020000) + (bits16 * 0x010000);
empf = empf + (bits17 * 0x8000) + (bits18 * 0x4000) + (bits19 * 0x2000) + (bits20 * 0x1000) + (bits21 * 0x0800) + (bits22 * 0x0400) + (bits23 * 0x0200) + (bits24 * 0x0100);
empf = empf + (bits25 * 0x80) + (bits26 * 0x40) + (bits27 * 0x20) + (bits28 * 0x10) + (bits29 * 0x08) + (bits30 * 0x04) + (bits31 * 0x02) + (bits32 * 0x01);

}

Das muß doch einfacher gehen. Bestimmt kein Problem für Experten. Vielen Dank im Voraus.



Edit: Ich hab dir da Code-Tags reingegeben, sieht imho besser aus als bold (PicNick, Mod)

cmock
06.08.2009, 19:09
du solltest mal was über schleifen und bit-operationen in C nachlesen :-)



void zerlegen (unsigned long int wert) {
int bit;

for (bit = 0; bit < 32; bit++) {
if(wert & 0x80000000)
senden(1);
else
senden(0);
wert <<= 1;
}
}

void zerlegenempf (unsigned long int wert) {
int aktion;
unsigned long empf;

aktion = (wert & 0xff000000) >> 24;
empf = wert & 0xffffff;
}


"<<" und ">>" schieben einfach die bits nach links und rechts, "&" ist binäres AND.

baumagnat
06.08.2009, 19:41
tolle Idee!!!

geht aber beides nicht.

Schiebt da was in die falsche Richtung????

baumagnat
06.08.2009, 20:15
...und wie erzeugt man eigentlich so ein Code-Fenster????

radbruch
06.08.2009, 20:21
Hallo

"if ((wert & 0x00000001) == 0x00000001) bits32 = 1;"
Das niederwertigste Bit heißt 32? Das würde ich überdenken.

Nicht berauschend kompakt, dafür aber noch halbwegs übersichtlich geht's mit vordefinierten Arrays mit den Wertigkeiten:

uint32_t wertigkeit[32]={1,2,4,8,16,32, .... ,2^30,2^31} // *gg

Das kann man dann in einer Schleife abklappern:

for(i=0; i<32; i++) if(wert & wertigkeit[31-i]) senden(1); else senden(0); // MSB zuerst senden.

... sendet so das MSB zuerst. Empfangen könnte man dann etwa so:

aktion=0;
for(i=0; i<8; i++) if(wert & wertigkeit[31-i]) aktion+=wertigkeit[31-i]; // Bits 24-31

empf=0;
for(i=0; i<24; i++) if(wert & wertigkeit[23-i]) empf+=wertigkeit[23-i]; // Bits 0-23

Ich bin nicht sicher ob das so auf Anhieb funktioniert wegen der MSB/LSBs. Zusätzlich weiß ich auch nicht ob ich das Thema nicht völlig verfehlt habe.


Programmcode erzeugt die Codebox.

Gruß

mic

baumagnat
06.08.2009, 20:35
OK, die Wertigkeit umdrehen ist ja nicht das Ding. Ist ja nur eine Beschriftungssache.
Bin aber der Meinung das es doch irgendwie ohne den ganzen schwung an Variablen gehen müßte. Der erste Ansatz von "cmock" war auch so mein Gedanke. Aber wie???

p_mork
07.08.2009, 14:27
Hallo Baumagnat,


geht aber beides nicht.

Schiebt da was in die falsche Richtung????

Cmock's Code ist an sich eigentlich richig aber ich glaube da fehlt ein "UL" nach den Long-Zahlen. Ohne "UL" werden sie als ints interpretiert, und ein int hat beim avr-gcc 16 Bit, d.h. die letzten 16 Bit werden von 0x80000000 abgeschnitten. So müsste das funktionieren:


void zerlegen (unsigned long int wert) {
int bit;

for (bit = 0; bit < 32; bit++) {
if(wert & 0x80000000UL)
senden(1);
else
senden(0);
wert <<= 1UL;
}
}


bzw



void zerlegen (unsigned long int wert) {
int bit;

for (bit = 0; bit < 32; bit++) {
if(wert & 1UL)
senden(1);
else
senden(0);
wert >>= 1UL;
}
}

wenn LSB zuerst ausgegebenwerden soll.

MfG Mark

baumagnat
07.08.2009, 16:36
teste ich gleich mal

baumagnat
07.08.2009, 17:24
sau geil mein code wird aufeinmal pfeilschnell so das ich die pausen sogar erhöhen muß. Vorher hat das der Code ganz von allein gemacht ;-).

Was ist mit dem Empfangteil? Hat da noch jemand eine Idee?

Gruß Thomas

cmock
07.08.2009, 21:39
ich denk, beim empfangsteil wird's auch das problem mit dem fehlenden "UL" nach den hex-zahlen sein.

ich hab aber grad weder einen AVR noch einen simulator hier zum testen, und der assembler-output vom avr.gcc 4.3.2 schaut mit und ohne "UL" gleich und IMHO korrekt aus...

baumagnat
08.08.2009, 10:06
leider funktioniert er auch dann nicht auf die Idee war ich auch schon gekommen. Es muß doch eine einfache Metode geben die Bits zu teilen. Der Vorschlag von cmock sieht ja klein und knackig aus aber funktioniert halt leider nicht.

sternst
08.08.2009, 18:10
Hast du die Funktion etwa genau so übernommen, wie sie von cmock gepostet wurde? Das ist doch anscheinend keine Fertiglösung, sondern nur so eine Art Konzeptvorschlag, denn schließlich werden dort die ermittelten Werte am Ende der Funktion einfach "weggeschmissen". Du musst die Funktion selbstverständlich so umschreiben, dass die Werte dort landen, wo du sie hin haben möchtest.

PS: Wenn du z.B. zwei globale Variablen "aktion" und "empf" hast, musst du nur die ersten beiden Zeilen der Funktion löschen.

baumagnat
09.08.2009, 09:11
schon klar. Es sind aber globale Variablen und somit überall wieder verwendbar.

sternst
09.08.2009, 09:21
In dem Code von cmock sind es lokale Variablen, die die globalen verdecken.

baumagnat
09.08.2009, 10:13
hab ich rausgenommen.

sternst
09.08.2009, 10:24
Dann solltest du mal "geht nicht" genauer spezifizieren.
Dazu gehört:
- aktuellen Code posten
- konkreten Testfall posten, also mit was "fütterst" du die Funktion, was sollte herauskommen und was kommt statt dessen heraus

cmock
09.08.2009, 14:17
was in der hinsicht übrigens empfehlenswert ist, ist "avrstudio" von atmel. das ist eine kostenlose entwicklungsumgebung für AVRs, die einen simulator beinhaltet. da kannst dann zeile für zeile das programm durchdebuggen, variablen und register anschauen...

baumagnat
09.08.2009, 17:41
ich nutze avrstudio aber eine Simulation ist mir dort nicht bekannt.

cmock
10.08.2009, 09:16
debug/start debugging startet den simulator.

evtl muß man noch unter debug/AVR simulator options den controller und den takt einstellen.

baumagnat
10.08.2009, 21:46
der simulator hat leider auch keine neuen erkenntnisse gebracht.

Noch einmal das Problem:
Ich möchte aus einen 32bit Wert zwei Werte machen.
Dabei soll der erste Wert die obersten 8Bit groß sein
und der zweite Wert aus den restlichen 24bit bestehen.


Gibt es dafür eine einfache rechenweise????

Vielen Dank!!!

Viele Grüße Thomas

sternst
10.08.2009, 22:01
Gibt es dafür eine einfache rechenweise????Ja, wurde aber von cmock schon gepostet.
Also so lange du uns weder mitteilst, wie der Code aktuell konkret aussieht, noch was genau damit schief läuft, kann dir auch niemand wirklich weiterhelfen.

baumagnat
10.08.2009, 22:31
wenn dieser code konkret ist werde ich mich nochmal hinsetzen und nach und nach prüfen warum dann immer wieder falsche Werte ankommen. Vieleicht habe ich ja auch einen Denkfehler. Ich danke allen!!!!

Ich melde mich wenn ich nicht mehr weiterkommen sollte.

Gruß Thomas

sternst
10.08.2009, 22:44
Der Code ist vom Prinzip her korrekt. Ob er auch bei dir korrekt ist (kann ja auch ein simpler Tippfehler drin sein), kann man nicht sagen, wenn du ihn nicht postest. Und wenn du dann zusätzlich noch ...
Ach, vergiss es, ich bin es Leid dich quasi auf Knien anzubetteln, doch endlich das herauszurücken, was für eine schnelle Hilfe nötig wäre.

radbruch
10.08.2009, 23:03
Der einfachste Weg eine 32-Bit-Variable nach 8/24-Bit zu splitten dürfte eine Union (http://de.wikibooks.org/wiki/C-Programmierung:_Komplexe_Datentypen#Unions) sein. Das sind verschieden benannte Variablen unterschiedlicher Größe die sich den selben Speicherplatz teilen.

http://de.wikibooks.org/wiki/C-Programmierung:_Komplexe_Datentypen#Unions