Forum: Mikrocontroller und Digitale Elektronik AVR Timer 1 Interrupt und UART Interrupt stören sich?


von Frank G. (dg1sbg)


Angehängte Dateien:

Lesenswert?

Hallo zusammen und guten Morgen,

nach nun einem Wochenende mit vergebenem Debuggen hier nochmal eine 
Frage zu UART per Interrupt und regelmäßigem Abarbeiten einer Funktion 
per Timer 1 im CTC Mode.

(Umgebung: ATMega32 8 MHz, AVR-GCC 4.3.2, AVR-Libc 1.6.4)

Folgende kleine Routine wird durch den Timer 1 aufgerufen:
1
ISR( TIMER1_COMPA_vect  )    // ISR triggered by Timer 1 to
2
{                                           // interact with the user via DARC.
3
4
  heart_beat();                        // Blink heartbeat LED.
5
6
  darc_get_command();           // Receive cmd via DARC channel. Will set
7
                                             // a flag if complete cmd received.
8
}

Die Funktion heart_beart() toggelt eine LED an Port B. In 
darc_get_command() wird geprüft, ob per UART (ebenso 
Interrupt-gesteuert) ein String empfangen wurde. Wenn ja, wird ein Flag 
gesetzt. Die Funktion nutzt die UART Lib von Peter Fleury. Sollte kein 
Zeichen anstehen, so springt die Routine sofort wieder zurück.

Die Routine wird ausgeführt - soviel verrät mit die Heartbeat LED.

In main() wird nun geprüft, ob das Flag gesetzt ist. Also 
"Standard-Vorgehen".
- Der ganze Code ist anbei ...

Ich habe auch einen Screenshot der Terminalausgabe beigefügt. Diese 
sieht so aus:
1
EVENT BOOT DEVICE=P1025A ID=801.
2
EVENT STATUS-CHANGE STATUS=BOOT.
3
OK.
4
HELLO, DEAR !
5
FAIL.
6
OK.
7
GOODBYE ...
8
9
EVENT BOOT DEVICE=P1025A ID=

Die Zeilen bis einschließlich "GOODBYE ..." zeigen den normalen Ablauf, 
wie ich ihn gerne hätte. Dies erreiche ich aber nur, wenn ich den Timer 
1 NICHT INITIALISIERE ...

Meine init_io_timer()-Funktion:
1
void init_io_timer ( void )
2
{
3
  double   nTickInterval;
4
  double   nDesiredTimerInterval;
5
  uint16_t nPrescalerValue;
6
7
  uint8_t  nTmpSREG = SREG;      // Save status 
8
 
9
  // We use timer 1 (16 bit Timer) in CTC mode. This timer shall 
10
  // generate an interrupt every PSU_IO_UPDATE_INTERVAL seconds.
11
  // Prescaler has to be set to 1 !
12
13
  cli();                         // Ensure atomic execution
14
15
  nTickInterval               = 0.0;   // [s]
16
  nDesiredTimerInterval = PSU_IO_UPDATE_INTERVAL;
17
  nPrescalerValue           = PSU_IO_TIMER_PRESCALER_VALUE;
18
19
  nTickInterval   = 1 / F_CPU * nPrescalerValue;
20
  nTimerLoadValue = nDesiredTimerInterval / nTickInterval - 1; 
21
    
22
  OCR1A  = nTimerLoadValue;      // Load the timer compare value
23
  
24
  TCNT1  = 0;                              // Reset counter value
25
  TCCR1A = 0;                             // No PWM
26
  TIMSK  |= _BV( OCIE1A );            // Output Compare A Interrupt: enable it
27
  TCCR1B |= _BV( WGM12 );          // Set CTC mode
28
  
29
  TCCR1B &= ~( _BV( CS12 ));        // Set prescaler to 1
30
  TCCR1B &= ~( _BV( CS11 ));        // and start timer.
31
  TCCR1B |= _BV( CS10 );         
32
33
  SREG = nTmpSREG;                   // Done - so interrupts ok now
34
}

Wie in der Ausgabe zu sehen ist, stoppt die Ausgabe nach "ID=". Danach 
kommt kein Zeichen mehr am Terminal an und ich kann auch kein Zeichen 
mehr per UART empfangen ...

Führe ich die Funktion darc_get_command() in der while-Schleife in 
main() aus, dann klappt die Sache wunderbar ...

Was ist mir hier mal wieder entgangen ???

Viele, vielen herzlichen Dank im Voraus !!!

Grüße,
   Frank

von Frank G. (dg1sbg)


Lesenswert?

Erledigt ! Fehler gefunden! ( War eine falsche Initalisierung des Timer 
1).

Dieser Beitrag hat mir gezeigt, wie's richtig geht:

Beitrag "Re: Timerprobleme"

Vielen Dank!

Gruß,
  Frank

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.