Forum: Mikrocontroller und Digitale Elektronik Mehrere Aufgaben abarbeiten


von mike32m (Gast)


Lesenswert?

Ich erarbeite gerade ein Projekt, bei dem ein ATmega32 mehrere Aufgaben 
übernehmen soll:
- Temperatur im zeitl. Rhythmus ermitteln (1-Wire DS1820)
(- Luftfeuchte ebendso ermitteln (später auch andere Sensoren))
- LED schalten (später Verbraucher) wenn Befehl via RFM12 erhalten
- Tastaturmatrix auslesen (i2C)
- eingegebene und gemessene Daten auf LCD darstellen (2-Wire)
- eingegebene und gemessene Daten via RFM12 senden
- Anfragen via RFM12 entgegennehmen und verarbeiten (Befehle)

Hat jemand schon sowas aufgebaut und kann mir Tips geben, wie diese 
Aufgaben sinnvoll verteilt/organisiert werden sollten.
Da hier verschiedene Module zusammenkommen, die mit unterschiedlichen 
Interrupts arbeiten, ist es für mich momentan ein wenig chaotisch und 
ich würde dies gern in geordnete Bahnen bringen.

Danke für Anregungen zur Herangehensweise.
Gruß Mike

von Pepe (Gast)


Lesenswert?

Hallo,
hab ne ähnliche Geschichte am Laufen. Hab folgenden Ansatz verfolgt:

- Endlosschleife, die auf entsprechende Flags im Speicher reagiert:

  if (mLCDNeuerWert) {
     zeigeWertAn
  }

  if (...) {
     macheDenNächstenJob
  }

- Die Flags werden rein durch die INTs gesetzt.

- Möglichst nur INT-basiert arbeiten: z.B. USART Ausgabe komplett über 
INTs
  die Zeichen in den Puffer eintragen, wenn der Puffer leer ist;

- Tätigkeiten anstossen ( z.B. Befehl über USART rausschicken ) auf die
  Antwort per INT warten. Eintragen der Antwortzeichen in Puffer und 
wenn
  alle Zeichen empfangen ( =EOT ), dann Flag in Variable setzen, um 
darauf
  in der Hauptschleife reagieren.

Sorry, hab nur USART gearbeitet. Hoffe Dir trotzdem geholfen zu haben.

Gruß, Pepe

von Peter D. (peda)


Lesenswert?


von Patrick W. (seennoob)


Lesenswert?

Ok Ich würd an erster Stelle mal die Aufgaben analysieren und dann 
ordnen wie wichtig eine Aufgabe ist. Danach die Priorität für die 
Interruptsfestlegen.

MFG

von aha (Gast)


Lesenswert?

>Danach die Priorität für die Interrupts festlegen.

Mega32. Kann das nicht. Muss er auch nicht. Die Aufgaben sind ja alle 
eher langsamer Art. Wie der erste Poste meinte : Den ADC und das UART im 
Interrupt laufen lassen und alles im Main mit einem Timer und Flags 
koordinieren.

von Patrick W. (seennoob)


Lesenswert?

Naja wennst jetzt Daten vom RFM Modul bekommst kann das blöd laufen wenn 
du nebenbei etwas anderes abarbeitest. Denn dann kann es dir dein 
Timming zusammenhauen ! Also würd ich da unter anderem wenn zB daten 
Empfangen oder Gesandet werden einfach mal die interrupts ausschalten 
(bis auf die Timerinterupts)

MFG

von peterguy (Gast)


Lesenswert?

Ich verwende für solche Aufgaben immer ein selbstentworfenes 
Stapelverarbeitungssystem.
Der Grundgedanke dabei ist, daß Funktionen auf einen Stapel gelegt 
werden können und von dort schnellstmöglich abgearbeitet werden.

Damit eine Funktion auf den Stapel gelegt werden kann muss sie folgenden 
Funktionsprototyp verwenden:
1
 void Funktionsname (void);

Auf diesen Funktionstyp wird ein Funktionspointer definiert:
1
 typedef void (*pFunc)( void );

Der Stapel sieht so aus (hier als Ringpuffer der Größe 20 
implementiert):
1
 struct {
2
  uint8 writeIndex;
3
  uint8 readIndex;
4
  pFunc job[20]; 
5
}OS_JobList;

Dann gibt es zwei Funktionen für Zugriffe auf den Stapel. Hier aus 
Gründen der Übersichtlichkeit nur die Prototypen, bei Interesse kann ich 
auch die kompletten Funktionen posten:
1
 
2
// adds function to the end of the list
3
int OS_AddJobToList( pFunc function ); 
4
5
// gets next job from list. returns a NULL pointer if list is empty
6
pFunc OS_GetNextJobFromList( );

Hier die Funktion, welche die Liste abarbeitet:
1
 void OS_Dispatcher( void ) 
2
{
3
  pFunc function;
4
  
5
  // try to get next job
6
  function = OS_GetNextJobFromList( );
7
  
8
  // Check if new job is available
9
  if (function == NULL) {
10
    return;  
11
  }
12
     // execute job
13
  (function)();
14
  
15
  return; 
16
}

Diese Dispatcher Funktion wird so im Hauptprogram aufgerufen:
1
void main (void)
2
{ 
3
   InitAll();
4
   while(1)
5
   {
6
      OS_Dispatcher();
7
   }
8
}

Der Code ist sehr schlank und sehr effektiv. Wenn man möchte kann man 
den Code noch um einen Scheduler erweitern, der dann auf Basis eines 
Timerinterrupts in festen Zeitabständen Funktionen auf den Stapel legt.
Ich kann auch hier gerne Beispielcode posten, nur ist der leider 
Hardwareabhängig und auf Freescale S12X MCUs ausgelegt.

von Falk B. (falk)


Lesenswert?

Siehe Multitasking

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.