Archiv verlassen und diese Seite im Standarddesign anzeigen : Schleifen parallel abarbeiten ???
Hallo zusammen, noch eine Frage ;o) zum parallelen Abarbeiten von Schleifen.
Bei mir liegt folgende Struktur vor:
schleife(immer wiederholend)
{
schleife_A()...
schleife_B()
}
Wie macht man es, das die Schleifen A und B parallel durchgearbeitet werden können.
Danke und Grüße
popi
pebisoft
14.06.2006, 17:32
nimm 2 micro......
Was passiert denn in den beiden Schleifen? Generell ist ein AVR natürlich kein Parallelrechner, aber ein rudimentäres Multitasking-System ließe sich wohl verwirklichen. Sind in den beiden Schleifen Warteschleifen enthalten? Dann solltest du diese entfernen und stattdessen die Timer nutzen und während der Pausen die zweite Aufgabe erledigen lassen....
Das klingt gut... es sind tatsächlich Warteschleifen drin...
Aber wie soll ich sie entfernen.
Mein Programm nutzt alle Timer um mehrere LEDs anzusteuern.
Hier der code (oder ein Teil daraus):
DDRB = (1<< DDB4) | (1<< DDB5) | (1<< DDB7) | (1<< DDB6);
PORTB = (1<< PB4) | (1<< PB5) | (1<< PB7) | (1<< PB6);
OCR0,OCR2,OCR1A,OCR1B = 0x00;
TCCR0 = (1 << WGM00) | (1<< COM01) | (1<< CS00);
TCCR2 = (1 << WGM20) | (1<< COM21) | (1<< CS20);
TCCR1A = (1 << WGM10) | (1 << WGM11) | (1<< COM1A1) | (1<< COM1B1);
TCCR1B = (1<< CS10);
while(x==2)
{
while(OCR0 <= 0x60) {for (i=0;i<300;i++) asm volatile("NOP"); OCR0 = OCR0 + 1;}
while(OCR2 <= 0x40) {for (i=0;i<300;i++) asm volatile("NOP"); OCR2 = OCR2 + 1;}
while(OCR1A <= 0xA0) {for (i=0;i<100;i++) asm volatile("NOP"); OCR1A = OCR1A + 1;}
while(OCR0 >= 0x40) {for (i=0;i<100;i++) asm volatile("NOP"); OCR0 = OCR0 - 1;}
while(OCR2 >= 0x10) {for (i=0;i<100;i++) asm volatile("NOP"); OCR2 = OCR2 - 1;}
while(OCR1A >= 0x10) {for (i=0;i<100;i++) asm volatile("NOP"); OCR1A = OCR1A - 1;}
while(OCR0 <= 0xCF) {for (i=0;i<200;i++) asm volatile("NOP"); OCR0 = OCR0 + 1;}
while(OCR1B <= 0xA0) {for (i=0;i<100;i++) asm volatile("NOP"); OCR1B = OCR1B + 1;}
while(OCR1A <= 0xA0) {for (i=0;i<100;i++) asm volatile("NOP"); OCR1A = OCR1A + 1;}
while(OCR0 >= 0x10) {for (i=0;i<100;i++) asm volatile("NOP"); OCR0 = OCR0 - 1;}
while(OCR1B <= 0x05) {for (i=0;i<100;i++) asm volatile("NOP"); OCR1B = OCR1B - 1;}
while(OCR1A >= 0x10) {for (i=0;i<100;i++) asm volatile("NOP"); OCR1A = OCR1A - 1;}
Danke und Grüße
popi
Kannst du das Konzept, das dahintersteht, mal in ein paar Worten erklären? Auf den ersten Blick scheint mir die Methode ziemlich abstrus... du zählst die Compare-Register hoch, bis sie einen bestimmten Wert erreicht haben? Was willst du damit ansteuern?
Das mag wirklich wirre aussehen, hast recht. (ist es auch) :o)
Aber ich habe erst gestern richtig angefangen, ein Programm in einen Controller zu schieben und dieses zu starten.
Der Timer 0 und 2 steuern eine rot/gelb Led an, die aussieht, als würde ein Streichholz brennen. Daher diese wirren Additionen und Subtraktionen.
Timer 1 Ausgang A und B sollen das gleiche tun, da bin ich aber noch dran, denn das mit dem B-Kanal funktioniert noch nicht wirklich.
Grüße
popi
Mal nen anderer Ansatz für dein Problem: Einen Timer auf ein möglichst kurzes Intervall einstellen, und in der ISR entweder über genügend lange (und verschiedenlange) Tabellen oder mit Zufallszahlen die PWM-Ausgänge (oder gleich Software-PWM, wenn die Kanäle nicht reichen) ansteuern...
Uwe, ich muss bis nächste Woche für den Schulabschluss ein Programm fertigkriegen und ganz davon zu schweigen, das es unmöglich ist (aber ich muss es schafen) und ich leider nicht wirklich viel Ahnung habe, was ich hier tue, würdest Du mir mit kleinen Routinen helfen können.
Ich würde Dir auch was bezahlen, hauptsache ich kriege keine 5.
Das wäre echt nett!
Was sagst Du dazu?
SprinterSB
14.06.2006, 23:59
Du kannst doch die Schleife über alle OCRs machen und jeder eine eigene Variable verpassen, die zählt, ob der Wert verändert werden soll.
Also, so könnte man das machen, indem man die inneren Schleife auflöst. Du kannst dir jetzt das Hirn zerrauchen und überlegen, was das alles soll und was es tut und das Zeug kommentieren. Denn wenn du was abgibst, das du nicht blickst, gibt's bestimmt auch ne 5 ;-)
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#define NUM_OCRS 2
typedef struct
{
uint8_t countdown;
void volatile * const preg;
const uint8_t size;
uint16_t zielwert;
} ocr_count_t;
void loop();
void tick (ocr_count_t*);
ocr_count_t ocr_counters[NUM_OCRS] =
{
{ 0, &OCR2, sizeof (OCR2) },
{ 0, &OCR1A, sizeof (OCR1A) }
};
void tick (ocr_count_t * poc)
{
if (poc->countdown != 0)
{
poc->countdown--;
return;
}
poc->countdown = rand();
if (1 == poc->size)
{
uint8_t * pocr = (uint8_t*) poc->preg;
uint8_t ocr = * pocr;
uint8_t ziel = poc->zielwert;
if (ocr == ziel)
{
ziel = rand();
poc->zielwert = ziel;
}
if (ocr < ziel) ocr++;
if (ocr > ziel) ocr--;
*pocr = ocr;
}
if (2 == poc->size)
{
uint16_t volatile * pocr = (uint16_t volatile *) poc->preg;
uint16_t ocr = * pocr;
uint16_t ziel = poc->zielwert;
if (ocr == ziel)
{
ziel = rand();
poc->zielwert = ziel;
}
if (ocr < ziel) ocr++;
if (ocr > ziel) ocr--;
*pocr = ocr;
}
}
void loop()
{
uint8_t i;
while (1)
{
for (i=0; i < sizeof (ocr_counters) / sizeof (ocr_count_t); i++)
tick (& ocr_counters[i]);
_delay_loop_1 (42);
}
}
ja, Du hast rechts... nur durch probieren kann man lernen...
Bin ja dabei und lerne durch Eure Beispiele.
Wenn man den Code nicht selbst programmiert, blickt man nicht durch, wie ich z.B. bei Deinem Beispiel ;o)
Aber habe ihn kopiert und in meine "Formelsammlung" unter dem Punkt "ungeklärt" abgelegt...
Ich bleib erst mal bei den Zeilen, die ich erstellt habe, denn durch eine vermischung der PWM Schleifen untereinander hab ich ein zufriedenes Ergebniss erzielt. Natürlich muss man justieren, dachte ich, und erhöhte den internen Quarz von 4 auf 8 MhZ... und es klappte ;o)
Als nächstes muss ich das Empfangen von Daten über UART auswerten... Also in den EEPROM packen nach dem Empfangen.
Da komme ich bestimmt noch mal auf Dich/Euch zu, vielleicht schon morgen ;o)
Grüße
popi
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.