USART_Polling_oder_Interrupt

Gast #1614826
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.
1
/// Includes //////////
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4

5
/// Data Types /////////
6
typedef unsigned char u8;
7
typedef unsigned int u16;
8
typedef struct task
9
{
10
   // pointer to a function
11
   void (*pfunc) (void);
12
   // delay before the first call
13
   u16 delay;
14
   // interval between subsequent runs
15
   u16 period;
16
   // flag indicating time to run
17
   u8 run;
18
}task;
19

20
struct USART
21
{ unsigned char empfangen;
22
unsigned char wert;
23
}
24

25
/// Defines ///////////
26
// 25msec period 256-180 
27
// 7.3728MHz and /1024 prescaler
28
#define StartFrom       76
29
// maximum number of tasks
30
#define MAXnTASKS       20
31

32
/// Globals ///////////
33
volatile task TaskArray[MAXnTASKS];
34

35
/// Prototypes ////////
36
void InitUART (u16 baud);
37
void TransmitByte (u8 data);
38
void InitScheduler (void);
39
void UpdateScheduler(void);
40
void DeleteTask (u8 index);
41
void AddTask (void (*taskfunc)(void), u16 taskdelay, u16 taskperiod);
42
void DispatchTask (void);
43

44
void TestA (void);
45
void TestB (void);
46
void TestC (void);
47

48
/// Main //////////////
49
int main(void)
50
{
51
   InitUART (23);
52
   InitScheduler();
53
        
54
   // populate task array       
55
   AddTask (TestA, 0, 3);
56
   AddTask (TestB, 1, 4);
57
   AddTask (TestC, 4, 0);
58
        
59
   // enable interrupts
60
   sei();
61
        
62
   while (1) 
63
   {
64
      DispatchTask();
65
   }            
66
}
67

68
void InitUART (u16 baud)
69
{
70
   UBRRH = (u8)(baud>>8);                                                        
71
   UBRRL = (u8)baud;
72
   UCSRB = (1<<RXEN)|(1<<TXEN);              
73
   UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
74
//hier ist noch der Recieveinterrupt zu aktivieren
75
}
76

77

78

79
void InitScheduler (void)
80
{
81
   u8 i;
82
   
83
   // timer prescaler clock/1024
84
   TCCR0 |= (1<<CS02)|(1<<CS00);
85
   // clear pending interrupts
86
   TIFR = 1<<TOV0;
87
   // enable timer0 overflow interrupt
88
   TIMSK |= 1<<TOIE0;
89
    // load timer0
90
   TCNT0 = StartFrom;
91

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

96
void DeleteTask (u8 j)
97
{
98
   TaskArray[j].pfunc = 0x0000;
99
   TaskArray[j].delay = 0;
100
   TaskArray[j].period = 0;
101
   TaskArray[j].run = 0;
102
}
103

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

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

111
   // place task
112
   if (n < MAXnTASKS)
113
   {
114
      TaskArray[n].pfunc = taskfunc;
115
      TaskArray[n].delay = taskdelay;
116
      TaskArray[n].period = taskperiod;
117
      TaskArray[n].run = 0;   
118
   }
119
}
120

121
SIGNAL(SIG_OVERFLOW0)
122
{
123
   u8 m;
124

125
  
126
   
127
   // load timer
128
   TCNT0 = StartFrom;
129
   
130
   for (m=0; m<MAXnTASKS; m++)
131
   {
132
      if (TaskArray[m].pfunc)
133
      {   
134
         if (TaskArray[m].delay == 0) 
135
         {
136
            TaskArray[m].run = 1;
137
            TaskArray[m].delay = TaskArray[m].period;
138
         }
139
         else TaskArray[m].delay--;
140
      }
141
   }
142
}
143
ISR(USART_RECv_vect)
144
{
145
USART.empfangen=1;
146
USART.wert=UDR;
147
}
148
void DispatchTask (void)
149
{
150
   u8 k;
151
   
152
   for (k=0; k<MAXnTASKS; k++)
153
   {
154
      if (TaskArray[k].run == 1)
155
      {
156
         // run task
157
         (*TaskArray[k].pfunc)();
158
         // clear run flag
159
         TaskArray[k].run = 0;
160
      }
161
   }
162

163
}
164

165
void TestA (void)
166
{
167
   
168
}
169

170
void TestB (void)
171
{
172
   
173
}
174

175
void TestC (void)
176
{
177
  //Abfrage, ob was Empfangen
178

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

182

183
//Ende der Verarbeitung
184
USART.empfangen=0;
185
}
186
}


mfg

PS: Freu mich auf die Antworten
#1616461
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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren