mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik USART_Polling_oder_Interrupt


Autor: AVR_Beginner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Habe da ein Problem:
Ich will mit folgendem Code den USART betreiben.
Unglücklicherweise las ich, dass bei Auftreten von mehreren ISRs dieser 
Sourcecode ungeeignet ist (sprich: Der Stack wird zusammengehaut) etc.

Wie man ersehen kann benutzt der Code schon einen Timer overflow 
interrupt. Meine Frage an euch Experten ist es, ob ich vl. evtl. evtl. 
doch nicht noch den USART-Recieve_ISR einfügen kann? (=Ich habe in 
dieser Routine nichts anderes vor, als UDR in eine andere Variable 
umzuspeichern und ein Flagbyte zu setzen?
Durch Abfrage des Flags in TestC soll dann der Wert abgearbeitet werden.
Eine Alternative ist die Pollingmethode,  jedoch befürchte ich, dass die 
Variable überschrieben werden könnte?
Mein MCU ist ein atmega32.
/// Includes //////////
#include <avr/io.h>
#include <avr/interrupt.h>

/// Data Types /////////
typedef unsigned char u8;
typedef unsigned int u16;
typedef struct task
{
   // pointer to a function
   void (*pfunc) (void);
   // delay before the first call
   u16 delay;
   // interval between subsequent runs
   u16 period;
   // flag indicating time to run
   u8 run;
}task;

struct USART
{ unsigned char empfangen;
unsigned char wert;
}

/// Defines ///////////
// 25msec period 256-180 
// 7.3728MHz and /1024 prescaler
#define StartFrom       76
// maximum number of tasks
#define MAXnTASKS       20

/// Globals ///////////
volatile task TaskArray[MAXnTASKS];

/// Prototypes ////////
void InitUART (u16 baud);
void TransmitByte (u8 data);
void InitScheduler (void);
void UpdateScheduler(void);
void DeleteTask (u8 index);
void AddTask (void (*taskfunc)(void), u16 taskdelay, u16 taskperiod);
void DispatchTask (void);

void TestA (void);
void TestB (void);
void TestC (void);

/// Main //////////////
int main(void)
{
   InitUART (23);
   InitScheduler();
        
   // populate task array       
   AddTask (TestA, 0, 3);
   AddTask (TestB, 1, 4);
   AddTask (TestC, 4, 0);
        
   // enable interrupts
   sei();
        
   while (1) 
   {
      DispatchTask();
   }            
}

void InitUART (u16 baud)
{
   UBRRH = (u8)(baud>>8);                                                        
   UBRRL = (u8)baud;
   UCSRB = (1<<RXEN)|(1<<TXEN);              
   UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
//hier ist noch der Recieveinterrupt zu aktivieren
}



void InitScheduler (void)
{
   u8 i;
   
   // timer prescaler clock/1024
   TCCR0 |= (1<<CS02)|(1<<CS00);
   // clear pending interrupts
   TIFR = 1<<TOV0;
   // enable timer0 overflow interrupt
   TIMSK |= 1<<TOIE0;
    // load timer0
   TCNT0 = StartFrom;

   // clear task array
   for (i=0; i<MAXnTASKS; i++) DeleteTask(i);
}

void DeleteTask (u8 j)
{
   TaskArray[j].pfunc = 0x0000;
   TaskArray[j].delay = 0;
   TaskArray[j].period = 0;
   TaskArray[j].run = 0;
}

void AddTask (void (*taskfunc)(void), u16 taskdelay, u16 taskperiod)
{
   u8 n=0;

   // find next available position
   while ((TaskArray[n].pfunc != 0) && (n < MAXnTASKS)) n++;

   // place task
   if (n < MAXnTASKS)
   {
      TaskArray[n].pfunc = taskfunc;
      TaskArray[n].delay = taskdelay;
      TaskArray[n].period = taskperiod;
      TaskArray[n].run = 0;   
   }
}

SIGNAL(SIG_OVERFLOW0)
{
   u8 m;

  
   
   // load timer
   TCNT0 = StartFrom;
   
   for (m=0; m<MAXnTASKS; m++)
   {
      if (TaskArray[m].pfunc)
      {   
         if (TaskArray[m].delay == 0) 
         {
            TaskArray[m].run = 1;
            TaskArray[m].delay = TaskArray[m].period;
         }
         else TaskArray[m].delay--;
      }
   }
}
ISR(USART_RECv_vect)
{
USART.empfangen=1;
USART.wert=UDR;
}
void DispatchTask (void)
{
   u8 k;
   
   for (k=0; k<MAXnTASKS; k++)
   {
      if (TaskArray[k].run == 1)
      {
         // run task
         (*TaskArray[k].pfunc)();
         // clear run flag
         TaskArray[k].run = 0;
      }
   }

}

void TestA (void)
{
   
}

void TestB (void)
{
   
}

void TestC (void)
{
  //Abfrage, ob was Empfangen

if(USART.empfangen){
// hier geschieht die Verarbeitung


//Ende der Verarbeitung
USART.empfangen=0;
}
}


mfg

PS: Freu mich auf die Antworten

Autor: Knut Ballhause (Firma: TravelRec.) (travelrec) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn der Timerinterrupt absolut zeitkritisch ist und nicht verzögert 
werden darf, polle die UART. Wenn dem nicht so ist, nimm den Interrupt. 
Es gibt keine allgemeingültige Formel für den Ablauf eines Programms.

Autor: Martin Vogel (oldmax)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi
ich finde den Weg, (trotz keiner allgemein gültigen Formel) den UART 
Empfang per ISR zu händeln, völlig richtig. Es geht auch nix verloren, 
wenn der empfangene Wert in einen Ringpuffer eingetragen wird. Wenn der 
Timer nicht grad im µS-bereich liegt, dürfte er höchstens mal kurz 
holpern, aber er dürfte nicht verloren gehen. Ist aber ein wenig 
abhängig von der Taktfrequenz.
Gruß oldmax

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.