PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : ISR für TIMER0 und TIMER1 laufen nicht zusammen



PhilSU
09.11.2012, 20:43
Hallo Zusammen : )

Ich arbeite gerade an einem größeren Projekt, in der ich 2 Timer benötige. Timer1 für einen Sekundenzähler, Timer0 zum Tastenentprellen. Dabei ist mir aufgefallen, dass die beiden ISR nicht zusammen laufen.
Zu Testzwecken habe ich mal ein kleines Programm zum Timer-Test gemacht, in der lediglich Variablen hochgezählt werden sollen um dann auf einem Display ausgegeben zu werden. Es handelt sich um einen ATmega64 mit 16MHz.
Die ISR(TIMER0_OVF_vect) läuft nur, wenn das Compare Interrupt Enable Flag von Timer1 deaktiviert ist. Setze ich TIMSK |= (1<<OCIE1A) geht nur die ISR(TIMER1_COMPA_vect). Er zählt nie beide Variablen auf dem Display hoch. Je nach OCIE1A-Bit die eine oder die andere. Es scheint als würden die sich gegenseitig blockieren.

Weiß jemand Rat?


#include <stdint.h> // Standard data types
#include "dogm.h" // Routinen für das DOGM LCD Module
#include <avr/pgmspace.h> // PROGMEM
#include <avr/eeprom.h> // EEPROM
#include <stdlib.h>
#include <stdio.h> // sprintf
#include <inttypes.h>
#include <util/delay.h>
#include <avr/io.h> //I/O Ports
#include <avr/interrupt.h>

//Port und Pinnummer für LEDs:
#define LED1_OFF (PORTG&=~(1<<PG0))
#define LED1_ON (PORTG|=(1<<PG0))

#define LED2_OFF (PORTG&=~(1<<PG1))
#define LED2_ON (PORTG|=(1<<PG1))

#define LED3_OFF (PORTG&=~(1<<PG2))
#define LED3_ON (PORTG|=(1<<PG2))

#define LED4_OFF (PORTG&=~(1<<PG3))
#define LED4_ON (PORTG|=(1<<PG3))

#define LED5_OFF (PORTG&=~(1<<PG4))
#define LED5_ON (PORTG|=(1<<PG4))

static volatile uint8_t DELAY_1 = 0;
static volatile uint8_t DELAY_2 = 0;

// ************************************************** **********
// D E L A Y _ T I M E R S
// ************************************************** **********
ISR(TIMER1_COMPA_vect)
{
char cSREG;
cSREG = SREG;

DELAY_1++;
PORTG ^= ( 1 << PG4 ); //LED5 Blinken

SREG = cSREG;
}


ISR(TIMER0_OVF_vect)
{
char cSREG;
cSREG = SREG;

DELAY_2++;
PORTG ^= ( 1 << PG3 ); //LED5 Blinken

SREG = cSREG;
}

// ************************************************** **********
// M A I N
// ************************************************** **********
int main(void)
{
//Ausgänge
DDRG = 0x1F; //PORTG als Ausgang (LED1-5)

dogm_init(); //Initialisierung DOGM

//Timer1 16Bit
TCCR1B |= (1 << WGM12); //CTC Modus (Mode 4)
TCCR1B |= (1 << CS12) | (1 << CS10); //Prescaler 1024
TCCR1B&=~(1<<CS11);
OCR1A = 15624; //Output Compare: OCR = (Sekunden * FCPU/Prescaler) -1
TIMSK |= (1<<OCIE1A); //<<<<<------ Sobald ich den Interrupt disable funktioniert die ISR des Timer0, ist es enabled, get nur die ISR Timer1

//Timer0 8Bit
TCCR0 |= (1<<CS02)|(1<<CS00); //Prescaler 256 -> t = (2^8 *1024)/16MHz = 4,1ms
TIMSK |= (1<<TOIE0); //Enable timer interrupt



//Für die Ausgabe am DIsplay
char DELAY_CHAR_1[6];
char DELAY_CHAR_2[6];

sei(); //Interrupts aktivieren

while(1)
{
dogm_clear();

//Ausgabe DELAY
dogm_gotoxy(0,1);
itoa (DELAY_1,DELAY_CHAR_1,10);
dogm_puts(DELAY_CHAR_1);

dogm_gotoxy(6,1);
itoa (DELAY_2,DELAY_CHAR_2,10);
dogm_puts(DELAY_CHAR_2);

LED3_ON;
_delay_ms(50);
LED3_OFF;
}
}

markusj
09.11.2012, 21:59
Die Zeile mit TCCR0 &=~ ist etwas kaputt, da fehlt noch der Teil bis zum Semikolon. Sonst fällt mir gerade nichts auf.

Zu deinen Interrupts: Du musst das I-Bit im SREG nicht löschen, das wird beim Eintritt in die ISR automatisch gemacht und mit Verlassen der ISR wieder eingeschaltet.

mfG
Markus

PhilSU
10.11.2012, 08:34
Vielen Dank fürs anschauen!
Das war noch ein altes Codefragment vom Testen. Habe das zusammen mit dem cli mal entfernt. Ich habe mittlerweile rausgefunden woran es lag. Sobald ich nach jeder Veränderung des OCIE1A-Bits das TOIE0-Bit neu setze geht es nun. Die Frage ist nur wieso dieses Bit mit verändert wird wenn ich OCIE1A setze oder lösche???

markusj
10.11.2012, 09:32
Auch in deiner geänderten Fassung sicherst du immer noch unnötig das SREG. Das wird vom Compiler automatisch gemacht.

Zum eigentlichen Problem: Das fühlt sich etwas an, als ob irgendwo anstelle eines |= ein = steht. Damit überschreibt die Operation das TIMSK-Register und alle anderen Bits werden auf Null gesetzt. In deinem Codeschnipsel kann ich das aber nicht finden. Alternativ wäre es interessant, sich anzusehen was der Compiler da erzeugt (insbesondere die .lst-Datei). Gleichwohl sind Compilerfehler eigentlich selten ...

mfG
Markus