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