for(uint8_ti=start;i<16;i+=2)// Auswahl der Zeile jede 2.
5
{
6
i2c_start(Bild_modul2_addr<<1);// schreibt modul 1
7
i2c_write(i);// angabe Zeile
8
i2c_write(bild1[nr]);// anzeige array
9
nr=nr+1;// array nr um 1 erhöht
10
_delay_ms(200);
11
i2c_stop();// Bus stop
12
}
13
}
Dazu übergebe ich dies:
1
Matrix_Write1Bild1Zeit(0);// schreibt bild1
Damit übergebe ich den Wert 0 und rufe das Programm auf. Innerhalb des
Programmes wird mit der Zeile 0 begonnen und jede 2 Zeile beschrieben.
Gleichzeitig wird aus dem Array Bild1 die nr durchgezählt und auf der
Matrix dargestellt. Damit es langsam von oben nach unten geschoben wird
ist das delay mit drin.
Das Problem ist die Umsetzung in Multitasking.
1. Versuch
Das delay austauschen - geht gar nichts mehr. z.B. so:
1
int16_tled1=0;
2
pause++;
3
if(pause==200)
4
{
5
Code// Schaltet
6
}
7
else
8
{
9
(pause=0;)
10
}
Da beide Schleifen verschachtelt sind, klappt es nicht bzw. beeinflussen
sich gegenseitig
pause wird aus einem Timer mit 1ms gesteuert.
1
if(flag_1ms)
2
{
3
flag_1ms=0;
4
pause++;
5
led_blinken1();// Aufruf Unterprogramm
6
}
Auch wenn ich die Abfrage über alles lege, geht es nicht.
Da es 8 Zeilen sind und jede Zeile mit eoiner Verzögerung von 200ms
läuft, ergibt es ca 1,6 Sekunden. Vollkommen ungeeignet,
Leider finde ich keinen Ansatz wie ich die Sache angehen kann.
Es sollen ca. 6 - 8 Matrix laufen. Ohne die Verzögerung geht es ohne
Probleme.
Atmega124p, 16 MHz, Zeit 1ms, Timer
achim
Was für ein Multitasking hast du denn?
Wenn du irgendeine Art von RTOS hast, solltest du da einen Timer
starten und an dieser Stelle die Steuerung an das OS abgeben. Die
genauen Umstände richten sich dann nach dem RTOS.
Wenn du selbstgezimmertes Multitasking machst, brauchst du auch
irgendeine Form von Timer. Prinzipiell kannst du dort natürlich
einen Hardwaretimer starten und in dessen Interruptroutine dann den
Stop für den I²C-Bus reinpacken, aber meist ist es sinnvoller, ein
allgemeineres Timer-Konzept zu haben, bei dem man jeweils zu bestimmten
Zeitpunkten oder nach bestimmten Zeitdauern etwas tun lassen kann.
Ggf. müsste dies dann mit einem Zustandsautomaten (state machine)
gekoppelt werden, der in diesem Falle zwischen den Zuständen „ruhend“
(nichts auf dem I²C los), „I²C gestartet“ und „I²C wartend“ (als
nächstes
muss dann der Stop kommen) wechselt.
Ein µC ohne OS macht prinzipiell kein Multitasking. Der arbeitet eine
Aufgabe nach der anderen ab. Mach einfach einen Timer der eine Variable
hochzählt. d.h. du zählst nr nicht in der Schleife sondern
Zeitgesteuert. jedes mal, wenn sich nr geändert hat schreibst du dann
die neue Zeile über I2C
Karl schrieb:> Ein µC ohne OS macht prinzipiell kein Multitasking.
Das ist zu sehr pauschalisiert. Sowie Interrupts benutzt werden,
hast du eine gewisse Nebenläufigkeit im Code, die man als Multitasking
ansehen kann. Kooperatives Multitasking käme sogar ohne Interrupts
aus (und sag nicht, dass kooperatives Multitasking keinen Sinn hätte:
erinnert sei hier an ältere Windows- und MACOS-Versionen).
Hallo Jörg
ich verwende einen Timer des 1284 und erzeuge damit eine ms. Einen RTOS
verwende ich nicht. Bisher habe ich es sogemacht, das alle
Unterprogramme usw. immer durchlaufen. Als Muster habe ich das
Multitasking aus dem WIKI genommen. Es geht (fast) alles ohne Probleme.
Nur leider diese verschachtelten Schleifen nicht. Ich suche einen Ansatz
wie man das machen kann
Hallo Karl
Karl schrieb:> d.h. du zählst nr nicht in der Schleife sondern> Zeitgesteuert.
Das klappt auch nicht, da die nr in Abhängigkeit der Zeilenzahl gesetzt
wird. nr wird in der Schleife erhöht.
Warum soll Multitasking nicht gehen. Auch mit RTOS habe ich nur einen
Kern zur Verfügung und kann nur eine Sache ausführen. Über das Thema
wurde schon lange diskutiert, so von KH oder Falk. Für mich ist es
wichtig, es geht einfach zu machen, nachvollziehbar und habe neben den
RTOS noch Platz für meine Programme.
achim
achim schrieb:> Nur leider diese verschachtelten Schleifen nicht. Ich suche einen Ansatz> wie man das machen kann
Nannte ich dir doch schon: Zustandsautomat.
> Für mich ist es> wichtig, es geht einfach zu machen, nachvollziehbar und habe neben den> RTOS noch Platz für meine Programme.
RTOS ist nicht gleichbedeutend mit „platzfressend“. Die gibt's durchaus
auch recht dünnwandig. Der Vorteil ist, dass jemand anders den Code
schon debuggt hat. ;-) Der Nachteil, ja, wenn man nicht auch das RTOS
selbst komplett verstanden haben will, hat man einige „undurchsichtige“
Teile an Code, bei denen man sich einfach nur auf die Doku verlässt.
Aber das mach' ich auf meinem PC auch: wenn ich „rm foo“ eingebe, dann
verlasse ich mich auch drauf, dass anschließend das OS den Namen „foo“
im Dateisystem auflöst, den zu dieser Datei gehörigen Eintrag aus dem
Verzeichnis löscht und, falls dies der letzte Eintrag für diese Datei
war, anschließend alle zu dieser Datei gehörenden Blöcke auf dem
Massenspeicher ausfindig macht und wieder freigibt. Um das zu benutzen,
muss ich mich nicht damit auseinandergesetzt haben, wie diese Blöcke im
Dateisystem angeordnet sind oder wie die Namenssuche im Detail arbeitet.
Jörg Wunsch schrieb:> Aber das mach' ich auf meinem PC auch: wenn ich „rm foo“ eingebe, dann> verlasse ich mich auch drauf, dass anschließend das OS den Namen „foo“> im Dateisystem auflöst, den zu dieser Datei gehörigen Eintrag aus dem> Verzeichnis löscht und, falls dies der letzte Eintrag für diese Datei> war, anschließend alle zu dieser Datei gehörenden Blöcke auf dem> Massenspeicher ausfindig macht und wieder freigibt.
Wenn's so einfach wäre ;-)
@ achim (Gast)
>zur Anzeige auf einer LED Matrix mit 8x8 LED mit dem I2C Bus verwende>ich den folgenden Code. Dieser läuft sehr gut, ohne jedes Problem.
Ist aber dennoch total falsch!
>void Matrix_Write2Bild1Zeit(uint8_t start) // schreibt bild1> {> int8_t nr = 0; // array nr auf 0> for (uint8_t i=start; i<16; i+=2) // Auswahl der Zeile jede 2.> {> i2c_start(Bild_modul2_addr<<1); // schreibt modul 1> i2c_write(i); // angabe Zeile> i2c_write(bild1[nr]); // anzeige array> nr = nr +1; // array nr um 1 erhöht> _delay_ms(200);> i2c_stop(); // Bus stop> }> }
Wozu für jede Zeile eine komplette I2C Transaktion mit start und stop?
Wozu 200ms Delay am Ende?
Das ist alles goßer Unsinn!
Werder kannst noch willst du dazulernen. Ich hatte dir eine korrekte
Version für das Beschreiben der LED-Matrix gegschickt, sie hat wunderbar
funktioniert. Aber aus einem wieder mal sehr irrationalen Grund hat sie
dir wohl nicht gefallen.
>Leider finde ich keinen Ansatz wie ich die Sache angehen kann.http://www.nadelspiel.com/stricken/strickmuster/>Es sollen ca. 6 - 8 Matrix laufen. Ohne die Verzögerung geht es ohne>Probleme.
Ach so? Oben hast du das Gegenteil behauptet!
>Atmega124p, 16 MHz, Zeit 1ms, Timer
Du hast immer noch nicht verstanden, dass man NICHT zwingend mit 1ms das
Multitasking machen muss. 10ms oder jeder andere Wert sind OK, wenn es
für die Aufgabe brauchbar ist.
Hallo Falk
die 200ms haben den Grund einer Verzögerten Anzeige. Das Bild wird
dadurch langsam aufgebaut. Nehme ich 50ms geht es recht zügig. Lasse ich
die Zeit weg, kommt das Bild sofort. Der verwendte IC lässt max 8
Adressen beim Bus zu. Habe auf der Platine jetzt 2 ICs drauf und auf
einer anderen noch mal ein IC. Zusätzlich sind dann noch ca 2 möglich.
Soweit ich Hardware habe. Wieso habe ich oben was naderes behauptet? Ich
nutze in dem Prg Tasterentprellung von KH 10 bzw 20 ms für die Taster
und einige Servos. Dein Programm nutze ich auch. Doch leider bekomme ich
damit auch kein Multitasking hin. Es geht dabei um die scheinbare
Darstellung und Bewegung auf verschiedenen Matrix und fast gleichzeitige
Nutzung anderer Module. Du hast doch selber den Beitrag geschrieben. Ob
ich jetzt 1 oder 20 ms nutze ist doch fast gleichgültig, hast du selber
geschrieben. Nutze zufällig gerade 1ms.
Die Zeit hat auch einen anderen einfachen Grund. Mit dieser Verzögerung
kann ich Bilde von einer Matrix auf eine andere Matrix "schieben", oder
bilder von oben oder links oder rechts. Dadurch ist eine Laufschrift
möglich.
Der Hersteller gibt doch selber Matrix mit 7x8 oder andere Grössen an.
Wieso Blödsinn, Teile von diesem Code stammen von dir oder Angaben aus
dem Datenblatt.
achim
@ achim (Gast)
>die 200ms haben den Grund einer Verzögerten Anzeige. Das Bild wird>dadurch langsam aufgebaut.
Wenn das die Absicht ist, ist die Umsetzung dennoch falsch. Wie man es
richtig macht, hast du schon vor einer kleinen Ewigkeit im Artikel
Multitasking gesehen.
>und einige Servos. Dein Programm nutze ich auch. Doch leider bekomme ich>damit auch kein Multitasking hin. Es geht dabei um die scheinbare>Darstellung und Bewegung auf verschiedenen Matrix und fast gleichzeitige>Nutzung anderer Module.
Tja, dazu muss man ein paar grundlegende Dinge verstehen, was dir seit
Jahren leider misslingt.
achim schrieb:> Das delay austauschen - geht gar nichts mehr. z.B. so:>
1
>int16_tled1=0;
2
>pause++;
3
>if(pause==200)
4
>{
5
>Code// Schaltet
6
>}
7
>else
8
>{
9
>(pause=0;)
10
>}
11
>
> Da beide Schleifen verschachtelt sind, klappt es nicht
das ist nicht der Grund.
Aber wie üblich bist du wieder mal schlampig in deinen Gedankengängen.
Wie soll denn pause da jemals den Wert 200 kriegen können?
Sobald es ungleich 200 ist, zum Beispiel den Wert 1 nach dem ersten
erhöhen hat, setzt du es sofort wieder auf 0 zurück. Mit dem Effekt,
dass pause ständig den Wert 1 bei der Abfrage auf 200 haben wird. 1 ist
aber nicht gleich 200 und daher ... setzt es dein Codeschnipsel gleich
wieder auf 0 zurück. Beim nächsten SChleifendurchlauf wird es wieder
erhöht, hat dann den Wert 1, 1 ist ungleich 200 .... daher wieder auf 0
setzen. ad infinitum.
1
pause++;
2
if(pause==200)
3
{
4
Code// Schaltet
5
pause=0;
6
}
Aber wie schon gesagt: In einer Multitaskung Umgebung, die auf Timern
basiert (also ohne RTOS welches die Taskmschaltung macht) zieht man das
alles ganz anders auf.
@Karl Heinz (kbuchegg) (Moderator)
>Aber wie üblich bist du wieder mal schlampig in deinen Gedankengängen.
Nur die persistente, gemeine Konfusion.
>Aber wie schon gesagt: In einer Multitaskung Umgebung, die auf Timern>basiert (also ohne RTOS welches die Taskmschaltung macht) zieht man das>alles ganz anders auf.
Dazu sollte man aber zuerst mal ein paar Programmiergrundlagen
beherrschen.
Jörg Wunsch schrieb:> Das ist zu sehr pauschalisiert. Sowie Interrupts benutzt werden,> hast du eine gewisse Nebenläufigkeit im Code, die man als Multitasking> ansehen kann.
O.K. ich hab hatte "meine eigene Definition" von Multitasking, die ehr
dem Begriff Multiprocessing entsprach.
achim schrieb:> Hallo Karl> Karl schrieb:>> d.h. du zählst nr nicht in der Schleife sondern>> Zeitgesteuert.> Das klappt auch nicht, da die nr in Abhängigkeit der Zeilenzahl gesetzt> wird. nr wird in der Schleife erhöht.
Mach es so:
Der Timer setzt alle 200 ms eine Variable write_line = 1
void Matrix_Write2Bild1Zeit(uint8_t start) // schreibt bild1
{
static int8_t nr = 0; // array nr auf 0
static uint8_t i = start
i2c_start(Bild_modul2_addr<<1); // schreibt modul 1
i2c_write(i); // angabe Zeile
i2c_write(bild1[nr]); // anzeige array
nr = nr +1; // array nr um 1 erhöht
i += 2
i2c_stop(); // Bus stop
if (i > 16){
i = 0;
}
write_line = 0;
}
while(1){
if write_line{
Matrix_Write2Bild1Zeit();
}
}
Dann wird alle 200 ms eine Zeile geschickt.
Hallo
Danke für eure Info und Hilfe.
Multitasking ist kein leichtes Thema. Wie oft hat KH schon gepredigt,
kein delay. Vielleicht ist das was ich mache noch blöder oder so, die
Verbindung von I2C Bus und Multitasking. Nach meinen ersten Aufbauten
und Programmen, kann ich jetzt schon sagen, es geht. Auch wenn es für
mich nicht einfach ist. Andere mögen darüber lächeln.
Das mit dem Schlampig hast du recht. Hatte die Sachen nicht weiter
gedacht. Bin gestern auf das gleiche gekommen. Deshalb auch meine Frage
nach Denkanstössen oder Richtung.
Als Grundlage ist das Programm von KH und Peter. Ordne alles, wirklich
alles der Zeit unter. Alle delay fliegen raus.
Danke, melde mich zum Ergebnis
achim
Karl schrieb:> void Matrix_Write2Bild1Zeit(uint8_t start) // schreibt bild1> {> static int8_t nr = 0; // array nr auf 0> static uint8_t i = start
Damit wird bei jedem Aufruf nr und i auf 0 gesetzt und die ganze Anzeige
bleibt in der Zeile 0 hängen.
Achim Seeger schrieb:> Damit wird bei jedem Aufruf nr und i auf 0 gesetzt und die ganze Anzeige> bleibt in der Zeile 0 hängen.
Schlüsselwort static net verstanden...
Nach handbuch C bedeutet static, das man diese Funktion nur innerhalb
der datei verwendet werden kann in der sie definiert wurde.
Das ist aber nicht das Problem.
Wenn ich es z.B. so schreibe:
i2c_start(HT16K33_modul2_addr<<1);// schreibt modul 1
10
i2c_write(i);// angabe Zeile
11
i2c_write(bild1[nr]);// anzeige array
12
i2c_stop();// Bus stop
13
nr=nr+1;// array nr um 1 erhöht
14
i+=2;
15
if(i>16)
16
{
17
i=0;
18
nr=0;
19
}
Damit begrenze ich die Eingabe auf Beginn der Zeilen 0 und 1. Bei jedem
Durchlauf soll i um 2 erhöht werden. Ich starte es aber immer bei 0 oder
1 neu, da alle 200ms ein neuer Aufruf der Funktion erfolgt. Dabei muss
das begrenzt werden und darf erst wieder auf 0 gehen wenn i=16 erreicht
wurde, nur beim ersten mal nicht. Jetzt bleibt i in der Zeile 0 hängen
und zählt 0 nicht hoch.
achim
Achim Seeger schrieb:> Nach handbuch C bedeutet static, das man diese Funktion nur innerhalb> der datei verwendet werden kann in der sie definiert wurde.
Du solltest dein Buch ein bißchen genauer lesen (oder, wenn's nicht
drinsteht, wegschmeißen und ein anderes kaufen).
"static" hat innerhalb von Funktionen eine andere Bedeutung als
außerhalb (die, die Du - richtig - erlesen hast).
Und natürlich ist "static" keine Funktion, sondern ein Schlüsselwort
bzw. eine Speicherklasse. Was das ist, sollte auch in deinem Buch
stehen, sonst -> Tonne.
Hallo Markus
Danke für die Info. Das Buch braucht nicht gleich in die Tonne. Werde
die Stelle suchen und lesen. Leider ist mir der Unterschied bisher nicht
klar gewesen.
achim