es war zu schön um wahr zu sein. Auf dem mega128 lief das folgende Progamm super, nun, portiert auf einen mega 32 kommt nur noch mist raus. Die Aufgabe ist es, die zeichen seriell zu übertragen. Dabei ist dem Empfänger eine '1' ein 6uS ein-Impuls und 94uS aus und eine 0 100uS 0. Via Interrupttimer erzeuge setze ich alle 100uS "interruptcheck = 1" Die Auswertung macht void se_data(char data) //ein Zeichen aus data in den Displayspeicher schreiben { int i; extern volatile char interruptcheck; while(interruptcheck == 0) asm("NOP"); //solange das Bit nicht gesetzt ist, passiert nix if (data == '1') { setbit(PORTC,PC5); for (i=6; i>0; i--) asm("NOP"); // halte den Zustand über 6 Takte clearbit(PORTC,PC5); } interruptcheck = 0; } und serviert werden die Zeichen von i2=1; while (i2 < 69 ) { se_data(sestring[i2++]); // einzelnes Zeichen schicken } und so sehen die Zeichen aus... switch(data[i1]) { case '1': bluefn(); sprintf(sestring,"100000000001111111000010110111100101100010001010010010 0101111100000"); break; case '2': bluefn(); sprintf(sestring,"100000000001111111000011010111100110111011001000001010 0101111100000"); break; case '3': bluefn(); sprintf(sestring,"100000000001111111000010010111100100101010001100011010 0101111100000"); break; ... bluefn ist dabei genau so ein Monstrum wie sestring das kann man sicherlich einfacher und weniger speicherfressend gestalten, oder? Aber wie?
Was heisst "Mist", bzw. kannzt Du den Fehler etwas genauer definieren? Die Code-Schnipsel sehen ansich "vernünftig" aus, doch solange Du nicht den gesammten Code postest, kann Dir nur schwer weiter geholfen werden... Gruss Peter
hi, benutzt du den internen Takt ? Falls ja, sind vielleicht beiden Takte unterschidelich? Chris
Das halte ich mal für ein Gerücht:
> for (i=6; i>0; i--) asm("NOP"); // halte den Zustand über 6 Takte
1. Wenn Dein Compiler schlau ist, dann optimiert er das
komplett weg da es für ihn keinen Effekt hat
-> zumindest i auf volatile setzen
2. Das da 6 Takte rauskommen ist eheer unwahrscheinlich.
Die komplette Schleifensteuerung braucht eben auch seine
Zeit.
Deine Servierschleife ist auch Unsinn. In C wird mit 0 zu zählen angefangen! D.h. die erste '1' wir überhaupt nicht ausgegeben. Dafür greifst du auf das Zeichen mit der Indexnummer 68 im String zu. Das ist aber immer das abschliessende '\0' Zeichen, das jeden String abschliesst. Anstatt da lang rumzuzaehlen, mach doch die Ausgabeschleife so: i2 = 0; while( sestring[i2] ) { se_data( sestring[i2++] ); // einzelnes Zeichen schicken } Vorteil: Du brauchst nichts abzuzählen, die Schleife richtet sich automatisch nach der tatsächlichen Stringlänge Wenn Dein Compiler nicht so auf Zack ist, kannst Du ihm auch noch etwas unter die Arme greifen: i2 = 0; while( (c = *(sestring + i2++)) != '\0' ) se_data( c ); Aber bevor Du das tust, solltest Du in C schon firm sein.
Um genau 6 Zyklen zu warten, dürfen die NOP's natürlich nicht in einer Schleife stehen, ist natürlich klar. //---------------------------------- // Delay for six CPU cycles /---------------------------------- asm ("NOP"); asm ("NOP"); asm ("NOP"); asm ("NOP"); asm ("NOP"); asm ("NOP"); //---------------------------------- Um ganz sicher zu sein kann man auch {asm volatile ("NOP")} schreiben, doch ich nehme an, dass asm() Statements nie wegoptimiert werden! Peter
> bluefn ist dabei genau so ein Monstrum wie sestring > das kann man sicherlich einfacher und weniger speicherfressend > gestalten, oder? > Aber wie? Sicher kann man. Zunaechst mal kannst Du den sprintf ganz einfach loswerden: > sprintf(sestring, "1000000000011111110000101101111001011000100010100100100101111100000"); Das hier ist identisch zu: strcpy( sestring, "..........dein String ....."); Nur duerfte das etwas schneller ablaufen. Dann. Wenn ich mir Deine Strings so ansehe, dann sehe ich, dass die alle in weiten Teilen gleich aufgebaut sind. Das kann man sofort benutzen: strcpy( sestring, "1000000000011111110000101101111001" ); switch( data[i] ) { case '1': strcat( sestring, "01100010001010010" ); break; case '2': strcat( sestring, "10111011001000001" ); break; case '3': strcat( sestring, "00101010001100011" ); break; ... } strcat( sestring, "0100101111100000" ); /* erst jetzt ist sestring, vollstaendig fertig und kann uebertragen werden */ Damit bist Du die Monster los. Vielleicht lehne ich mich jetzt etwas zuweit aus dem Fenster, aber ich denke mal, dass diese Bitsequenzen irgendwelche Befehle bedeuten. d.h. ich wuerde mir da mal mittels define ein paar Konstante machen: #define COMMAND_A "1000000000011111" #define COMMAND_IRGENDWAS "1100001011011110" #define COMMAND_WAS_ANDERES_1 "0110001000101001" ... und dann mit denen arbeiten: strcpy( sestring, COMMAND_A ); strcat( sestring, COMMAND_IRGENDWAS ); switch( data[i] ) { case '1': strcat( sestring, COMMAND_WAS_ANDERES_1 ); break; case '2': strcat( sestring, COMMAND_WAS_ANDERES_2 ); break; case '3': strcat( sestring, COMMAND_WAS_ANDERES_3 ); break; ... } strcat( sestring, COMMAND_ENDE ); und holla. Plötzlich wird das ganze schon lesbarer. Ich weiss jetzt nicht, welchen Wertebereich data[i] überstreicht. Eventuell könnte man den ganze switch-case Block durch einen simplen Arrayzugriff ersetzen: #define COMMAND_A "1000000000011111" #define COMMAND_IRGENDWAS "1100001011011110" #define COMMAND_WAS_ANDERES_1 "0110001000101001" const char* Commands[] = { COMMAND_WAS_ANDERES1, /* '1' */ COMMAND_WAS_ANDERES2, /* '2' */ COMMAND_WAS_ANDERES3, /* '3' */ ... }; strcpy( sestring, COMMAND_A ); strcat( sestring, COMMAND_IRGENDWAS ); strcat( sestring, Commands[ data[i] ] ); strcat( sestring, COMMAND_ENDE ); Das ist doch schon was. Lesbar, kurz und wartungsfeundlich.
erst mal vielen dank an alle warum die 6 Nops ca. 6 Zyklen ausmachen weiss ich nicht. Es funktioniert nur mit mehr als 6 NOPs, sind es weniger, wird es wohl tatsächlich wegoptimiert. (damit hätte ich auch diese Frage geklärt) Defakto hatte ich knapp 70 solcher monströsen Strings in der Case-Schleife angelegt und da ist der Speicher übergelaufen. ich habe nun die Nacht damit zugebracht die Start- und Stop-Sequenzen abzutrennen und den Rest in Hex umzudandeln und den dann Bitweise durch den Port zu schieben. Klappt, und dass Programm ist von 45 hex. kbyte auf 5 hex kbyte geschrupft.
Da der Compiler erst mal jeden String ins Ram lädt braucht das gleich n haufen Speicher Man kann die Strings dann auch ins Flash verlagern. Steht im GCC-Tutorial Kapitel 17 Gruß Roland
"das kann man sicherlich einfacher und weniger speicherfressend gestalten, oder?" Aber sicher. Es tut mir in der Seele weh, wenn man Bits in Strings speichert, sind ja nur schlappe 700% Overhead. Wenn es nur um die Lesbarkeit des Quelltextes geht, es gibt Macros, um ein Byte in Bitschreibweise darzustellen bzw. für den AVR-GCC war man der Meinung, es direkt in den Compiler mit aufzunehmen (0b11111111). Dann sind pro String nur noch 9 Bytes nötig und die kann man auch im Flash ablegen. Wie genau müssen denn die 6µs und 94µs sein ? Mit irgendwelchen C-Loops ist das ne ziemlich unsichere Sache. Ich würds entweder mit Inline Assembler oder mit Timer machen. Peter
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.